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#include <Carbon/Carbon.h>
25
26//#include <Resources.h>
27//#include <OSUtils.h>
28
29//#include <Components.h>
30
31#include "DeviceControlPriv.h"
32#include "IsochronousDataHandler.h"
33#include "DVVers.h"
34
35#include <stdio.h>
36#include <stdlib.h>
37//#include <syslog.h>	// Debug messages
38
39#include <CoreFoundation/CoreFoundation.h>
40#include <IOKit/IOKitLib.h>
41#include <IOKit/avc/IOFireWireAVCLib.h>
42
43#define DEBUG 0
44
45/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
46
47typedef struct ControlComponentInstance	ControlComponentInstance, *ControlComponentInstancePtr;
48
49struct ControlComponentInstance
50{
51    // Instance variables in MacOS9 version
52    ComponentInstance	self;
53    Boolean		fDeviceEnable;
54    // X Stuff
55    IOFireWireAVCLibUnitInterface **fAVCInterface;
56};
57
58/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
59
60/* QT defines */
61
62#define CALLCOMPONENT_BASENAME() IDHDV
63#define CALLCOMPONENT_GLOBALS()	ControlComponentInstancePtr storage
64
65#define DEVICECONTROL_BASENAME()	FWDVC
66#define DEVICECONTROL_GLOBALS()	ControlComponentInstancePtr storage
67#include "DeviceControl.k.h"
68#include "DeviceControlPriv.k.h"
69
70/* Function prototypes */
71
72pascal ComponentResult
73FWDVCCodecComponentDispatch(ComponentParameters *params, char ** storage);
74
75
76/* ---------------------- Debug Stuff -------------------------- */
77#ifdef DEBUG
78#define FailMessage(cond)		assert (!(cond))
79#else
80#define FailMessage(cond)		{}
81#endif
82#define FailWithVal(cond, handler,num)	\
83        if (cond) {			\
84                goto handler;		\
85        }
86#define FailWithAction(cond, action, handler)	\
87        if (cond) {				\
88                { action; }			\
89                goto handler;			\
90        }
91
92#define FailIf(cond, handler)	\
93        if (cond) {		\
94            FailMessage(false);	\
95                goto handler;	\
96        }
97
98#if DEBUG
99static void print4(UInt32 val)
100{
101    char a, b, c, d;
102    a = val>>24;
103    b = val>>16;
104    c = val>>8;
105    d = val;
106
107    if(a >= ' ' && b >= ' ' && c >= ' ' && d >= ' ')
108        printf("%c%c%c%c", a, b, c, d);
109    else
110        printf(" 0x%x ", (int)val);
111}
112
113static void RecordEventLogger(UInt32 a, UInt32 b, UInt32 c, UInt32 d)
114{
115    if(a)
116    print4(a);
117    if(b)
118    print4(b);
119    if(c)
120    print4(c);
121    if(d)
122    print4(d);
123    printf("\n");
124}
125#else
126#define RecordEventLogger(a, b, c, d)
127#endif
128
129//====================================================================================
130//
131// DoAVCTransaction()
132//
133//	ToDo:
134//====================================================================================
135static pascal ComponentResult
136FWDVCDeviceControlDoAVCTransaction(ControlComponentInstancePtr dc,
137                DVCTransactionParams* inTransaction)
138{
139    if ( dc->fAVCInterface == NULL )
140            return(kIDHErrInvalidDeviceID);
141
142    if ( !dc->fDeviceEnable )
143            return(kIDHErrDeviceDisconnected);
144    return (*dc->fAVCInterface)->AVCCommand(dc->fAVCInterface,
145            inTransaction->commandBufferPtr, inTransaction->commandLength,
146            inTransaction->responseBufferPtr, &inTransaction->responseBufferSize);
147
148}
149
150//====================================================================================
151//
152// EnableAVCTransactions()
153//
154//
155//====================================================================================
156static pascal ComponentResult
157FWDVCDeviceControlEnableAVCTransactions(ControlComponentInstancePtr dc)
158{
159    ComponentResult	result = noErr;
160
161    if ( dc->fAVCInterface != NULL )
162            dc->fDeviceEnable = true;
163    else
164            result = kIDHErrDeviceNotOpened;
165
166    return result;
167}
168
169//====================================================================================
170//
171// DisableAVCTransactions()
172//
173//
174//====================================================================================
175static pascal ComponentResult
176FWDVCDeviceControlDisableAVCTransactions(ControlComponentInstancePtr dc)
177{
178    ComponentResult				result = noErr;
179
180    dc->fDeviceEnable = false;
181
182    return result;
183}
184
185//====================================================================================
186//
187// SetDeviceConnectionID()
188//
189//
190//====================================================================================
191static pascal ComponentResult
192FWDVCDeviceControlSetDeviceConnectionID(
193                            ControlComponentInstancePtr dc, DeviceConnectionID connectionID)
194{
195    ComponentResult		result = noErr;
196
197    if ( dc->fDeviceEnable )
198            result = kIDHErrDeviceInUse;
199    else {
200        if(dc->fAVCInterface != NULL)
201            (*dc->fAVCInterface)->Release(dc->fAVCInterface);
202        dc->fAVCInterface = (IOFireWireAVCLibUnitInterface **)(connectionID);
203        if(dc->fAVCInterface != NULL)
204            (*dc->fAVCInterface)->AddRef(dc->fAVCInterface);
205    }
206
207    return result;
208}
209
210//====================================================================================
211//
212// GetDeviceConnectionID()
213//
214//
215//====================================================================================
216static pascal ComponentResult
217FWDVCDeviceControlGetDeviceConnectionID(
218                            ControlComponentInstancePtr dc, DeviceConnectionID* connectionID)
219{
220    *connectionID = (DeviceConnectionID)dc->fAVCInterface;
221    return noErr;
222}
223
224/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
225
226static pascal ComponentResult
227FWDVCComponentOpen(ControlComponentInstancePtr storage, ComponentInstance self)
228{
229    kern_return_t err = noErr;
230
231    RecordEventLogger( 'devc', 'open', 0, 0);
232    storage = (ControlComponentInstancePtr)NewPtrClear(sizeof(ControlComponentInstance));
233    if( nil == storage)
234        return(MemError());
235    RecordEventLogger( 'devc', 'ope2', (int)storage, 0);
236
237    SetComponentInstanceStorage(self, (Handle) storage);
238
239//Exit:
240
241    return( err );
242}
243
244/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
245
246static pascal ComponentResult
247FWDVCComponentClose(ControlComponentInstancePtr storage, ComponentInstance self)
248{
249    RecordEventLogger( 'devc', 'clos', 0, (unsigned long) storage);
250    if( !storage)
251        return( noErr );
252
253    if(storage->fAVCInterface != NULL)
254        (*storage->fAVCInterface)->Release(storage->fAVCInterface);
255    DisposePtr((Ptr) storage);
256
257    SetComponentInstanceStorage(self, (Handle) nil );
258
259    return( noErr );
260}
261
262/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
263
264static pascal ComponentResult
265FWDVCComponentVersion(ControlComponentInstancePtr storage)
266{
267    RecordEventLogger( 'devc', 'vers', 0, 0);
268    return 0x10001;
269}
270
271static pascal ComponentResult
272FWDVCComponentRegister(ControlComponentInstancePtr storage)
273{
274    // need to re-register with each source type?
275    RecordEventLogger( 'devc', 'reg ', 0, 0);
276    return( noErr );
277}
278
279/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
280/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
281
282#define DoCDispatchWS(x,p,s)		\
283    case k ## x ## Select:		\
284        /* printf("FWDV" #x "{"); */	\
285        { ComponentResult err;		\
286            err = CallComponentFunctionWithStorageProcInfo( s, p, (ProcPtr) FWDVC ## x,	\
287                                                uppCall ## x ## ProcInfo );		\
288        /* printf("%ld}\n", err); */	\
289        return err;	}
290
291#define DoDispatchWS(x,p,s)		\
292    case k ## x ## Select:		\
293        /* printf("FWDV" #x "{"); */	\
294        { ComponentResult err;		\
295            err = CallComponentFunctionWithStorageProcInfo( s, p, (ProcPtr) FWDVC ## x,	\
296                                                upp ## x ## ProcInfo );			\
297        /* printf("%ld}\n", err); */ 	\
298        return err;	}
299
300
301static pascal ComponentResult
302FWDVCComponentCanDo(ControlComponentInstancePtr storage, short selector)
303{
304    RecordEventLogger( 'devc', 'cand', 0, 0);
305
306    switch(selector) {
307        /* Standard selectors */
308        case kComponentOpenSelect:
309        case kComponentCloseSelect:
310        case kComponentCanDoSelect:
311        case kComponentVersionSelect:
312
313        /* Device Control selectors */
314        case kDeviceControlDoAVCTransactionSelect:
315        case kDeviceControlEnableAVCTransactionsSelect:
316        case kDeviceControlDisableAVCTransactionsSelect:
317        case kDeviceControlSetDeviceConnectionIDSelect:
318        case kDeviceControlGetDeviceConnectionIDSelect:
319
320            return(true);
321
322        default:
323            RecordEventLogger( 'devc', 'cant', selector, 0);
324            return (false);
325    }
326}
327
328
329pascal ComponentResult
330FWDVCCodecComponentDispatch(ComponentParameters *params, char ** storage)
331{
332    ComponentResult result;
333
334    /*	If the selector is less than zero, it's a Component manager selector.	*/
335
336    if ( params->what < 0  ) {
337        switch ( params->what ) {
338            DoCDispatchWS( ComponentOpen, params, storage );
339            DoCDispatchWS( ComponentClose, params, storage );
340            DoCDispatchWS( ComponentRegister, params, storage );
341            DoCDispatchWS( ComponentCanDo, params, storage );
342            DoCDispatchWS( ComponentVersion, params, storage );
343
344            default :
345                return (paramErr);
346        }
347    }
348
349    /*
350     *	Here we dispatch the rest of our calls. We use the magic thing manager routine which
351     *	calls our subroutines with the proper parameters. The prototypes are in Image Codec.h.
352     */
353    switch ( params->what ) {
354        DoDispatchWS( DeviceControlDoAVCTransaction, params, storage );
355        DoDispatchWS( DeviceControlEnableAVCTransactions, params, storage );
356        DoDispatchWS( DeviceControlDisableAVCTransactions, params, storage );
357        DoDispatchWS( DeviceControlSetDeviceConnectionID, params, storage );
358        DoDispatchWS( DeviceControlGetDeviceConnectionID, params, storage );
359
360    default:
361        {
362            int len = params->paramSize/4;
363            int i;
364            printf("DVC unimp:%d %d ", params->what, params->paramSize);
365            for(i=0; i<len; i++)
366                printf("0x%lx ", params->params[i]);
367            printf("\n");
368            result = paramErr;
369            return(result);
370        }
371    }
372}
373
374
375