1/*
2 * Copyright (c) 1998-2000 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 *  IOFireWireLibUnitDirectory.cpp
24 *  IOFireWireLib
25 *
26 *  Created by NWG on Thu Apr 27 2000.
27 *  Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
28 *
29 */
30
31#import "IOFireWireLibUnitDirectory.h"
32#import "IOFireWireLibDevice.h"
33
34#import <System/libkern/OSCrossEndian.h>
35
36namespace IOFireWireLib {
37
38	// static interface table
39	LocalUnitDirectory::Interface LocalUnitDirectory::sInterface =
40	{
41		INTERFACEIMP_INTERFACE,
42		1, 0, // version/revision
43		& LocalUnitDirectory::SAddEntry_Ptr,
44		& LocalUnitDirectory::SAddEntry_UInt32,
45		& LocalUnitDirectory::SAddEntry_FWAddress,
46		& LocalUnitDirectory::SPublish,
47		& LocalUnitDirectory::SUnpublish
48	} ;
49
50	// ============================================================
51	// LocalUnitDirectory implementation
52	// ============================================================
53
54	LocalUnitDirectory::LocalUnitDirectory( Device& userclient )
55	: IOFireWireIUnknown( reinterpret_cast<const IUnknownVTbl &>( sInterface) ),
56	  mUserClient(userclient),
57	  mPublished(false)
58	{
59		uint32_t outputCnt = 1;
60		uint64_t outputVal = 0;
61		IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(),
62								  kLocalConfigDirectory_Create,
63								  NULL,0,&outputVal,&outputCnt);
64		mKernUnitDirRef = (UserObjectHandle) outputVal;
65	}
66
67	LocalUnitDirectory::~LocalUnitDirectory()
68	{
69		if (mPublished)
70			Unpublish() ;
71	}
72
73	LocalUnitDirectory::Interface**
74	LocalUnitDirectory::Alloc( Device& userclient )
75	{
76		LocalUnitDirectory*	me = new LocalUnitDirectory( userclient ) ;
77
78		if( !me )
79			return nil ;
80
81		return reinterpret_cast<Interface**>(&me->GetInterface()) ;
82	}
83
84	HRESULT STDMETHODCALLTYPE
85	LocalUnitDirectory::QueryInterface(REFIID iid, LPVOID* ppv)
86	{
87		HRESULT		result = S_OK ;
88		*ppv = nil ;
89
90		CFUUIDRef	interfaceID	= CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, iid) ;
91
92		if (CFEqual(interfaceID, IUnknownUUID) || CFEqual(interfaceID, kIOFireWireLocalUnitDirectoryInterfaceID) )
93		{
94			*ppv = & GetInterface() ;
95			AddRef() ;
96		}
97		else
98		{
99			*ppv = nil ;
100			result = E_NOINTERFACE ;
101		}
102
103		CFRelease(interfaceID) ;
104		return result ;
105	}
106
107	inline const char *
108	CFStringGetChars( CFStringRef string, unsigned & outLen )
109	{
110		CFIndex stringLength = ::CFStringGetLength( string ) ;
111
112		const char * result = ::CFStringGetCStringPtr( string, kCFStringEncodingUTF8 ) ;
113		if ( result )
114		{
115			outLen = (unsigned)stringLength ;
116			return result ;
117		}
118
119		CFIndex bufferSize = ::CFStringGetBytes( string, ::CFRangeMake( 0, stringLength ), kCFStringEncodingUTF8,
120				0xFF, false, NULL, 0, NULL ) ;
121
122		UInt8 inlineBuffer[ bufferSize ] ;
123		result = (char*)inlineBuffer ;
124
125		::CFStringGetBytes( string, ::CFRangeMake( 0, stringLength ), kCFStringEncodingUTF8, 0xFF, false, inlineBuffer, bufferSize, NULL ) ;
126
127		outLen = bufferSize ;
128		return result ;
129	}
130
131	IOReturn
132	LocalUnitDirectory::AddEntry( int key, void* buffer, size_t len, CFStringRef desc )
133	{
134		unsigned descLen = 0;
135		const char * descCString = NULL;
136
137		if( desc )
138		{
139			descCString = CFStringGetChars( desc, descLen ) ;
140		}
141
142		uint32_t outputCnt = 0;
143		const uint64_t inputs[6] = {(const uint64_t)mKernUnitDirRef, key, (const uint64_t)buffer,len, (const uint64_t)descCString, descLen};
144		return IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(), kLocalConfigDirectory_AddEntry_Buffer,
145										 inputs,6,
146										 NULL,&outputCnt);
147	}
148
149	IOReturn
150	LocalUnitDirectory::AddEntry(
151		int			key,
152		UInt32		value,
153		CFStringRef desc )
154	{
155		unsigned descLen = 0;
156		const char * descCString = NULL;
157
158		if( desc )
159		{
160			descCString = CFStringGetChars( desc, descLen ) ;
161		}
162
163		uint32_t outputCnt = 0;
164		const uint64_t inputs[5] = {(const uint64_t)mKernUnitDirRef, key, value, (const uint64_t)descCString, descLen};
165		IOReturn err = IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(), kLocalConfigDirectory_AddEntry_UInt32,
166												 inputs,5,
167												 NULL,&outputCnt);
168
169		DebugLogCond( err, "LocalUnitDirectory::AddEntry[UInt32](): result = 0x%08x\n", err ) ;
170
171		return err ;
172	}
173
174	IOReturn
175	LocalUnitDirectory::AddEntry(
176		int					key,
177		const FWAddress &	value,
178		CFStringRef			desc )
179	{
180		unsigned descLen = 0;
181		const char * descCString = NULL;
182
183		if( desc )
184		{
185			descCString = CFStringGetChars( desc, descLen ) ;
186		}
187
188		FWAddress host_value(value);
189
190#ifndef __LP64__
191		ROSETTA_ONLY(
192			{
193				host_value.nodeID = OSSwapInt16( value.nodeID );
194				host_value.addressHi = OSSwapInt16( value.addressHi );
195				host_value.addressLo = OSSwapInt32( value.addressLo );
196			}
197		);
198#endif
199		uint32_t outputCnt = 0;
200		size_t outputStructSize =  0 ;
201		const uint64_t inputs[4] = {(const uint64_t)mKernUnitDirRef, key, (const uint64_t)descCString,descLen};
202		return IOConnectCallMethod(mUserClient.GetUserClientConnection(),
203								   kLocalConfigDirectory_AddEntry_FWAddr,
204								   inputs,4,
205								   &host_value,sizeof(value),
206								   NULL,&outputCnt,
207								   NULL,&outputStructSize);
208	}
209
210	IOReturn
211	LocalUnitDirectory::Publish()
212	{
213		if (mPublished)
214			return kIOReturnSuccess ;
215
216		uint32_t outputCnt = 0;
217		const uint64_t inputs[1]={(const uint64_t)mKernUnitDirRef};
218
219		IOReturn err = IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(),
220												 kLocalConfigDirectory_Publish,
221												 inputs,1,
222												 NULL,&outputCnt);
223
224		mPublished = ( kIOReturnSuccess == err ) ;
225
226		return err ;
227	}
228
229	IOReturn
230	LocalUnitDirectory::Unpublish()
231	{
232		if (!mPublished)
233			return kIOReturnSuccess ;
234
235		uint32_t outputCnt = 0;
236		const uint64_t inputs[1]={(const uint64_t)mKernUnitDirRef};
237		IOReturn err = IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(),
238												 kLocalConfigDirectory_Unpublish,
239												 inputs,1,
240												 NULL,&outputCnt);
241
242		mPublished = (!err) ;
243
244		return err ;
245	}
246
247	// ============================================================
248	//
249	// static interface methods
250	//
251	// ============================================================
252
253	IOReturn
254	LocalUnitDirectory::SAddEntry_Ptr(
255		DirRef self,
256		int				key,
257		void* 			inBuffer,
258		size_t 			inLen,
259		CFStringRef 	inDesc)
260	{
261		return IOFireWireIUnknown::InterfaceMap<LocalUnitDirectory>::GetThis(self)->AddEntry(key, inBuffer, inLen, inDesc);
262	}
263
264	IOReturn
265	LocalUnitDirectory::SAddEntry_UInt32(
266		DirRef self,
267		int 			key,
268		UInt32 			value,
269		CFStringRef 	inDesc)
270	{
271		return IOFireWireIUnknown::InterfaceMap<LocalUnitDirectory>::GetThis(self)->AddEntry(key, value, inDesc);
272	}
273
274	IOReturn
275	LocalUnitDirectory::SAddEntry_FWAddress(
276		DirRef self,
277		int 				key,
278		const FWAddress*	inAddr,
279		CFStringRef 		inDesc)
280	{
281		return IOFireWireIUnknown::InterfaceMap<LocalUnitDirectory>::GetThis(self)->AddEntry(key, *inAddr, inDesc);
282	}
283
284	IOReturn
285	LocalUnitDirectory::SPublish(
286		DirRef self)
287	{
288		return IOFireWireIUnknown::InterfaceMap<LocalUnitDirectory>::GetThis(self)->Publish();
289	}
290
291	IOReturn
292	LocalUnitDirectory::SUnpublish(
293		DirRef self)
294	{
295		return IOFireWireIUnknown::InterfaceMap<LocalUnitDirectory>::GetThis(self)->Unpublish();
296	}
297}
298