1/* 2 * Copyright (c) 1998-2001 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 23#include <stdlib.h> 24#include <stdio.h> 25#include <CoreFoundation/CoreFoundation.h> 26 27#include <IOKit/avc/IOFireWireAVCLib.h> 28#include "IOFireWireAVCUserClientCommon.h" 29#include <IOKit/avc/IOFireWireAVCConsts.h> 30 31#include <mach/mach_port.h> 32 33#import <System/libkern/OSCrossEndian.h> 34 35#include <syslog.h> // Debug messages 36 37__BEGIN_DECLS 38#include <IOKit/iokitmig.h> 39__END_DECLS 40 41#define FWLOG printf 42 43struct _AVCProtocol; 44typedef struct _InterfaceMap 45{ 46 IUnknownVTbl *pseudoVTable; 47 struct _AVCProtocol *obj; 48} InterfaceMap; 49 50typedef struct _AVCProtocol 51{ 52 53 ////////////////////////////////////// 54 // cf plugin interfaces 55 56 InterfaceMap fIOCFPlugInInterface; 57 InterfaceMap fIOFireWireAVCLibProtocolInterface; 58 59 ////////////////////////////////////// 60 // cf plugin ref counting 61 62 CFUUIDRef fFactoryId; 63 UInt32 fRefCount; 64 65 ////////////////////////////////////// 66 // user client connection 67 68 io_service_t fService; 69 io_connect_t fConnection; 70 71 ////////////////////////////////////// 72 // async callbacks 73 74 mach_port_t fAsyncPort; 75 CFRunLoopRef fCFRunLoop; 76 CFRunLoopSourceRef fCFRunLoopSource; 77 CFMachPortRef fCFAsyncPort; 78 IONotificationPortRef fNotifyPort; 79 io_object_t fNotification; 80 IOFWAVCMessageCallback fMessageCallbackRoutine; 81 void * fMessageCallbackRefCon; 82 83 ////////////////////////////////////// 84 // Lump 'o stuff for handling AVC requests 85 IOFWAVCRequestCallback fAVCRequestCallbackRoutine; 86 void * fAVCRequestCallbackRefCon; 87 88 UInt32 fCmdLen; 89 UInt32 fCmdGeneration; 90 UInt32 fCmdSource; 91 UInt8 fCommand[512]; 92 IOFWAVCCommandHandlerCallback userCallBack; 93 void *userRefCon; 94 IOFWSpeed speed; 95 UInt32 handlerSearchIndex; 96} AVCProtocol; 97 98 // utility function to get "this" pointer from interface 99#define getThis( self ) \ 100 (((InterfaceMap *) self)->obj) 101 102static IOReturn stop( void * self ); 103static void removeIODispatcherFromRunLoop( void * self ); 104static IOReturn sendAVCResponse(void *self, 105 UInt32 generation, 106 UInt16 nodeID, 107 const char *response, 108 UInt32 responseLen); 109IOReturn setSubunitPlugSignalFormat(void *self, 110 UInt32 subunitTypeAndID, 111 IOFWAVCPlugTypes plugType, 112 UInt32 plugNum, 113 UInt32 signalFormat); 114 115////////////////////////////////////////////////////////////////// 116// callback static methods 117// 118 119// messageCallback 120// 121// 122 123static void messageCallback(void * refcon, io_service_t service, 124 natural_t messageType, void *messageArgument) 125{ 126 //printf("DEBUG: AVCProtocol::messageCallback\n"); 127 128 AVCProtocol *me = (AVCProtocol *)refcon; 129 130 if( me->fMessageCallbackRoutine != NULL ) 131 (me->fMessageCallbackRoutine)( me->fMessageCallbackRefCon, messageType, messageArgument ); 132} 133 134static void avcCommandHandlerCallback( void *refcon, IOReturn result, io_user_reference_t *args, int numArgs) 135{ 136 AVCProtocol *me = (AVCProtocol *)refcon; 137 UInt32 pos; 138 UInt32 len; 139 const UInt8* src; 140 UInt32 fixedArgs[kMaxAsyncArgs]; 141 UInt32 i; 142 uint64_t inArg[4]; 143 uint32_t outputScalarCnt = 0; 144 size_t outputStructSize = 0; 145 146 //printf("DEBUG: AVCProtocol::avcCommandHandlerCallback\n"); 147 148 // First copy all the args with endian byte-swapping. Note that only 149 // the args that contain command-bytes need this, but doing them all 150 // here simplifies the logic below. 151 IF_ROSETTA() 152 { 153 // Note: This code assumes ROSETTA only happens for in 32-bit mode! 154 for (i=0;i<numArgs;i++) 155 fixedArgs[i] = (OSSwapInt32(args[i]) & 0xFFFFFFFF); 156 } 157 else 158 { 159 for (i=0;i<numArgs;i++) 160 fixedArgs[i] = (args[i] & 0xFFFFFFFF); 161 } 162 163 pos = args[0] & 0xFFFFFFFF; 164 len = args[1] & 0xFFFFFFFF; 165 src = (const UInt8*)(fixedArgs+2); 166 if(pos == 0) 167 { 168 me->fCmdGeneration = args[2] & 0xFFFFFFFF; 169 me->fCmdSource = args[3] & 0xFFFFFFFF;; 170 me->fCmdLen = args[4] & 0xFFFFFFFF; 171 me->userCallBack = (IOFWAVCCommandHandlerCallback) ((unsigned long)args[5]); 172 me->userRefCon = (void*) ((unsigned long)args[6]); 173 me->speed = (IOFWSpeed) args[7] & 0xFFFFFFFF; 174 me->handlerSearchIndex = args[8] & 0xFFFFFFFF; 175 src = (const UInt8*)(fixedArgs+9); 176 } 177 178 bcopy(src, me->fCommand+pos, len); 179 if(pos+len == me->fCmdLen) 180 { 181 IOReturn status; 182 status = me->userCallBack(me->userRefCon, me->fCmdGeneration, me->fCmdSource, me->speed, me->fCommand , me->fCmdLen); 183 184 // See if application handled command or not 185 if (status != kIOReturnSuccess) 186 { 187 inArg[0] = me->fCmdGeneration; 188 inArg[1] = me->fCmdSource; 189 inArg[2] = me->speed; 190 inArg[3] = me->handlerSearchIndex; 191 192 // Pass this command back to the kernel to possibly 193 // find another handler, or to respond not implemented 194 IOConnectCallMethod(me->fConnection, 195 kIOFWAVCProtocolUserClientAVCRequestNotHandled, 196 inArg, 197 4, 198 me->fCommand, 199 me->fCmdLen, 200 NULL, 201 &outputScalarCnt, 202 NULL, 203 &outputStructSize); 204 } 205 } 206} 207 208static void subunitPlugHandlerCallback( void *refcon, IOReturn result, io_user_reference_t *args, int numArgs) 209{ 210 AVCProtocol *me = (AVCProtocol *)refcon; 211 IOFWAVCSubunitPlugHandlerCallback userCallBack; 212 void *userRefCon; 213 IOReturn status; 214 IOFWAVCSubunitPlugMessages plugMessage = (IOFWAVCSubunitPlugMessages)args[3]; 215 UInt32 generation = args[7] & 0xFFFFFFFF; 216 UInt32 nodeID = args[8] & 0xFFFFFFFF; 217 UInt8 response[8]; 218 IOFWAVCPlugTypes plugType = (IOFWAVCPlugTypes) args[1] & 0xFFFFFFFF; 219 UInt32 plugNum = args[2] & 0xFFFFFFFF; 220 UInt32 msgParams = args[4] & 0xFFFFFFFF; 221 UInt32 subunitTypeAndID = args[0] & 0xFFFFFFFF; 222 223 //printf("DEBUG: AVCProtocol::subunitPlugHandlerCallback\n"); 224 225 userCallBack = (IOFWAVCSubunitPlugHandlerCallback) ((unsigned long)args[5]); 226 userRefCon = (void*) ((unsigned long)args[6]); 227 228 // Callback the user 229 status = userCallBack(userRefCon,subunitTypeAndID,plugType,plugNum,plugMessage,msgParams); 230 231 // For the message kIOFWAVCSubunitPlugMsgSignalFormatModified 232 // send a response to the plug signal format control command 233 if (plugMessage == kIOFWAVCSubunitPlugMsgSignalFormatModified) 234 { 235 response[kAVCCommandResponse] = (status == kIOReturnSuccess) ? kAVCAcceptedStatus : kAVCRejectedStatus; 236 response[kAVCAddress] = kAVCUnitAddress; 237 response[kAVCOpcode] = (plugType == IOFWAVCPlugSubunitSourceType) ? kAVCOutputPlugSignalFormatOpcode : kAVCInputPlugSignalFormatOpcode; 238 response[kAVCOperand0] = plugNum; 239 response[kAVCOperand1] = ((msgParams & 0xFF000000) >> 24); 240 response[kAVCOperand2] = ((msgParams & 0x00FF0000) >> 16); 241 response[kAVCOperand3] = ((msgParams & 0x0000FF00) >> 8); 242 response[kAVCOperand4] = (msgParams & 0x000000FF); 243 244 sendAVCResponse(me,generation,(UInt16) nodeID,(const char *)response,8); 245 246 // If we accepted the control command, we need to set this 247 // signal format as the current signal format 248 if (status == kIOReturnSuccess) 249 setSubunitPlugSignalFormat(me,subunitTypeAndID,plugType,plugNum,msgParams); 250 } 251 return; 252} 253 254static void pcrWriteCallback( void *refcon, IOReturn result, io_user_reference_t *args, int numArgs) 255{ 256 IOFWAVCPCRCallback func; 257 258 //printf("DEBUG: AVCProtocol::pcrWriteCallback\n"); 259 260 func = (IOFWAVCPCRCallback) ((unsigned long)args[0]); 261 func(refcon, (UInt32)args[1], (UInt16)args[2], (UInt32)args[3], (UInt32)args[4], (UInt32)args[5]); 262} 263 264static UInt32 addRef( void * self ) 265{ 266 //printf("DEBUG: AVCProtocol::addRef\n"); 267 268 AVCProtocol *me = getThis(self); 269 me->fRefCount++; 270 return me->fRefCount; 271} 272 273static UInt32 release( void * self ) 274{ 275 AVCProtocol *me = getThis(self); 276 UInt32 retVal = me->fRefCount; 277 278 //printf("DEBUG: AVCProtocol::release\n"); 279 280 if( 1 == me->fRefCount-- ) 281 { 282 removeIODispatcherFromRunLoop(self); 283 stop(self); 284 CFPlugInRemoveInstanceForFactory( me->fFactoryId ); 285 CFRelease( me->fFactoryId ); 286 free(me); 287 } 288 else if( me->fRefCount < 0 ) 289 { 290 me->fRefCount = 0; 291 } 292 293 return retVal; 294} 295 296 297static HRESULT queryInterface( void * self, REFIID iid, void **ppv ) 298{ 299 CFUUIDRef uuid = CFUUIDCreateFromUUIDBytes(NULL, iid); 300 HRESULT result = S_OK; 301 AVCProtocol *me = getThis(self); 302 303 //printf("DEBUG: AVCProtocol::queryInterface\n"); 304 305 if( CFEqual(uuid, IUnknownUUID) || CFEqual(uuid, kIOCFPlugInInterfaceID) ) 306 { 307 *ppv = &me->fIOCFPlugInInterface; 308 addRef(self); 309 } 310 else if( CFEqual(uuid, kIOFireWireAVCLibProtocolInterfaceID) ) 311 { 312 *ppv = &me->fIOFireWireAVCLibProtocolInterface; 313 addRef(self); 314 } 315 else 316 *ppv = 0; 317 318 if( !*ppv ) 319 result = E_NOINTERFACE; 320 321 CFRelease( uuid ); 322 323 return result; 324} 325 326////////////////////////////////////////////////////////////////// 327// IOCFPlugInInterface methods 328// 329 330// probe 331// 332// 333 334static IOReturn probe( void * self, CFDictionaryRef propertyTable, 335 io_service_t service, SInt32 *order ) 336{ 337 338 //printf("DEBUG: AVCProtocol::probe\n"); 339 340 // only load against local FireWire node 341 if( !service || !IOObjectConformsTo(service, "IOFireWireLocalNode") ) 342 return kIOReturnBadArgument; 343 344 return kIOReturnSuccess; 345} 346 347// start 348// 349// 350 351static IOReturn start( void * self, CFDictionaryRef propertyTable, 352 io_service_t service ) 353{ 354 IOReturn status = kIOReturnSuccess; 355 CFNumberRef guidDesc = 0; 356 io_iterator_t enumerator = 0; 357 io_object_t device = 0; 358 mach_port_t masterDevicePort; 359 AVCProtocol *me = getThis(self); 360 CFMutableDictionaryRef dict; 361 CFMutableDictionaryRef dict2; 362 363 //printf("DEBUG: AVCProtocol::start\n"); 364 365 me->fService = service; 366 367 // Conjure up our user client 368 do { 369 dict = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, 370 &kCFTypeDictionaryKeyCallBacks, 371 &kCFTypeDictionaryValueCallBacks); 372 373 if(!dict) 374 continue; 375 dict2 = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, 376 &kCFTypeDictionaryKeyCallBacks, 377 &kCFTypeDictionaryValueCallBacks); 378 379 if(!dict2) 380 continue; 381 CFDictionarySetValue( dict2, CFSTR("IODesiredChild"), CFSTR("IOFireWireAVCProtocolUserClient") ); 382 CFDictionarySetValue( dict, CFSTR("SummonNub"), dict2 ); 383 384 status = IORegistryEntrySetCFProperties(service, dict ); 385 CFRelease( dict ); 386 CFRelease( dict2 ); 387 388 // Now find it - has same GUID as the IOFireWireLocalNode 389 guidDesc = (CFNumberRef)IORegistryEntryCreateCFProperty(service, CFSTR("GUID"), kCFAllocatorDefault, 0); 390 391 dict = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, 392 &kCFTypeDictionaryKeyCallBacks, 393 &kCFTypeDictionaryValueCallBacks); 394 395 if(!dict) 396 break; 397 398 CFDictionarySetValue( dict, CFSTR(kIOProviderClassKey), CFSTR("IOFireWireAVCProtocolUserClient")); 399 //CFDictionarySetValue( dict, CFSTR("GUID"), guidDesc); 400 // get mach master port 401 status = IOMasterPort(bootstrap_port, & masterDevicePort) ; 402 if ( status != kIOReturnSuccess ) { 403 break; 404 } 405 406 status = IOServiceGetMatchingServices( 407 masterDevicePort, 408 dict, 409 & enumerator ); 410 411 if( kIOReturnSuccess != status ) { 412 break; 413 } 414 415 // Find an unused user client 416 while(device = IOIteratorNext(enumerator)) { 417 status = IOServiceOpen( device, mach_task_self(), 418 kIOFireWireAVCLibConnection, &me->fConnection ); 419 IOObjectRelease(device); 420 if(kIOReturnSuccess == status) 421 break; 422 } 423 } while(0); 424 425 if(guidDesc) 426 CFRelease(guidDesc); 427 if (enumerator) 428 IOObjectRelease(enumerator) ; 429 430 if( !me->fConnection ) 431 status = kIOReturnNoDevice; 432 433 if( status == kIOReturnSuccess ) 434 { 435 status = IOCreateReceivePort( kOSAsyncCompleteMessageID, &me->fAsyncPort ); 436 } 437 438 return status; 439} 440 441// stop 442// 443// 444 445static IOReturn stop( void * self ) 446{ 447 AVCProtocol *me = getThis(self); 448 449 //printf("DEBUG: AVCProtocol::stop\n"); 450 451 if( me->fConnection ) 452 { 453 IOServiceClose( me->fConnection ); 454 me->fConnection = MACH_PORT_NULL; 455 } 456 457 if( me->fAsyncPort != MACH_PORT_NULL ) 458 { 459 mach_port_destroy( mach_task_self(), me->fAsyncPort); 460 me->fAsyncPort = MACH_PORT_NULL; 461 } 462 463 return kIOReturnSuccess; 464} 465 466////////////////////////////////////////////////////////////////// 467// IOFireWireAVCLibProtocol methods 468// 469 470// addIODispatcherToRunLoop 471// 472// 473 474static IOReturn addIODispatcherToRunLoop( void *self, CFRunLoopRef cfRunLoopRef ) 475{ 476 AVCProtocol *me = getThis(self); 477 IOReturn status = kIOReturnSuccess; 478 mach_port_t masterDevicePort; 479 IONotificationPortRef notifyPort; 480 CFRunLoopSourceRef cfSource; 481 482 //printf("DEBUG: AVCProtocol::addIODispatcherToRunLoop\n"); 483 484 if( !me->fConnection ) 485 return kIOReturnNoDevice; 486 487 // get mach master port 488 status = IOMasterPort(bootstrap_port, &masterDevicePort) ; 489 490 notifyPort = IONotificationPortCreate(masterDevicePort); 491 cfSource = IONotificationPortGetRunLoopSource(notifyPort); 492 CFRunLoopAddSource(cfRunLoopRef, cfSource, kCFRunLoopDefaultMode); 493// Get messages from device 494 status = IOServiceAddInterestNotification(notifyPort, me->fService, 495 kIOGeneralInterest, messageCallback, me, 496 &me->fNotification); 497 498 me->fCFRunLoop = cfRunLoopRef; 499 me->fNotifyPort = notifyPort; 500 501 502 if( status == kIOReturnSuccess ) 503 { 504 CFMachPortContext context; 505 Boolean shouldFreeInfo; // zzz what's this for? I think it's set to true if the create failed. 506 507 context.version = 1; 508 context.info = me; 509 context.retain = NULL; 510 context.release = NULL; 511 context.copyDescription = NULL; 512 513 me->fCFAsyncPort = CFMachPortCreateWithPort( kCFAllocatorDefault, me->fAsyncPort, 514 (CFMachPortCallBack) IODispatchCalloutFromMessage, 515 &context, &shouldFreeInfo ); 516 if( !me->fCFAsyncPort ) 517 status = kIOReturnNoMemory; 518 } 519 520 if( status == kIOReturnSuccess ) 521 { 522 me->fCFRunLoopSource = CFMachPortCreateRunLoopSource( kCFAllocatorDefault, me->fCFAsyncPort, 0 ); 523 if( !me->fCFRunLoopSource ) 524 status = kIOReturnNoMemory; 525 } 526 527 if( status == kIOReturnSuccess ) 528 { 529 CFRunLoopAddSource(cfRunLoopRef, me->fCFRunLoopSource, kCFRunLoopDefaultMode ); 530 } 531 532 return status; 533} 534 535// removeIODispatcherFromRunLoop 536// 537// 538 539static void removeIODispatcherFromRunLoop( void * self ) 540{ 541 AVCProtocol *me = getThis(self); 542 543 //printf("DEBUG: AVCProtocol::removeIODispatcherFromRunLoop\n"); 544 545 if( me->fNotification ) 546 { 547 IOObjectRelease(me->fNotification); 548 me->fNotification = (io_object_t)0; 549 } 550 if( me->fNotifyPort ) 551 { 552 CFRunLoopRemoveSource( me->fCFRunLoop, 553 IONotificationPortGetRunLoopSource(me->fNotifyPort), kCFRunLoopDefaultMode ); 554 IONotificationPortDestroy(me->fNotifyPort); 555 me->fNotifyPort = NULL; 556 } 557 558 if(me->fCFRunLoopSource) { 559 CFRunLoopRemoveSource( me->fCFRunLoop, 560 me->fCFRunLoopSource, kCFRunLoopDefaultMode ); 561 CFRelease(me->fCFRunLoopSource); 562 me->fCFRunLoopSource = NULL; 563 } 564 565 if( me->fCFAsyncPort != NULL ) { 566 CFMachPortInvalidate(me->fCFAsyncPort); 567 CFRelease( me->fCFAsyncPort ); 568 me->fCFAsyncPort = NULL; 569 } 570} 571 572// setMessageCallback 573// 574// 575 576static void setMessageCallback( void * self, void * refCon, 577 IOFWAVCMessageCallback callback ) 578{ 579 AVCProtocol *me = getThis(self); 580 581 //printf("DEBUG: AVCProtocol::setMessageCallback\n"); 582 583 me->fMessageCallbackRoutine = callback; 584 me->fMessageCallbackRefCon = refCon; 585} 586 587// setAVCRequestCallback 588// 589// 590 591static IOReturn setAVCRequestCallback( void *self, UInt32 subUnitType, UInt32 subUnitID, 592 void *refCon, IOFWAVCRequestCallback callback) 593{ 594 // This function has been deprecated! 595 return kIOReturnUnsupported; 596} 597 598static IOReturn allocateInputPlug( void *self, void *refcon, IOFWAVCPCRCallback func, UInt32 *plug) 599{ 600 AVCProtocol *me = getThis(self); 601 uint64_t params; 602 IOReturn status; 603 uint64_t refrncData[kOSAsyncRef64Count]; 604 uint32_t outputCnt = 1; 605 uint64_t returnVal; 606 607 //printf("DEBUG: AVCProtocol::allocateInputPlug\n"); 608 609 refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t)&pcrWriteCallback; 610 refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long)refcon; 611 params = (unsigned long)func; 612 const uint64_t inputs[1]={(const uint64_t)params}; 613 614 status = IOConnectCallAsyncScalarMethod(me->fConnection, 615 kIOFWAVCProtocolUserClientAllocateInputPlug, 616 me->fAsyncPort, 617 refrncData,kOSAsyncRef64Count, 618 inputs, 1, 619 &returnVal,&outputCnt); 620 *plug = returnVal & 0xFFFFFFFF; 621 622 return status; 623} 624 625static void freeInputPlug( void *self, UInt32 plug) 626{ 627 AVCProtocol *me = getThis(self); 628 uint32_t outputCnt = 0; 629 const uint64_t inArg = plug; 630 const uint64_t inputs[1]={(const uint64_t)inArg}; 631 632 633 //printf("DEBUG: AVCProtocol::freeInputPlug\n"); 634 635 IOConnectCallScalarMethod(me->fConnection, 636 kIOFWAVCProtocolUserClientFreeInputPlug, 637 inputs, 638 1, 639 NULL, 640 &outputCnt); 641} 642 643static UInt32 readInputPlug( void *self, UInt32 plug) 644{ 645 AVCProtocol *me = getThis(self); 646 UInt32 val; 647 const uint64_t inArg = plug; 648 uint32_t outputCnt = 1; 649 uint64_t outputVal = 0; 650 const uint64_t inputs[1]={(const uint64_t)inArg}; 651 652 //printf("DEBUG: AVCProtocol::readInputPlug\n"); 653 654 IOConnectCallScalarMethod(me->fConnection, 655 kIOFWAVCProtocolUserClientReadInputPlug, 656 inputs, 657 1, 658 &outputVal, 659 &outputCnt); 660 661 val = outputVal & 0xFFFFFFFF; 662 663 return val; 664} 665 666static IOReturn updateInputPlug( void *self, UInt32 plug, UInt32 oldVal, UInt32 newVal) 667{ 668 AVCProtocol *me = getThis(self); 669 uint64_t inArg[3]; 670 uint32_t outputCnt = 0; 671 672 inArg[0] = plug; 673 inArg[1] = oldVal; 674 inArg[2] = newVal; 675 676 //printf("DEBUG: AVCProtocol::updateInputPlug\n"); 677 678 return IOConnectCallScalarMethod(me->fConnection, 679 kIOFWAVCProtocolUserClientUpdateInputPlug, 680 inArg, 681 3, 682 NULL, 683 &outputCnt); 684} 685 686static IOReturn allocateOutputPlug( void *self, void *refcon, IOFWAVCPCRCallback func, UInt32 *plug) 687{ 688 AVCProtocol *me = getThis(self); 689 uint64_t params; 690 IOReturn status; 691 uint64_t refrncData[kOSAsyncRef64Count]; 692 uint32_t outputCnt = 1; 693 uint64_t returnVal; 694 695 //printf("DEBUG: AVCProtocol::allocateOutputPlug\n"); 696 697 refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t)pcrWriteCallback; 698 refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long)refcon; 699 params = (unsigned long)func; 700 const uint64_t inputs[1]={(const uint64_t)params}; 701 702 status = IOConnectCallAsyncScalarMethod(me->fConnection, 703 kIOFWAVCProtocolUserClientAllocateOutputPlug, 704 me->fAsyncPort, 705 refrncData,kOSAsyncRef64Count, 706 inputs, 1, 707 &returnVal,&outputCnt); 708 709 *plug = returnVal & 0xFFFFFFFF; 710 711 return status; 712} 713 714static void freeOutputPlug( void *self, UInt32 plug) 715{ 716 AVCProtocol *me = getThis(self); 717 uint32_t outputCnt = 0; 718 const uint64_t inArg = plug; 719 const uint64_t inputs[1]={(const uint64_t)inArg}; 720 721 //printf("DEBUG: AVCProtocol::freeOutputPlug\n"); 722 723 IOConnectCallScalarMethod(me->fConnection, 724 kIOFWAVCProtocolUserClientFreeOutputPlug, 725 inputs, 726 1, 727 NULL, 728 &outputCnt); 729} 730 731static UInt32 readOutputPlug( void *self, UInt32 plug) 732{ 733 AVCProtocol *me = getThis(self); 734 UInt32 val; 735 const uint64_t inArg = plug; 736 uint32_t outputCnt = 1; 737 uint64_t outputVal = 0; 738 const uint64_t inputs[1]={(const uint64_t)inArg}; 739 740 //printf("DEBUG: AVCProtocol::readOutputPlug\n"); 741 742 IOConnectCallScalarMethod(me->fConnection, 743 kIOFWAVCProtocolUserClientReadOutputPlug, 744 inputs, 745 1, 746 &outputVal, 747 &outputCnt); 748 749 val = outputVal & 0xFFFFFFFF; 750 751 return val; 752} 753 754static IOReturn updateOutputPlug( void *self, UInt32 plug, UInt32 oldVal, UInt32 newVal) 755{ 756 AVCProtocol *me = getThis(self); 757 uint64_t inArg[3]; 758 uint32_t outputCnt = 0; 759 760 inArg[0] = plug; 761 inArg[1] = oldVal; 762 inArg[2] = newVal; 763 764 //printf("DEBUG: AVCProtocol::updateOutputPlug\n"); 765 766 return IOConnectCallScalarMethod(me->fConnection, 767 kIOFWAVCProtocolUserClientUpdateOutputPlug, 768 inArg, 769 3, 770 NULL, 771 &outputCnt); 772} 773 774static UInt32 readOutputMasterPlug( void *self) 775{ 776 AVCProtocol *me = getThis(self); 777 UInt32 val; 778 uint32_t outputCnt = 1; 779 uint64_t outputVal = 0; 780 781 //printf("DEBUG: AVCProtocol::readOutputMasterPlug\n"); 782 783 IOConnectCallScalarMethod(me->fConnection, 784 kIOFWAVCProtocolUserClientReadOutputMasterPlug, 785 NULL, 786 0, 787 &outputVal, 788 &outputCnt); 789 790 val = outputVal & 0xFFFFFFFF; 791 792 return val; 793} 794 795static IOReturn updateOutputMasterPlug( void *self, UInt32 oldVal, UInt32 newVal) 796{ 797 AVCProtocol *me = getThis(self); 798 uint64_t inArg[2]; 799 uint32_t outputCnt = 0; 800 801 inArg[0] = oldVal; 802 inArg[1] = newVal; 803 804 //printf("DEBUG: AVCProtocol::updateOutputMasterPlug\n"); 805 806 return IOConnectCallScalarMethod(me->fConnection, 807 kIOFWAVCProtocolUserClientUpdateOutputMasterPlug, 808 inArg, 809 2, 810 NULL, 811 &outputCnt); 812} 813 814static UInt32 readInputMasterPlug( void *self) 815{ 816 AVCProtocol *me = getThis(self); 817 UInt32 val; 818 uint32_t outputCnt = 1; 819 uint64_t outputVal = 0; 820 821 //printf("DEBUG: AVCProtocol::readInputMasterPlug\n"); 822 823 IOConnectCallScalarMethod(me->fConnection, 824 kIOFWAVCProtocolUserClientReadInputMasterPlug, 825 NULL, 826 0, 827 &outputVal, 828 &outputCnt); 829 830 val = outputVal & 0xFFFFFFFF; 831 832 return val; 833} 834 835static IOReturn updateInputMasterPlug( void *self, UInt32 oldVal, UInt32 newVal) 836{ 837 AVCProtocol *me = getThis(self); 838 uint64_t inArg[2]; 839 uint32_t outputCnt = 0; 840 841 inArg[0] = oldVal; 842 inArg[1] = newVal; 843 844 //printf("DEBUG: AVCProtocol::updateInputMasterPlug\n"); 845 846 return IOConnectCallScalarMethod(me->fConnection, 847 kIOFWAVCProtocolUserClientUpdateInputMasterPlug, 848 inArg, 849 2, 850 NULL, 851 &outputCnt); 852} 853 854static IOReturn publishAVCUnitDirectory(void *self) 855{ 856 AVCProtocol *me = getThis(self); 857 uint32_t outputCnt = 0; 858 859 //printf("DEBUG: AVCProtocol::publishAVCUnitDirectory\n"); 860 861 IOConnectCallScalarMethod(me->fConnection, 862 kIOFWAVCProtocolUserClientPublishAVCUnitDirectory, 863 NULL, 864 0, 865 NULL, 866 &outputCnt); 867 868 return kIOReturnSuccess; 869} 870 871static IOReturn installAVCCommandHandler(void *self, 872 UInt32 subUnitTypeAndID, 873 UInt32 opCode, 874 void *refCon, 875 IOFWAVCCommandHandlerCallback callback) 876{ 877 AVCProtocol *me = getThis(self); 878 IOReturn status = kIOReturnSuccess; 879 uint64_t params[4]; 880 uint64_t refrncData[kOSAsyncRef64Count]; 881 uint32_t outputCnt = 0; 882 883 884 //printf("DEBUG: AVCProtocol::installAVCCommandHandler\n"); 885 886 refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t)avcCommandHandlerCallback; 887 refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long)me; 888 params[0] = subUnitTypeAndID; 889 params[1] = opCode; 890 params[2] = (unsigned long)callback; 891 params[3] = (unsigned long)refCon; 892 893 status = IOConnectCallAsyncScalarMethod(me->fConnection, 894 kIOFWAVCProtocolUserClientInstallAVCCommandHandler, 895 me->fAsyncPort, 896 refrncData,kOSAsyncRef64Count, 897 params, 4, 898 NULL,&outputCnt); 899 900 return status; 901} 902 903static IOReturn sendAVCResponse(void *self, 904 UInt32 generation, 905 UInt16 nodeID, 906 const char *response, 907 UInt32 responseLen) 908{ 909 AVCProtocol *me = getThis(self); 910 uint64_t inArg[2]; 911 uint32_t outputScalarCnt = 0; 912 size_t outputStructSize = 0; 913 914 inArg[0] = generation; 915 inArg[1] = nodeID; 916 917 return IOConnectCallMethod(me->fConnection, 918 kIOFWAVCProtocolUserClientSendAVCResponse, 919 inArg, 920 2, 921 response, 922 responseLen, 923 NULL, 924 &outputScalarCnt, 925 NULL, 926 &outputStructSize); 927 928 929} 930 931IOReturn addSubunit(void *self, 932 UInt32 subunitType, 933 UInt32 numSourcePlugs, 934 UInt32 numDestPlugs, 935 void *refCon, 936 IOFWAVCSubunitPlugHandlerCallback callback, 937 UInt32 *pSubunitTypeAndID) 938{ 939 AVCProtocol *me = getThis(self); 940 IOReturn status = kIOReturnSuccess; 941 uint64_t params[5]; 942 uint64_t refrncData[kOSAsyncRef64Count]; 943 uint32_t outputCnt = 1; 944 uint64_t returnVal; 945 946 //printf("DEBUG: AVCProtocol::addSubunit\n"); 947 948 refrncData[kIOAsyncCalloutFuncIndex] = (uint64_t)subunitPlugHandlerCallback; 949 refrncData[kIOAsyncCalloutRefconIndex] = (unsigned long)me; 950 params[0] = subunitType; 951 params[1] = numSourcePlugs; 952 params[2] = numDestPlugs; 953 params[3] = (unsigned long)callback; 954 params[4] = (unsigned long)refCon; 955 956 status = IOConnectCallAsyncScalarMethod(me->fConnection, 957 kIOFWAVCProtocolUserClientAddSubunit, 958 me->fAsyncPort, 959 refrncData,kOSAsyncRef64Count, 960 params, 5, 961 &returnVal,&outputCnt); 962 963 *pSubunitTypeAndID = returnVal & 0xFFFFFFFF; 964 965 return status; 966} 967 968IOReturn setSubunitPlugSignalFormat(void *self, 969 UInt32 subunitTypeAndID, 970 IOFWAVCPlugTypes plugType, 971 UInt32 plugNum, 972 UInt32 signalFormat) 973{ 974 AVCProtocol *me = getThis(self); 975 uint64_t inArg[4]; 976 uint32_t outputCnt = 0; 977 978 inArg[0] = subunitTypeAndID; 979 inArg[1] = plugType; 980 inArg[2] = plugNum; 981 inArg[3] = signalFormat; 982 983 //printf("DEBUG: AVCProtocol::setSubunitPlugSignalFormat\n"); 984 985 return IOConnectCallScalarMethod(me->fConnection, 986 kIOFWAVCProtocolUserClientSetSubunitPlugSignalFormat, 987 inArg, 988 4, 989 NULL, 990 &outputCnt); 991} 992 993 994IOReturn getSubunitPlugSignalFormat(void *self, 995 UInt32 subunitTypeAndID, 996 IOFWAVCPlugTypes plugType, 997 UInt32 plugNum, 998 UInt32 *pSignalFormat) 999{ 1000 AVCProtocol *me = getThis(self); 1001 IOReturn status = kIOReturnSuccess; 1002 uint32_t outputCnt = 1; 1003 uint64_t outputVal = 0; 1004 uint64_t inArg[3]; 1005 1006 inArg[0] = subunitTypeAndID; 1007 inArg[1] = plugType; 1008 inArg[2] = plugNum; 1009 1010 //printf("DEBUG: AVCProtocol::getSubunitPlugSignalFormat\n"); 1011 1012 status = IOConnectCallScalarMethod(me->fConnection, 1013 kIOFWAVCProtocolUserClientGetSubunitPlugSignalFormat, 1014 inArg, 1015 3, 1016 &outputVal, 1017 &outputCnt); 1018 1019 *pSignalFormat = outputVal & 0xFFFFFFFF; 1020 return status; 1021} 1022 1023IOReturn connectTargetPlugs(void *self, 1024 UInt32 sourceSubunitTypeAndID, 1025 IOFWAVCPlugTypes sourcePlugType, 1026 UInt32 *pSourcePlugNum, 1027 UInt32 destSubunitTypeAndID, 1028 IOFWAVCPlugTypes destPlugType, 1029 UInt32 *pDestPlugNum, 1030 bool lockConnection, 1031 bool permConnection) 1032{ 1033 AVCProtocol *me = getThis(self); 1034 IOReturn status = kIOReturnSuccess; 1035 AVCConnectTargetPlugsInParams inParams; 1036 AVCConnectTargetPlugsOutParams outParams; 1037 size_t outputCnt = sizeof(AVCConnectTargetPlugsOutParams); 1038 1039 //printf("DEBUG: AVCProtocol::connectTargetPlugs\n"); 1040 1041 inParams.sourceSubunitTypeAndID = sourceSubunitTypeAndID; 1042 inParams.sourcePlugType = sourcePlugType; 1043 inParams.sourcePlugNum = *pSourcePlugNum; 1044 inParams.destSubunitTypeAndID = destSubunitTypeAndID; 1045 inParams.destPlugType = destPlugType; 1046 inParams.destPlugNum = *pDestPlugNum; 1047 inParams.lockConnection = lockConnection; 1048 inParams.permConnection = permConnection; 1049 1050 ROSETTA_ONLY( 1051 { 1052 inParams.sourceSubunitTypeAndID = OSSwapInt32(inParams.sourceSubunitTypeAndID); 1053 inParams.sourcePlugType = OSSwapInt32(inParams.sourcePlugType); 1054 inParams.sourcePlugNum = OSSwapInt32(inParams.sourcePlugNum); 1055 inParams.destSubunitTypeAndID = OSSwapInt32(inParams.destSubunitTypeAndID); 1056 inParams.destPlugType = OSSwapInt32(inParams.destPlugType); 1057 inParams.destPlugNum = OSSwapInt32(inParams.destPlugNum); 1058 } 1059 ); 1060 1061 status = IOConnectCallStructMethod(me->fConnection, 1062 kIOFWAVCProtocolUserClientConnectTargetPlugs, 1063 &inParams, 1064 sizeof(AVCConnectTargetPlugsInParams), 1065 &outParams, 1066 &outputCnt); 1067 1068 ROSETTA_ONLY( 1069 { 1070 outParams.sourcePlugNum = OSSwapInt32(outParams.sourcePlugNum); 1071 outParams.destPlugNum = OSSwapInt32(outParams.destPlugNum); 1072 } 1073 ); 1074 1075 *pSourcePlugNum = outParams.sourcePlugNum; 1076 *pDestPlugNum = outParams.destPlugNum; 1077 return status; 1078} 1079 1080IOReturn disconnectTargetPlugs(void *self, 1081 UInt32 sourceSubunitTypeAndID, 1082 IOFWAVCPlugTypes sourcePlugType, 1083 UInt32 sourcePlugNum, 1084 UInt32 destSubunitTypeAndID, 1085 IOFWAVCPlugTypes destPlugType, 1086 UInt32 destPlugNum) 1087{ 1088 AVCProtocol *me = getThis(self); 1089 uint32_t outputCnt = 0; 1090 uint64_t inArg[6]; 1091 1092 inArg[0] = sourceSubunitTypeAndID; 1093 inArg[1] = sourcePlugType; 1094 inArg[2] = sourcePlugNum; 1095 inArg[3] = destSubunitTypeAndID; 1096 inArg[4] = destPlugType; 1097 inArg[5] = destPlugNum; 1098 1099 //printf("DEBUG: AVCProtocol::disconnectTargetPlugs\n"); 1100 1101 return IOConnectCallScalarMethod(me->fConnection, 1102 kIOFWAVCProtocolUserClientDisconnectTargetPlugs, 1103 inArg, 1104 6, 1105 NULL, 1106 &outputCnt); 1107} 1108 1109IOReturn getTargetPlugConnection(void *self, 1110 UInt32 subunitTypeAndID, 1111 IOFWAVCPlugTypes plugType, 1112 UInt32 plugNum, 1113 UInt32 *pConnectedSubunitTypeAndID, 1114 IOFWAVCPlugTypes *pConnectedPlugType, 1115 UInt32 *pConnectedPlugNum, 1116 bool *pLockConnection, 1117 bool *pPermConnection) 1118{ 1119 AVCProtocol *me = getThis(self); 1120 IOReturn status = kIOReturnSuccess; 1121 AVCGetTargetPlugConnectionInParams inParams; 1122 AVCGetTargetPlugConnectionOutParams outParams; 1123 size_t outputCnt = sizeof(AVCGetTargetPlugConnectionInParams); 1124 1125 //printf("DEBUG: AVCProtocol::getTargetPlugConnection\n"); 1126 1127 inParams.subunitTypeAndID = subunitTypeAndID; 1128 inParams.plugType = plugType; 1129 inParams.plugNum = plugNum; 1130 1131 ROSETTA_ONLY( 1132 { 1133 inParams.subunitTypeAndID = OSSwapInt32(inParams.subunitTypeAndID); 1134 inParams.plugType = OSSwapInt32(inParams.plugType); 1135 inParams.plugNum = OSSwapInt32(inParams.plugNum); 1136 } 1137 ); 1138 1139 status = IOConnectCallStructMethod(me->fConnection, 1140 kIOFWAVCProtocolUserClientGetTargetPlugConnection, 1141 &inParams, 1142 sizeof(AVCConnectTargetPlugsInParams), 1143 &outParams, 1144 &outputCnt); 1145 1146 ROSETTA_ONLY( 1147 { 1148 outParams.connectedSubunitTypeAndID = OSSwapInt32(outParams.connectedSubunitTypeAndID); 1149 outParams.connectedPlugType = OSSwapInt32(outParams.connectedPlugType); 1150 outParams.connectedPlugNum = OSSwapInt32(outParams.connectedPlugNum); 1151 } 1152 ); 1153 1154 *pConnectedSubunitTypeAndID = outParams.connectedSubunitTypeAndID; 1155 *pConnectedPlugType = outParams.connectedPlugType; 1156 *pConnectedPlugNum = outParams.connectedPlugNum; 1157 *pLockConnection = outParams.lockConnection; 1158 *pPermConnection = outParams.permConnection; 1159 1160 return status; 1161} 1162 1163 1164// static interface table for IOCFPlugInInterface 1165// 1166 1167static IOCFPlugInInterface sIOCFPlugInInterface = 1168{ 1169 0, 1170 &queryInterface, 1171 &addRef, 1172 &release, 1173 1, 0, // version/revision 1174 &probe, 1175 &start, 1176 &stop 1177}; 1178 1179// 1180// static interface table for IOFireWireAVCLibProtocolInterface 1181// 1182 1183static IOFireWireAVCLibProtocolInterface sProtocolInterface = 1184{ 1185 0, 1186 &queryInterface, 1187 &addRef, 1188 &release, 1189 2, 0, // version/revision 1190 &addIODispatcherToRunLoop, 1191 &removeIODispatcherFromRunLoop, 1192 &setMessageCallback, 1193 &setAVCRequestCallback, 1194 &allocateInputPlug, 1195 &freeInputPlug, 1196 &readInputPlug, 1197 &updateInputPlug, 1198 &allocateOutputPlug, 1199 &freeOutputPlug, 1200 &readOutputPlug, 1201 &updateOutputPlug, 1202 &readOutputMasterPlug, 1203 &updateOutputMasterPlug, 1204 &readInputMasterPlug, 1205 &updateInputMasterPlug, 1206 &publishAVCUnitDirectory, 1207 &installAVCCommandHandler, 1208 &sendAVCResponse, 1209 &addSubunit, 1210 &setSubunitPlugSignalFormat, 1211 &getSubunitPlugSignalFormat, 1212 &connectTargetPlugs, 1213 &disconnectTargetPlugs, 1214 &getTargetPlugConnection 1215}; 1216 1217// IOFireWireAVCLibProtocolFactory 1218 1219// alloc 1220// 1221// static allocator, called by factory method 1222 1223static IOCFPlugInInterface ** alloc() 1224{ 1225 IOCFPlugInInterface ** interface = NULL; 1226 AVCProtocol * me; 1227 1228 //printf("DEBUG: AVCProtocol::alloc\n"); 1229 1230 me = (AVCProtocol *)malloc(sizeof(AVCProtocol)); 1231 if( me ) 1232 { 1233 bzero(me, sizeof(AVCProtocol)); 1234 // we return an interface here. queryInterface will not be called. set refs to 1 1235 // init cf plugin ref counting 1236 me->fRefCount = 1; 1237 1238 // init user client connection 1239 me->fConnection = MACH_PORT_NULL; 1240 me->fService = MACH_PORT_NULL; 1241 1242 // create plugin interface map 1243 me->fIOCFPlugInInterface.pseudoVTable = (IUnknownVTbl *) &sIOCFPlugInInterface; 1244 me->fIOCFPlugInInterface.obj = me; 1245 1246 // create test driver interface map 1247 me->fIOFireWireAVCLibProtocolInterface.pseudoVTable 1248 = (IUnknownVTbl *) &sProtocolInterface; 1249 me->fIOFireWireAVCLibProtocolInterface.obj = me; 1250 1251 me->fFactoryId = kIOFireWireAVCLibProtocolFactoryID; 1252 CFRetain( me->fFactoryId ); 1253 CFPlugInAddInstanceForFactory( me->fFactoryId ); 1254 interface = (IOCFPlugInInterface **) &me->fIOCFPlugInInterface.pseudoVTable; 1255 } 1256 return interface; 1257} 1258 1259// 1260// factory method (only exported symbol) 1261 1262void *IOFireWireAVCLibProtocolFactory( CFAllocatorRef allocator, CFUUIDRef typeID ) 1263{ 1264 1265 //printf("DEBUG: AVCProtocol::IOFireWireAVCLibProtocolFactory\n"); 1266 1267 if( CFEqual(typeID, kIOFireWireAVCLibProtocolTypeID) ) 1268 return (void *) alloc(); 1269 else 1270 return NULL; 1271} 1272 1273