1/* 2 * Copyright (c) 2009 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23#include <Carbon/Carbon.h> 24#include <QuickTime/QuickTime.h> 25 26#include <stdio.h> 27#include <stdlib.h> 28 29#include <sys/types.h> 30#include <sys/stat.h> 31#include <fcntl.h> 32#include <iokit/IOKitLib.h> 33#include <iokit/avc/IOFireWireAVCConsts.h> 34 35#include <DVComponentGlue/IsochronousDataHandler.h> 36#include <DVComponentGlue/DeviceControl.h> 37 38static QTAtomSpec videoConfig; 39static IDHDeviceID deviceID; 40static IDHNotificationID notificationID; 41 42static void printP(const char *s) 43{ 44 int len = *s++; 45 while(len--) 46 printf("%c", *s++); 47} 48 49static void print4(const char *s, UInt32 val) 50{ 51 printf("%s'%c%c%c%c'(0x%x)", s, val>>24, val>>16, val>>8, val, val); 52} 53 54static OSStatus notificationProc(IDHGenericEvent* event, void* userData) 55{ 56 ComponentInstance theInst = userData; 57 printf("Got notification for device 0x%x, notification 0x%x, event 0x%x, userdata 0x%x\n", 58 event->eventHeader.deviceID, event->eventHeader.notificationID, event->eventHeader.event, 59 userData); 60 61 // Reenable notification 62 IDHNotifyMeWhen(theInst, event->eventHeader.notificationID, kIDHEventEveryEvent); 63 64 return noErr; 65} 66 67static void doControlTest(ComponentInstance theInst, QTAtomSpec *currentIsochConfig, UInt8 op1, UInt8 op2) 68{ 69 //Component control; 70 ComponentInstance controlInst; 71 ComponentResult result; 72 IDHDeviceStatus devStatus; 73 DVCTransactionParams pParams; 74 char in[4], out[16]; 75 //char in[44], out[44]; 76 int i; 77 78 result = IDHGetDeviceControl(theInst, &controlInst); 79 if(result) 80 goto Exit; 81 //controlInst = OpenComponent(control); 82 // get the local node's fw ref id 83 result = IDHGetDeviceStatus( theInst, currentIsochConfig, &devStatus); 84 if(result) 85 goto Exit; 86 //result = FWClockPrivSetFWReferenceID(clockInst, (FWReferenceID) devStatus.localNodeID ); 87 //if(result) 88 // goto Exit; 89 90 // set the clock's fw id 91 //clockInst = OpenDefaultComponent(clockComponentType, systemMicrosecondClock); 92 93 if(!controlInst) 94 goto Exit; 95 96#if 1 97 // fill up the avc frame 98 in[0] = kAVCStatusInquiryCommand; //kAVCControlCommand; 99 in[1] = 0x20; // for now 100 in[2] = op1; 101 in[3] = op2; 102#else 103 // fill up the avc frame 104 in[0] = 0x00; 105 in[1] = 0x58; // for now 106 in[2] = 0x50; 107 in[3] = 0x00; 108 109 in[4] = 0xff; 110 in[5] = 0x00; // for now 111 in[6] = 0x00; 112 in[7] = 0x00; 113 114 in[8] = 0xff; 115 in[9] = 0xff; 116 in[10] = 0xff; 117 in[11] = 0xff; 118 119 in[12] = 0x00; 120 in[13] = 0x00; 121 in[14] = 0x00; 122 in[15] = 0x1b; 123 124 in[16] = 0x5c; 125 in[17] = 0x44; 126 in[18] = 0x43; 127 in[19] = 0x49; 128 129 in[20] = 0x4d; 130 in[21] = 0x5c; 131 in[22] = 0x31; 132 in[23] = 0x30; 133 134 in[24] = 0x31; 135 in[25] = 0x43; 136 in[26] = 0x41; 137 in[27] = 0x4e; 138 139 in[28] = 0x4f; 140 in[29] = 0x4e; 141 in[30] = 0x5c; 142 in[31] = 0x41; 143 144 in[32] = 0x55; 145 in[33] = 0x54; 146 in[34] = 0x5f; 147 in[35] = 0x30; 148 149 in[36] = 0x31; 150 in[37] = 0x30; 151 in[38] = 0x33; 152 in[39] = 0x2e; 153 154 in[40] = 0x4a; 155 in[41] = 0x50; 156 in[42] = 0x47; 157 in[43] = 0x00; 158 159 160#endif 161 162 // fill up the transaction parameter block 163 pParams.commandBufferPtr = in; 164 pParams.commandLength = sizeof(in); 165 pParams.responseBufferPtr = out; 166 pParams.responseBufferSize = sizeof(out); 167 pParams.responseHandler = NULL; 168 169 do { 170 for(i=0; i<sizeof(out); i++) 171 out[i] = 0; 172 result = DeviceControlDoAVCTransaction( controlInst, &pParams); 173 if(result == kIOReturnOffline) { 174 printf("offline!!\n"); 175 sleep(1); 176 continue; 177 } 178 if(result) 179 goto Exit; 180 printf("Received %d bytes:", pParams.responseBufferSize); 181 for(i=0; i<sizeof(out); i++) 182 printf("%d(0x%x) ", out[i], out[i]); 183 printf("\n"); 184 } while (1); //(result != kIOReturnSuccess); 185 186 //sleep(10); 187 188Exit: 189 if(result != noErr) 190 printf("Control error %d(%x)\n", result, result); 191} 192 193static void OpenDV() 194{ 195 ComponentInstance theInst; 196 ComponentResult version; 197 QTAtomContainer deviceList = NULL; 198 short nDVDevices, i, j; 199 QTAtom deviceAtom; 200 UInt32 cmpFlag; 201 UInt32 isoversion; 202 long size; 203 OSStatus err; 204 205 theInst = OpenDefaultComponent('ihlr', 'dv '); 206 printf("Instance is 0x%x\n", theInst); 207 if(theInst == NULL) 208 return; 209 210 version = CallComponentVersion(theInst); 211 printf("Version is 0x%x\n", version); 212 213// Ask for notifications for what's happening - ask for EVERYTHING!! 214 err = IDHNewNotification(theInst, kIDHDeviceIDEveryDevice, notificationProc, theInst, ¬ificationID); 215 if( err != noErr) 216 goto error; 217 218 err = IDHNotifyMeWhen(theInst, notificationID, kIDHEventEveryEvent); 219 if( err != noErr) 220 goto error; 221 222 do { 223 err = IDHGetDeviceList( theInst, &deviceList); 224 if( err != noErr) 225 goto error; 226 227 nDVDevices = QTCountChildrenOfType( deviceList, kParentAtomIsContainer, kIDHDeviceAtomType); 228 if(nDVDevices > 0) 229 break; 230 printf("Waiting for a camera...\n"); 231 sleep(1); 232 } while(true); 233 234 235 QTLockContainer( deviceList); 236 // find the cmp atom 237 deviceAtom = QTFindChildByIndex( deviceList, kParentAtomIsContainer, kIDHUseCMPAtomType, 1, nil); 238 if( deviceAtom == nil) 239 goto error; 240 241 // get the value of the cmp atom 242 QTCopyAtomDataToPtr( deviceList, deviceAtom, true, sizeof( cmpFlag), &cmpFlag, &size); 243 244 // find the version atom 245 deviceAtom = QTFindChildByIndex( deviceList, kParentAtomIsContainer, kIDHIsochVersionAtomType, 1, nil); 246 if( deviceAtom == nil) 247 goto error; 248 249 // get the value of the version atom 250 QTCopyAtomDataToPtr( deviceList, deviceAtom, true, sizeof( isoversion), &isoversion, &size); 251 252 printf("Version 0x%x. %d DV devices, use CMP flag is %d\n", isoversion, nDVDevices, cmpFlag); 253 254 for( i=0; i<nDVDevices; ++i) 255 { 256 QTAtom isochAtom, dataAtom; 257 UInt32 test[2]; 258 int nConfigs; 259 char cameraName[256]; 260 IDHDeviceStatus deviceStatus; 261 262 // get the atom to this device 263 deviceAtom = QTFindChildByIndex( deviceList, kParentAtomIsContainer, kIDHDeviceAtomType, i + 1, nil); 264 if( deviceAtom == nil) 265 goto error; 266 267 printf("device %d ", i); 268 269 dataAtom = QTFindChildByIndex( deviceList, deviceAtom, kIDHUniqueIDType, 1, nil); 270 if( dataAtom == nil) 271 goto error; 272 QTCopyAtomDataToPtr( deviceList, dataAtom, true, sizeof( test), test, &size); 273 printf("guid 0x%x%08x ", test[0], test[1]); 274 275 dataAtom = QTFindChildByIndex( deviceList, deviceAtom, kIDHNameAtomType, 1, nil); 276 if( dataAtom == nil) 277 goto error; 278 QTCopyAtomDataToPtr( deviceList, dataAtom, true, 255, cameraName, &size); 279 cameraName[size] = 0; 280 printf("%s ", cameraName+1); 281 282 dataAtom = QTFindChildByIndex( deviceList, deviceAtom, kIDHDeviceIDType, 1, nil); 283 if( dataAtom == nil) 284 goto error; 285 QTCopyAtomDataToPtr( deviceList, dataAtom, true, sizeof( deviceID), &deviceID, &size); 286 printf("deviceID 0x%x ", deviceID); 287 288 dataAtom = QTFindChildByIndex( deviceList, deviceAtom, 'ddin', 1, nil); 289 if( dataAtom == nil) 290 goto error; 291 QTCopyAtomDataToPtr( deviceList, dataAtom, true, sizeof( deviceStatus), &deviceStatus, &size); 292 printf("\ndevice status:\n"); 293 printf("version %d\n", deviceStatus.version); 294 printf("physicallyConnected %d\n", deviceStatus.physicallyConnected); 295 printf("readEnabled %d ", deviceStatus.readEnabled); 296 printf("writeEnabled %d ", deviceStatus.writeEnabled); 297 printf("exclusiveAccess %d\n", deviceStatus.exclusiveAccess); 298 printf("currentBandwidth %d ", deviceStatus.currentBandwidth); 299 printf("currentChannel %d ", deviceStatus.currentChannel); 300 printf("inputStandard %d ", deviceStatus.inputStandard); 301 printf("deviceActive %d\n", deviceStatus.deviceActive); 302 303 // find the isoch characteristics for this device 304 isochAtom = QTFindChildByIndex( deviceList, deviceAtom, kIDHIsochServiceAtomType, 1, nil); 305 if( isochAtom == nil) 306 goto error; 307 308 // how many configs exist for this device 309 nConfigs = QTCountChildrenOfType( deviceList, isochAtom, kIDHIsochModeAtomType); 310 printf("\n%d configs:\n", nConfigs); 311 312 videoConfig.atom = nil; // start with no selected config 313 314 // process each config 315 for( j=0; j<nConfigs; ++j) 316 { 317 OSType mediaType; 318 QTAtom configAtom, mediaAtom; 319 320 // get this configs atom 321 configAtom = QTFindChildByIndex( deviceList, isochAtom, kIDHIsochModeAtomType, j + 1, nil); 322 if( configAtom == nil) 323 goto error; 324 325 printf("Config %d",j); 326 // find the media type atom 327 mediaAtom = QTFindChildByIndex( deviceList, configAtom, kIDHIsochMediaType, 1, nil); 328 if( mediaAtom == nil) 329 goto error; 330 331 // get the value of the mediaType atom 332 QTCopyAtomDataToPtr( deviceList, mediaAtom, true, sizeof( mediaType), &mediaType, &size); 333 print4(" Media type:", mediaType); 334 335 // is this config an video config? 336 if( mediaType == kIDHVideoMediaAtomType) // found video device 337 { 338 videoConfig.container = deviceList; // save this config 339 videoConfig.atom = configAtom; 340 break; 341 } 342 printf("\n"); 343 } 344 printf("-----\n"); 345 346 } 347 348 if( videoConfig.atom == nil) // no good configs found 349 goto error; 350 351 printf("setting config\n"); 352 // set isoch to use this config 353 err = IDHSetDeviceConfiguration( theInst, &videoConfig); 354 if( err != noErr) 355 goto error; 356#if 1 357 doControlTest(theInst, &videoConfig, 358 //0xc3, //kAVCPlayOpcode 359 //0x75 //kAVCPlayForward 360 0xd0, // Transport State 361 0x7f 362 ); 363#else 364 { 365 TimeRecord time1, time2; 366 do { 367 err = IDHGetDeviceTime(theInst, &time1); 368 err = IDHGetDeviceTime(theInst, &time2); 369 if(time2.value.lo > time1.value.lo+1) { 370 //printf("read device time1, scale: %d, time 0x%x:0x%x\n", 371 // time1.scale, time1.value.hi, time1.value.lo); 372 //printf("read device time2, scale: %d, time 0x%x:0x%x\n", 373 // time2.scale, time2.value.hi, time2.value.lo); 374 375 printf("Diff is %d\n", time2.value.lo-time1.value.lo); 376 } 377 } while (1); 378 } 379#endif 380error: 381 if( err != noErr) 382 printf("error %d(0x%x)\n", err, err); 383 if(deviceList) { 384 QTUnlockContainer( deviceList); 385 QTDisposeAtomContainer(deviceList); 386 } 387 388 CloseComponent(theInst); 389 390} 391 392 393int main(int argc, char **argv) 394{ 395 UInt32 seed = GetComponentListModSeed(); 396 UInt32 num; 397 Handle aName; 398 ComponentDescription desc, aDesc; 399 Component aComponent; 400 401 int pos = 1; 402 403 printf("Component seed is %d\n", seed); 404 desc.componentType = 'ihlr'; /* A unique 4-byte code indentifying the command set */ 405 desc.componentSubType = 0; /* Particular flavor of this instance */ 406 desc.componentManufacturer = 0; /* Vendor indentification */ 407 desc.componentFlags = 0; /* 8 each for Component,Type,SubType,Manuf/revision */ 408 desc.componentFlagsMask = 0; /* Mask for specifying which flags to consider in search, zero during registration */ 409 410 num = CountComponents(&desc); 411 printf("%d components match\n", num); 412 413 aComponent = 0; 414 aName = NewHandleClear(200); 415 while (aComponent = FindNextComponent(aComponent, &desc)) { 416 OSStatus oops; 417 printf("Found component 0x%x:", aComponent); 418 oops = GetComponentInfo(aComponent, &aDesc, aName, 419 NULL, NULL); 420 if(oops) 421 printf("GetComponentInfo() returned error %d\n", oops); 422 else { 423 if(GetHandleSize(aName)) 424 printP(*aName); 425 else 426 printf("Unnamed"); 427 print4(", Type ", aDesc.componentType); 428 429 print4(", SubType ", aDesc.componentSubType); 430 print4(", Manufacturer ", aDesc.componentManufacturer); 431 printf("\n"); 432 } 433 } 434 435 num = 0; 436 do { 437 ComponentInstance theInst; 438 439 theInst = OpenDefaultComponent('ihlr', 'dv '); 440 //printf("Instance is 0x%x\n", theInst); 441 if(theInst == NULL) 442 return; 443 num++; 444 usleep(50000); 445 CloseComponent(theInst); 446 } while (0); 447 OpenDV(); 448 return 0; 449} 450 451