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/*
24 *  DVtest.c
25 *  IOFWDVComponents
26 *
27 *  Created by wgulland on Tue Oct 17 2000.
28 *  Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
29 *
30 */
31
32#include <Carbon/Carbon.h>
33
34#include <unistd.h>
35#include <stdio.h>
36#include <stdlib.h>
37
38#include <sys/types.h>
39#include <sys/stat.h>
40//#include <fcntl.h> in Carbon.h?
41
42#include "DVFamily.h"
43
44typedef struct DVFuncsStruct {
45    UInt32 (*fDVCountDevices)( void );
46    OSErr (*fDVGetIndDevice)( DVDeviceID * pDVDevice, UInt32 index );
47    OSErr (*fDVSetDeviceName)( DVDeviceID deviceID, char * str );
48    OSErr (*fDVGetDeviceName)( DVDeviceID deviceID, char * str );
49
50    OSErr (*fDVOpenDriver)( DVDeviceID deviceID, DVDeviceRefNum *pRefNum );
51    OSErr (*fDVCloseDriver)( DVDeviceRefNum refNum );
52
53    OSErr (*fDVDoAVCTransaction)( DVDeviceRefNum refNum, AVCTransactionParamsPtr pParams );
54
55    OSErr (*fDVIsEnabled)( DVDeviceRefNum refNum, Boolean *isEnabled);
56    OSErr (*fDVGetDeviceStandard)( DVDeviceRefNum refNum, UInt32 * pStandard );
57
58    // DV Isoch Read
59    OSErr (*fDVEnableRead)( DVDeviceRefNum refNum );
60    OSErr (*fDVDisableRead)( DVDeviceRefNum refNum );
61    OSErr (*fDVReadFrame)( DVDeviceRefNum refNum, Ptr *ppReadBuffer, UInt32 * pSize );
62    OSErr (*fDVReleaseFrame)( DVDeviceRefNum refNum, Ptr pReadBuffer );
63
64    // DV Isoch Write
65    OSErr (*fDVEnableWrite)( DVDeviceRefNum refNum );
66    OSErr (*fDVDisableWrite)( DVDeviceRefNum refNum );
67    OSErr (*fDVGetEmptyFrame)( DVDeviceRefNum refNum, Ptr *ppEmptyFrameBuffer, UInt32 * pSize );
68    OSErr (*fDVWriteFrame)( DVDeviceRefNum refNum, Ptr pWriteBuffer );
69
70    // Notifications
71    OSErr (*fDVNewNotification)( DVDeviceRefNum refNum, DVNotifyProc notifyProc,
72						void *userData, DVNotificationID *pNotifyID );
73    OSErr (*fDVNotifyMeWhen)( DVDeviceRefNum refNum, DVNotificationID notifyID, UInt32 events);
74    OSErr (*fDVCancelNotification)( DVDeviceRefNum refNum, DVNotificationID notifyID );
75    OSErr (*fDVDisposeNotification)( DVDeviceRefNum refNum, DVNotificationID notifyID );
76
77} DVFuncs, *DVFuncsPtr;
78
79static DVFuncs sDVFuncs;
80
81static CFBundleRef findMe()
82{
83    CFURLRef    bundleURL;
84    CFBundleRef myBundle;
85    Boolean didLoad = false;
86    // Make a CFURLRef from the CFString representation of the
87    // bundle's path. See the Core Foundation URL Services chapter
88    // for details.
89    bundleURL = CFURLCreateWithFileSystemPath(
90                    kCFAllocatorDefault,
91                    CFSTR("/System/Library/Extensions/DVFamily.bundle"),
92                    kCFURLPOSIXPathStyle,
93                    true );
94
95    printf("Bundle URL: %p\n", bundleURL);
96    // Make a bundle instance using the URLRef.
97    myBundle = CFBundleCreate( kCFAllocatorDefault, bundleURL );
98    printf("Bundle: %p\n", myBundle);
99
100    // Try to load the executable from my bundle.
101    didLoad = CFBundleLoadExecutable( myBundle );
102    printf("loaded? %d\n", didLoad);
103
104    sDVFuncs.fDVCountDevices = CFBundleGetFunctionPointerForName(
105                myBundle, CFSTR("DVCountDevices") );
106    sDVFuncs.fDVGetIndDevice = CFBundleGetFunctionPointerForName(
107                myBundle, CFSTR("DVGetIndDevice") );
108    sDVFuncs.fDVSetDeviceName = CFBundleGetFunctionPointerForName(
109                myBundle, CFSTR("DVSetDeviceName") );
110    sDVFuncs.fDVGetDeviceName = CFBundleGetFunctionPointerForName(
111                myBundle, CFSTR("DVGetDeviceName") );
112    sDVFuncs.fDVOpenDriver = CFBundleGetFunctionPointerForName(
113                myBundle, CFSTR("DVOpenDriver") );
114    sDVFuncs.fDVCloseDriver = CFBundleGetFunctionPointerForName(
115                myBundle, CFSTR("DVCloseDriver") );
116
117// AVC Stuff
118    sDVFuncs.fDVDoAVCTransaction = CFBundleGetFunctionPointerForName(
119                myBundle, CFSTR("DVDoAVCTransaction") );
120
121    sDVFuncs.fDVIsEnabled = CFBundleGetFunctionPointerForName(
122                myBundle, CFSTR("DVIsEnabled") );
123    sDVFuncs.fDVGetDeviceStandard = CFBundleGetFunctionPointerForName(
124                myBundle, CFSTR("DVGetDeviceStandard") );
125
126// Isoch I/O
127    sDVFuncs.fDVEnableRead = CFBundleGetFunctionPointerForName(
128                myBundle, CFSTR("DVEnableRead") );
129    sDVFuncs.fDVDisableRead = CFBundleGetFunctionPointerForName(
130                myBundle, CFSTR("DVDisableRead") );
131    sDVFuncs.fDVReadFrame = CFBundleGetFunctionPointerForName(
132                myBundle, CFSTR("DVReadFrame") );
133    sDVFuncs.fDVReleaseFrame = CFBundleGetFunctionPointerForName(
134                myBundle, CFSTR("DVReleaseFrame") );
135    sDVFuncs.fDVEnableWrite = CFBundleGetFunctionPointerForName(
136                myBundle, CFSTR("DVEnableWrite") );
137    sDVFuncs.fDVDisableWrite = CFBundleGetFunctionPointerForName(
138                myBundle, CFSTR("DVDisableWrite") );
139    sDVFuncs.fDVGetEmptyFrame = CFBundleGetFunctionPointerForName(
140                myBundle, CFSTR("DVGetEmptyFrame") );
141    sDVFuncs.fDVWriteFrame = CFBundleGetFunctionPointerForName(
142                myBundle, CFSTR("DVWriteFrame") );
143
144// Notifications
145    sDVFuncs.fDVNewNotification = CFBundleGetFunctionPointerForName(
146                myBundle, CFSTR("DVNewNotification") );
147    sDVFuncs.fDVNotifyMeWhen = CFBundleGetFunctionPointerForName(
148                myBundle, CFSTR("DVNotifyMeWhen") );
149    sDVFuncs.fDVCancelNotification = CFBundleGetFunctionPointerForName(
150                myBundle, CFSTR("DVCancelNotification") );
151    sDVFuncs.fDVDisposeNotification = CFBundleGetFunctionPointerForName(
152                myBundle, CFSTR("DVDisposeNotification") );
153
154    // Any CF objects returned from functions with "create" or
155    // "copy" in their names must be released by us!
156    CFRelease( bundleURL );
157    return myBundle;
158}
159
160static OSErr doControlTest(DVDeviceRefNum refNum, UInt8 op1, UInt8 op2)
161{
162        //Component control;
163    AVCTransactionParams avcParams;
164    char in[4], out[16];
165    OSErr err;
166
167    // fill up the avc frame
168    in[0]	= kAVCControlCommand;
169    in[1] 	= 0x20;	// for now
170    in[2] 	= op1;
171    in[3] 	= op2;
172
173    // fill up the transaction parameter block
174    avcParams.commandBufferPtr = in;
175    avcParams.commandLength = sizeof(in);
176    avcParams.responseBufferPtr = out;
177    avcParams.responseBufferSize = sizeof(out);
178    avcParams.responseHandler = NULL;
179
180    err = sDVFuncs.fDVDoAVCTransaction(refNum, &avcParams );
181    if(err)
182        printf("Error %d calling DVDoAVCTransaction(%ld)\n", err, refNum);
183
184    return err;
185}
186
187static OSErr doStatusTest(DVDeviceRefNum refNum, UInt8 op1, UInt8 op2)
188{
189        //Component control;
190    AVCTransactionParams avcParams;
191    char in[4], out[16];
192    OSErr err;
193
194    // fill up the avc frame
195    in[0]	= kAVCStatusInquiryCommand;
196    in[1] 	= 0x20;	// for now
197    in[2] 	= op1;
198    in[3] 	= op2;
199
200    // fill up the transaction parameter block
201    avcParams.commandBufferPtr = in;
202    avcParams.commandLength = sizeof(in);
203    avcParams.responseBufferPtr = out;
204    avcParams.responseBufferSize = sizeof(out);
205    avcParams.responseHandler = NULL;
206
207    err = sDVFuncs.fDVDoAVCTransaction(refNum, &avcParams );
208    //if(err)
209        printf("Error %d calling DVDoAVCTransaction(%ld)\n", err, refNum);
210
211    return err;
212}
213
214static OSErr doStatusTest6(DVDeviceRefNum refNum, UInt8 op1, UInt8 op2,
215    UInt8 op3, UInt8 op4, UInt8 op5, UInt8 op6)
216{
217        //Component control;
218    AVCTransactionParams avcParams;
219    char in[8], out[16];
220    OSErr err;
221
222    // fill up the avc frame
223    in[0]	= kAVCStatusInquiryCommand;
224    in[1] 	= 0x20;	// for now
225    in[2] 	= op1;
226    in[3] 	= op2;
227    in[4] 	= op3;
228    in[5] 	= op4;
229    in[6] 	= op5;
230    in[7] 	= op6;
231
232    // fill up the transaction parameter block
233    avcParams.commandBufferPtr = in;
234    avcParams.commandLength = sizeof(in);
235    avcParams.responseBufferPtr = out;
236    avcParams.responseBufferSize = sizeof(out);
237    avcParams.responseHandler = NULL;
238
239    err = sDVFuncs.fDVDoAVCTransaction(refNum, &avcParams );
240    //if(err)
241        printf("Error %d calling DVDoAVCTransaction_6(%ld)\n", err, refNum);
242
243    return err;
244}
245
246static OSStatus myNotifyProc(DVEventRecordPtr event, void *userData )
247{
248    printf("event for device %d, event %d, userdata %p\n",
249        event->eventHeader.deviceID, event->eventHeader.theEvent, userData);
250    return noErr;
251}
252
253int main(int argc, char **argv)
254{
255    CFBundleRef myBundle;
256    UInt32 numDevs, i;
257    UInt32 standard;
258    Boolean isEnabled;
259    OSErr err;
260    DVDeviceID device;
261    DVDeviceRefNum refNum;
262    DVNotificationID notifyID;
263    char name[256];
264    int file;
265
266    myBundle = findMe();
267
268    numDevs = sDVFuncs.fDVCountDevices();
269    printf("Number of devices: %ld\n", numDevs);
270    if(numDevs == 0) {
271        err = sDVFuncs.fDVNewNotification( kEveryDVDeviceRefNum, myNotifyProc,
272						(void *)0x1234, &notifyID );
273        if(err)
274            printf("Error %d calling DVNewNotification(, %ld)\n", err, kEveryDVDeviceRefNum);
275	err = sDVFuncs.fDVNotifyMeWhen( kEveryDVDeviceRefNum, notifyID,
276            kDVDeviceAdded | kDVDeviceRemoved);
277        if(err)
278            printf("Error %d calling NotifyMeWhen(%ld, %ld)\n", err, kEveryDVDeviceRefNum, notifyID);
279
280        while (true) {
281        printf("Waiting for devices: %ld\n", numDevs);
282        usleep(1000000);	// 1000 milliseconds
283        numDevs = sDVFuncs.fDVCountDevices();
284        }
285    }
286    for(i=1; i<=numDevs; i++) {
287        err = sDVFuncs.fDVGetIndDevice(&device, i);
288        if(err)
289            printf("Error %d calling DVGetIndDevice(, %ld)\n", err, i);
290        err = sDVFuncs.fDVGetDeviceName(device, name);
291        if(err)
292            printf("Error %d calling DVGetDeviceName(%ld)\n", err, device);
293        else
294            printf("Device %ld name is %s\n", device, name);
295
296        err = sDVFuncs.fDVOpenDriver( device, &refNum );
297        if(err)
298            printf("Error %d calling DVOpenDriver(%ld)\n", err, device);
299
300        err = sDVFuncs.fDVGetDeviceStandard(refNum, &standard);
301        if(err)
302            printf("Error %d calling DVGetDeviceStandard(%ld)\n", err, device);
303        else if(standard == kNTSCStandard)
304            printf("Device %ld video standard is NTSC\n", device);
305        else if(standard == kPALStandard)
306            printf("Device %ld video standard is PAL\n", device);
307        else
308            printf("Device %ld, unknown video standard %ld\n", device, standard);
309
310	err = sDVFuncs.fDVIsEnabled(refNum, &isEnabled);
311        if(err)
312            printf("Error %d calling DVIsEnabled(%ld)\n", err, device);
313        else
314            printf("Device %ld isEnabled: %d\n", device, isEnabled);
315
316        //sleep(10);
317
318        printf("Destruction test...\n");
319                usleep(4000);	// 4 milliseconds
320        while(true) {
321            err = doStatusTest(refNum, kAVCMechaModeInquiryOpcode, kAVCMechaModeDummyOperand);
322            //if(err)
323                //usleep(4000);	// 4 milliseconds
324            err = doStatusTest6(refNum, kAVCPositionTimeCodeOpcode, kAVCPositionValueInquiry,
325                0xff, 0xff, 0xff, 0xff);
326            //if(err)
327                //usleep(4000);	// 4 milliseconds
328            if(err != noErr) {
329                UInt32 num;
330                num = sDVFuncs.fDVCountDevices();
331                printf("err %d, num devices %d\n", err, num);
332            }
333        }
334        err = sDVFuncs.fDVCloseDriver( refNum );
335        if(err)
336            printf("Error %d calling DVCloseDriver(%ld)\n", err, device);
337
338    }
339
340    // Unload the bundle's executable code.
341    CFBundleUnloadExecutable( myBundle );
342    CFRelease( myBundle );
343    return 0;
344}
345