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