1 2/* 3 * Copyright (c) 1998-2007 Apple Computer, Inc. All rights reserved. 4 * 5 * @APPLE_LICENSE_HEADER_START@ 6 * 7 * The contents of this file constitute Original Code as defined in and 8 * are subject to the Apple Public Source License Version 1.1 (the 9 * "License"). You may not use this file except in compliance with the 10 * License. Please obtain a copy of the License at 11 * http://www.apple.com/publicsource and read it before using this file. 12 * 13 * This Original Code and all software distributed under the License are 14 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 18 * License for the specific language governing rights and limitations 19 * under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24// public 25#import <IOKit/firewire/IOFireWireLib.h> 26 27// private 28#include "IOFireWireLibPHYPacketListener.h" 29#include "IOFireWireLibCommand.h" 30#import "IOFireWireLibDevice.h" 31#import "IOFireWireLibPriv.h" 32 33namespace IOFireWireLib 34{ 35 36 IOFireWireLibPHYPacketListenerInterface PHYPacketListener::sInterface = 37 { 38 INTERFACEIMP_INTERFACE, 39 1, 1, // version/revision 40 41 &PHYPacketListener::SSetListenerCallback, 42 &PHYPacketListener::SSetSkippedPacketCallback, 43 &PHYPacketListener::SNotificationIsOn, 44 &PHYPacketListener::STurnOnNotification, 45 &PHYPacketListener::STurnOffNotification, 46 &PHYPacketListener::SClientCommandIsComplete, 47 &PHYPacketListener::SSetRefCon, 48 &PHYPacketListener::SGetRefCon, 49 &PHYPacketListener::SSetFlags, 50 &PHYPacketListener::SGetFlags 51 }; 52 53 // Alloc 54 // 55 // 56 57 IUnknownVTbl** PHYPacketListener::Alloc( Device& userclient, UInt32 queue_count ) 58 { 59 PHYPacketListener * me = new PHYPacketListener( userclient, queue_count ); 60 if( !me ) 61 return nil; 62 63 return reinterpret_cast<IUnknownVTbl**>(&me->GetInterface()); 64 } 65 66 // PHYPacketListener 67 // 68 // 69 70 PHYPacketListener::PHYPacketListener( Device & userClient, UInt32 queue_count ) 71 : IOFireWireIUnknown( reinterpret_cast<const IUnknownVTbl &>( sInterface ) ), 72 mUserClient( userClient ), 73 mKernelRef( 0 ), 74 mQueueCount( queue_count ), 75 mRefCon( NULL ), 76 mCallback( NULL ), 77 mSkippedCallback( NULL ), 78 mFlags( 0 ), 79 mNotifyIsOn( false ) 80 { 81 mUserClient.AddRef(); 82 83 // input data 84 const uint64_t inputs[1]={ (const uint64_t)mQueueCount }; 85 86 // output data 87 uint64_t kernel_ref = 0; 88 uint32_t outputCnt = 1; 89 90 // send it down 91 IOReturn status = IOConnectCallScalarMethod( mUserClient.GetUserClientConnection(), 92 kPHYPacketListenerCreate, 93 inputs, 1, 94 &kernel_ref, &outputCnt ); 95 if( status != kIOReturnSuccess ) 96 { 97 throw status; 98 } 99 100 mKernelRef = kernel_ref; 101 } 102 103 // ~PHYPacketListener 104 // 105 // 106 107 PHYPacketListener::~PHYPacketListener() 108 { 109 if( mKernelRef ) 110 { 111 IOReturn result = kIOReturnSuccess; 112 113 uint32_t outputCnt = 0; 114 const uint64_t inputs[1]={ (const uint64_t)mKernelRef }; 115 result = IOConnectCallScalarMethod( mUserClient.GetUserClientConnection(), 116 kReleaseUserObject, 117 inputs, 1, 118 NULL, &outputCnt); 119 120 DebugLogCond( result, "VectorCommand::~VectorCommand: command release returned 0x%08x\n", result ); 121 } 122 123 mUserClient.Release(); 124 } 125 126 // QueryInterface 127 // 128 // 129 130 HRESULT 131 PHYPacketListener::QueryInterface( REFIID iid, LPVOID* ppv ) 132 { 133 HRESULT result = S_OK; 134 *ppv = nil; 135 136 CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes( kCFAllocatorDefault, iid ); 137 138 if( CFEqual(interfaceID, IUnknownUUID) || CFEqual(interfaceID, kIOFireWirePHYPacketListenerInterfaceID) ) 139 { 140 *ppv = &GetInterface(); 141 AddRef(); 142 } 143 else 144 { 145 *ppv = nil; 146 result = E_NOINTERFACE; 147 } 148 149 CFRelease( interfaceID ); 150 return result; 151 } 152 153 //////////////////////////////////////////////////////////////////////// 154 #pragma mark - 155 156 // SetRefCon 157 // 158 // 159 160 void PHYPacketListener::SSetRefCon( IOFireWireLibPHYPacketListenerRef self, void* refCon ) 161 { 162 PHYPacketListener * me = IOFireWireIUnknown::InterfaceMap<PHYPacketListener>::GetThis(self); 163 me->mRefCon = refCon; 164 } 165 166 // GetRefCon 167 // 168 // 169 170 void * PHYPacketListener::SGetRefCon( IOFireWireLibPHYPacketListenerRef self ) 171 { 172 PHYPacketListener * me = IOFireWireIUnknown::InterfaceMap<PHYPacketListener>::GetThis(self); 173 return me->mRefCon; 174 } 175 176 // SetListenerCallback 177 // 178 // 179 180 void PHYPacketListener::SSetListenerCallback( IOFireWireLibPHYPacketListenerRef self, 181 IOFireWireLibPHYPacketCallback inCallback ) 182 { 183 PHYPacketListener * me = IOFireWireIUnknown::InterfaceMap<PHYPacketListener>::GetThis(self); 184 me->mCallback = inCallback; 185 } 186 187 // SetSkippedPacketCallback 188 // 189 // 190 191 void PHYPacketListener::SSetSkippedPacketCallback( IOFireWireLibPHYPacketListenerRef self, 192 IOFireWireLibPHYPacketSkippedCallback inCallback ) 193 { 194 PHYPacketListener * me = IOFireWireIUnknown::InterfaceMap<PHYPacketListener>::GetThis(self); 195 me->mSkippedCallback = inCallback; 196 } 197 198 // NotificationIsOn 199 // 200 // 201 202 Boolean PHYPacketListener::SNotificationIsOn( IOFireWireLibPHYPacketListenerRef self ) 203 { 204 PHYPacketListener * me = IOFireWireIUnknown::InterfaceMap<PHYPacketListener>::GetThis(self); 205 return me->mNotifyIsOn; 206 } 207 208 // TurnOnNotification 209 // 210 // 211 212 IOReturn PHYPacketListener::STurnOnNotification( IOFireWireLibPHYPacketListenerRef self ) 213 { 214 PHYPacketListener * me = IOFireWireIUnknown::InterfaceMap<PHYPacketListener>::GetThis(self); 215 return me->TurnOnNotification( self ); 216 } 217 218 IOReturn PHYPacketListener::TurnOnNotification( IOFireWireLibPHYPacketListenerRef self ) 219 { 220 IOReturn status = kIOReturnSuccess; 221 222 if( mNotifyIsOn ) 223 status = kIOReturnNotPermitted; 224 225 io_connect_t connection = NULL; 226 if( status == kIOReturnSuccess ) 227 { 228 connection = mUserClient.GetUserClientConnection(); 229 if( connection == 0 ) 230 { 231 status = kIOReturnNoDevice; 232 } 233 } 234 235 if( status == kIOReturnSuccess ) 236 { 237 uint64_t refrncData[kOSAsyncRef64Count]; 238 refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t) 0; 239 refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long) 0; 240 const uint64_t inputs[2] = { 241 (const uint64_t)&SListenerCallback, 242 (const uint64_t)self 243 }; 244 uint32_t outputCnt = 0; 245 status = IOConnectCallAsyncScalarMethod( connection, 246 mUserClient.MakeSelectorWithObject( kPHYPacketListenerSetPacketCallback, mKernelRef ), 247 mUserClient.GetAsyncPort(), 248 refrncData, kOSAsyncRef64Count, 249 inputs, 2, 250 NULL, &outputCnt); 251 } 252 253 if( status == kIOReturnSuccess ) 254 { 255 uint64_t refrncData[kOSAsyncRef64Count]; 256 refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t) 0; 257 refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long) 0; 258 const uint64_t inputs[2] = { 259 (const uint64_t)&SSkippedCallback, 260 (const uint64_t)self 261 }; 262 uint32_t outputCnt = 0; 263 status = IOConnectCallAsyncScalarMethod( connection, 264 mUserClient.MakeSelectorWithObject( kPHYPacketListenerSetSkippedCallback, mKernelRef ), 265 mUserClient.GetAsyncPort(), 266 refrncData, kOSAsyncRef64Count, 267 inputs, 2, 268 NULL, &outputCnt); 269 } 270 271 if( status == kIOReturnSuccess ) 272 { 273 uint32_t outputCnt = 0; 274 status = IOConnectCallScalarMethod( connection, 275 mUserClient.MakeSelectorWithObject( kPHYPacketListenerActivate, mKernelRef ), 276 NULL, 0, 277 NULL, &outputCnt ); 278 } 279 280 281 if( status == kIOReturnSuccess ) 282 { 283 mNotifyIsOn = true; 284 } 285 286 return status; 287 } 288 289 // TurnOffNotification 290 // 291 // 292 293 void PHYPacketListener::STurnOffNotification( IOFireWireLibPHYPacketListenerRef self ) 294 { 295 PHYPacketListener * me = IOFireWireIUnknown::InterfaceMap<PHYPacketListener>::GetThis(self); 296 me->TurnOffNotification( self ); 297 } 298 299 void PHYPacketListener::TurnOffNotification( IOFireWireLibPHYPacketListenerRef self ) 300 { 301 IOReturn status = kIOReturnSuccess; 302 303 if( !mNotifyIsOn ) 304 status = kIOReturnNotPermitted; 305 306 io_connect_t connection = NULL; 307 if( status == kIOReturnSuccess ) 308 { 309 connection = mUserClient.GetUserClientConnection(); 310 if( connection == 0 ) 311 { 312 status = kIOReturnNoDevice; 313 } 314 } 315 316 if( status == kIOReturnSuccess ) 317 { 318 uint64_t refrncData[kOSAsyncRef64Count]; 319 refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t) 0; 320 refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long) 0; 321 const uint64_t inputs[2] = { 322 (const uint64_t)0, 323 (const uint64_t)self 324 }; 325 uint32_t outputCnt = 0; 326 status = IOConnectCallAsyncScalarMethod( connection, 327 mUserClient.MakeSelectorWithObject( kPHYPacketListenerSetPacketCallback, mKernelRef ), 328 mUserClient.GetAsyncPort(), 329 refrncData, kOSAsyncRef64Count, 330 inputs, 2, 331 NULL, &outputCnt); 332 } 333 334 if( status == kIOReturnSuccess ) 335 { 336 uint64_t refrncData[kOSAsyncRef64Count]; 337 refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t) 0; 338 refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long) 0; 339 const uint64_t inputs[2] = { 340 (const uint64_t)0, 341 (const uint64_t)self 342 }; 343 uint32_t outputCnt = 0; 344 status = IOConnectCallAsyncScalarMethod( connection, 345 mUserClient.MakeSelectorWithObject( kPHYPacketListenerSetSkippedCallback, mKernelRef ), 346 mUserClient.GetAsyncPort(), 347 refrncData, kOSAsyncRef64Count, 348 inputs, 2, 349 NULL, &outputCnt); 350 } 351 352 if( status == kIOReturnSuccess ) 353 { 354 uint32_t outputCnt = 0; 355 status = IOConnectCallScalarMethod( connection, 356 mUserClient.MakeSelectorWithObject( kPHYPacketListenerDeactivate, mKernelRef ), 357 NULL, 0, 358 NULL, &outputCnt ); 359 } 360 361 mNotifyIsOn = false; 362 } 363 364 // ClientCommandIsComplete 365 // 366 // 367 368 void PHYPacketListener::SClientCommandIsComplete( IOFireWireLibPHYPacketListenerRef self, 369 FWClientCommandID commandID ) 370 { 371 PHYPacketListener * me = IOFireWireIUnknown::InterfaceMap<PHYPacketListener>::GetThis(self); 372 373 uint32_t outputCnt = 0; 374 const uint64_t inputs[2] = { 375 (const uint64_t)commandID 376 }; 377 378 IOConnectCallScalarMethod( me->mUserClient.GetUserClientConnection(), 379 me->mUserClient.MakeSelectorWithObject( kPHYPacketListenerClientCommandIsComplete, me->mKernelRef ), 380 inputs, 1, 381 NULL, &outputCnt ); 382 } 383 384 // SetFlags 385 // 386 // 387 388 void PHYPacketListener::SSetFlags( IOFireWireLibPHYPacketListenerRef self, UInt32 inFlags ) 389 { 390 PHYPacketListener * me = IOFireWireIUnknown::InterfaceMap<PHYPacketListener>::GetThis(self); 391 me->mFlags = inFlags; 392 } 393 394 // GetFlags 395 // 396 // 397 398 UInt32 PHYPacketListener::SGetFlags( IOFireWireLibPHYPacketListenerRef self ) 399 { 400 PHYPacketListener * me = IOFireWireIUnknown::InterfaceMap<PHYPacketListener>::GetThis(self); 401 return me->mFlags; 402 } 403 404 // ListenerCallback 405 // 406 // 407 408 void PHYPacketListener::SListenerCallback( IOFireWireLibPHYPacketListenerRef self, IOReturn result, void ** args, int numArgs) 409 { 410 PHYPacketListener * me = IOFireWireIUnknown::InterfaceMap<PHYPacketListener>::GetThis(self); 411 412 if( me->mCallback ) 413 { 414 (me->mCallback)( 415 self, 416 (FWClientCommandID)args[0], // commandID, 417 (unsigned long)args[1], // data1 418 (unsigned long)args[2], // data2 419 (void*) me->mRefCon); // refcon 420 } 421 else 422 { 423 me->SClientCommandIsComplete( self, args[0] ); 424 } 425 426 } 427 428 // SkippedPacket 429 // 430 // 431 432 void PHYPacketListener::SSkippedCallback( IOFireWireLibPHYPacketListenerRef self, IOReturn result, void ** args, int numArgs ) 433 { 434 PHYPacketListener * me = IOFireWireIUnknown::InterfaceMap<PHYPacketListener>::GetThis(self); 435 436 // printf( "PHYPacketListener::SSkippedCallback - arg0 0x%08lx arg1 0x%08lx\n", args[0], args[1] ); 437 438 if( me->mSkippedCallback ) 439 { 440 (me->mSkippedCallback)( self, 441 (FWClientCommandID)args[0], // commandID, 442 (unsigned long)args[1], // count, 443 (void*)me->mRefCon ); // refcon 444 } 445 else 446 { 447 me->SClientCommandIsComplete( self, (FWClientCommandID)args[0] ); 448 } 449 } 450} 451