1 /*---------------------------------------------------------------------------*
2   Project:  Host I/O Interface for HIO2
3   File:     Hio2If.c
4 
5   (C)2005 HUDSON SOFT
6 
7   $Header: /home/cvsroot/SDK/build/demos/hio2demo/HioIf/src/Hio2If.c,v 1.2 2006/03/09 12:28:43 yasuh-to Exp $
8 
9   $NoKeywords: $
10  *---------------------------------------------------------------------------*/
11 
12 #include <stdio.h>
13 #include <stdarg.h>
14 #include <revolution.h>
15 #include "Hio2If.h"
16 
17 //#define	HIO2IF_DEBUG
18 
19 // device information
20 static s32	hio2DevCount = 0;
21 static HIO2DeviceType	hio2Devices[HIO2_CHAN_MAX + 1] =
22 {
23 	HIO2_DEVICE_INVALID,
24 	HIO2_DEVICE_INVALID,
25 	HIO2_DEVICE_INVALID
26 };
27 
28 // error
29 static HIO2IF_ERROR	hio2LastError = HIO2IF_ERROR_NONE;
30 static char	hio2Message[128] = { '\0' };
31 
32 // status
33 static HIO2IF_STATUS	hio2Status[HIO2_CHAN_MAX] =
34 {
35 	{
36 		HIO2_DEVICE_INVALID,
37 		HIO2IF_INVALID_ID,
38 		HIO2_INVALID_HANDLE_VALUE,
39 		HIO2IF_MODE_NONE,
40 		FALSE,
41 		FALSE,
42 		FALSE,
43 		HIO2IF_ASYNC_NONE,
44 		NULL,
45 		0,
46 		NULL
47 	},
48 	{
49 		HIO2_DEVICE_INVALID,
50 		HIO2IF_INVALID_ID,
51 		HIO2_INVALID_HANDLE_VALUE,
52 		HIO2IF_MODE_NONE,
53 		FALSE,
54 		FALSE,
55 		FALSE,
56 		HIO2IF_ASYNC_NONE,
57 		NULL,
58 		0,
59 		NULL
60 	},
61 };
62 
63 // packet command for Open
64 static const u8	hio2PacketCmd[] =
65 {
66 	HIO2IF_CMD_OPEN_RDONLY,
67 	HIO2IF_CMD_OPEN_WRONLY,
68 	HIO2IF_CMD_OPEN_RDWR,
69 };
70 
71 // initialize flag
72 static BOOL	hio2Initialized = FALSE;
73 
74 // error strings
75 static const char*	hio2ErrorStrings[HIO2IF_ERROR_MAX] =
76 {
77 
78 #include "Hio2IfErr.str"
79 
80 };
81 
82 ///////////////////////////////////////////////////////////////////////////////
83 //
84 // inline function definition
85 //
86 
87 // Gets HIO2IF_ID from HIO2 handle
88 static inline
hio2GetIdOfHandle(HIO2Handle h)89 s32	hio2GetIdOfHandle(HIO2Handle h)
90 {
91 	return (hio2Status[0].hHIO == h) ? 0 : 1;
92 }
93 
94 ///////////////////////////////////////////////////////////////////////////////
95 //
96 // callback definition
97 //
98 
99 // HIO2EnumDevice() - callback
100 static
hio2EnumCallback(HIO2DeviceType type)101 BOOL	hio2EnumCallback( HIO2DeviceType type )
102 {
103 #ifdef HIO2IF_DEBUG
104 	OSReport("Device = %d\n", type);
105 #endif
106 	hio2Devices[hio2DevCount++] = type;
107 	return TRUE;
108 }
109 
110 // callback for receive mail
111 static
hio2ReceiveCallback(HIO2Handle h)112 void	hio2ReceiveCallback( HIO2Handle h )
113 {
114 	s32 id;
115 	HIO2IF_EVENT event;
116 	u32 mail = 0;
117 
118 	(void)HIO2ReadMailbox(h, &mail);
119 	id = hio2GetIdOfHandle(h);
120 
121 	switch ( HIO2IF_GET_PACKET_CMD(mail) )
122 	{
123 	case HIO2IF_CMD_OPEN_RESULT:
124 		hio2Status[id].nPc		= HIO2IF_GET_PACKET_CHAN(mail);
125 		hio2Status[id].bConnect = TRUE;
126 		event = HIO2IF_EVENT_CONNECT;
127 		break;
128 	case HIO2IF_CMD_SEND:
129 		hio2Status[id].bReceived = TRUE;
130 		event = HIO2IF_EVENT_RECEIVED;
131 		break;
132 	case HIO2IF_CMD_SEND_RESULT:
133 		hio2Status[id].bSendPossible = TRUE;
134 		event = HIO2IF_EVENT_SEND_POSSIBLE;
135 		break;
136 	case HIO2IF_CMD_CLOSE:
137 		// the actual close process must be done in the application
138 		hio2Status[id].bConnect = FALSE;
139 		event = HIO2IF_EVENT_DISCONNECT;
140 		break;
141 	default:
142 		event = HIO2IF_EVENT_UNKOWN;
143 	}
144 
145 	// event callback function call
146 	if ( hio2Status[id].fncCallback != NULL )
147 		hio2Status[id].fncCallback(id, event);
148 }
149 
150 // callback for HIO2ReadAsync()
151 static
hio2ReadAsyncCallback(HIO2Handle h)152 void	hio2ReadAsyncCallback( HIO2Handle h )
153 {
154 	s32 id = hio2GetIdOfHandle(h);
155 	u32 async = HIO2IF_ASYNC_READ_MASK(hio2Status[id].dwAsyncMode);
156 
157 	DCInvalidateRange((void *)hio2Status[id].pReadAsyncPtr,
158 					  hio2Status[id].dwReadAsyncSize);
159 
160 	// If "async" is specified by Read, notify the connection target of the read completion; notification is unnecessary for ReadFree
161 	//
162 	if ( async & HIO2IF_ASYNC_READ )
163 	{
164 		(void)HIO2WriteMailbox(
165 			hio2Status[id].hHIO,
166 			HIO2IF_SET_PACKET(hio2Status[id].nType, HIO2IF_CMD_SEND_RESULT));
167 	}
168 
169 	hio2Status[id].dwAsyncMode &= ~async;
170 
171 	// Event callback function call
172 	if (hio2Status[id].fncCallback != NULL )
173 		hio2Status[id].fncCallback(id, HIO2IF_EVENT_READ_ASYNC_DONE);
174 }
175 
176 // Callback for HIO2WriteAsync()
177 static
hio2WriteAsyncCallback(HIO2Handle h)178 void	hio2WriteAsyncCallback( HIO2Handle h )
179 {
180 	s32 id = hio2GetIdOfHandle(h);
181 	u32 async = HIO2IF_ASYNC_WRITE_MASK(hio2Status[id].dwAsyncMode);
182 
183 	// If "async" is specified by Write, notify the connection target of the write; notification is unnecessary for WriteFree
184 	//
185 	if ( async & HIO2IF_ASYNC_WRITE )
186 	{
187 		(void)HIO2WriteMailbox(
188 			hio2Status[id].hHIO,
189 			HIO2IF_SET_PACKET(hio2Status[id].nType, HIO2IF_CMD_SEND));
190 	}
191 
192 	hio2Status[id].dwAsyncMode &= ~async;
193 
194 	// event callback function call
195 	if ( hio2Status[id].fncCallback != NULL )
196 		hio2Status[id].fncCallback(id, HIO2IF_EVENT_WRITE_ASYNC_DONE);
197 }
198 
199 // callback for disconnect
200 static
hio2DisconnectCallback(HIO2Handle h)201 void	hio2DisconnectCallback( HIO2Handle h )
202 {
203 	s32 id = hio2GetIdOfHandle(h);
204 
205 	(void)sprintf(hio2Message, "INTERRUPT, EXI device(%d)",
206 				  hio2Status[id].nType);
207 
208 	// event callback function call
209 	if ( hio2Status[id].fncCallback != NULL )
210 		hio2Status[id].fncCallback(id, HIO2IF_EVENT_INTERRUPT);
211 
212 	hio2Status[id].nType			= HIO2_DEVICE_INVALID;
213 	hio2Status[id].nPc				= HIO2IF_INVALID_ID;
214 	hio2Status[id].hHIO				= HIO2_INVALID_HANDLE_VALUE;
215 	hio2Status[id].nMode			= HIO2IF_MODE_NONE;
216 	hio2Status[id].bConnect			= FALSE;
217 	hio2Status[id].bReceived		= FALSE;
218 	hio2Status[id].bSendPossible	= FALSE;
219 	hio2Status[id].fncCallback		= NULL;
220 }
221 
222 //-----------------------------------------------------------------------------
223 // local function definition
224 
225 static
hio2SetFatal(HIO2IF_ERROR errID,...)226 HIO2IF_RESULT	hio2SetFatal( HIO2IF_ERROR errID, ... )
227 {
228 	va_list argptr;
229 
230 	va_start(argptr, errID);
231 	(void)vsprintf(hio2Message, (char*)hio2ErrorStrings[errID], argptr);
232 	va_end(argptr);
233 
234 	hio2LastError = errID;
235 
236 	return HIO2IF_RESULT_FATAL;
237 }
238 
239 static
hio2SetError(HIO2IF_ERROR errID,...)240 HIO2IF_RESULT	hio2SetError( HIO2IF_ERROR errID, ... )
241 {
242 	va_list argptr;
243 
244 	va_start(argptr, errID);
245 	(void)vsprintf(hio2Message, (char*)hio2ErrorStrings[errID], argptr);
246 	va_end(argptr);
247 
248 	hio2LastError = errID;
249 
250 	return HIO2IF_RESULT_ERROR;
251 }
252 
253 ///////////////////////////////////////////////////////////////////////////////
254 //
255 // Host I/O interface for NNGC
256 //
257 
258 //-----------------------------------------------------------------------------
HIO2IFGetDeviceCount(void)259 s32	HIO2IFGetDeviceCount( void )
260 {
261 	return hio2DevCount;
262 }
263 
264 //-----------------------------------------------------------------------------
HIO2IFGetDevice(s32 index)265 HIO2DeviceType	HIO2IFGetDevice( s32 index )
266 {
267 	ASSERT((index >= 0) && (index < (HIO2_CHAN_MAX + 1)));
268 	return hio2Devices[index];
269 }
270 
271 //-----------------------------------------------------------------------------
HIO2IFInit(void)272 HIO2IF_RESULT	HIO2IFInit( void )
273 {
274 	// when initialized, terminate HIO2
275 	if ( hio2Initialized ) HIO2Exit();
276 
277 	hio2DevCount = 0;
278 	hio2Devices[0] = hio2Devices[1] =
279 	hio2Status[0].nType = hio2Status[1].nType = HIO2_DEVICE_INVALID;
280 
281 	// HIO2 initialization
282 	if ( !HIO2Init() )
283 		return hio2SetFatal(HIO2IF_FATAL_INIT, HIO2GetLastError());
284 
285 	// search for an EXI device
286 	if ( !HIO2EnumDevices(hio2EnumCallback) )
287 		return hio2SetFatal(HIO2IF_FATAL_ENUMDEVICES, HIO2GetLastError());
288 
289 	hio2Initialized = TRUE;
290 
291 	return HIO2IF_RESULT_SUCCESS;
292 }
293 
294 //-----------------------------------------------------------------------------
HIO2IFOpen(HIO2DeviceType type,HIO2IF_MODE mode,HIO2IF_EVENT_CALLBACK callback,HIO2IF_ID * id)295 HIO2IF_RESULT	HIO2IFOpen( HIO2DeviceType type, HIO2IF_MODE mode,
296 							HIO2IF_EVENT_CALLBACK callback, HIO2IF_ID* id )
297 {
298 	*id = HIO2IF_INVALID_ID;
299 
300 	// When an EXI channel has not been detected
301 	if ( type == HIO2_DEVICE_INVALID )
302 		return hio2SetError(HIO2IF_ERROR_CHAN_NOT_FIND, type);
303 
304 	// When the specified EXI channel is in use
305 	if ( (type == hio2Status[0].nType) || (type == hio2Status[1].nType) )
306 		return hio2SetError(HIO2IF_ERROR_CHAN_ALREADY_OPENED, type);
307 
308 	// Search for an available ID
309 	*id = (hio2Status[0].nType == HIO2IF_INVALID_ID) ? 0 : 1;
310 
311 	hio2Status[*id].hHIO =
312 		HIO2Open(type, hio2ReceiveCallback, hio2DisconnectCallback);
313 	if ( hio2Status[*id].hHIO == HIO2_INVALID_HANDLE_VALUE )
314 		return hio2SetFatal(HIO2IF_FATAL_OPEN, type, HIO2GetLastError());
315 
316 	hio2Status[*id].nType			= type;
317 	hio2Status[*id].nMode			= mode;
318 	hio2Status[*id].bConnect		= FALSE;
319 	hio2Status[*id].bReceived		= FALSE;
320 	hio2Status[*id].bSendPossible	= TRUE;
321 	hio2Status[*id].fncCallback		= callback;
322 
323 	// Open notification
324 	(void)HIO2WriteMailbox(hio2Status[*id].hHIO,
325 						   HIO2IF_SET_PACKET(type, hio2PacketCmd[mode]));
326 
327 	return HIO2IF_RESULT_SUCCESS;
328 }
329 
330 //-----------------------------------------------------------------------------
HIO2IFRead(HIO2IF_ID id,u32 addr,void * buffer,s32 size,BOOL async)331 HIO2IF_RESULT	HIO2IFRead( HIO2IF_ID id, u32 addr, void* buffer, s32 size,
332 							BOOL async )
333 {
334 	if ( id == HIO2IF_INVALID_ID ) return hio2SetError(HIO2IF_ERROR_INVALID_ID);
335 	// For the write-only mode
336 	if ( hio2Status[id].nMode == HIO2IF_MODE_WRONLY )
337 		return hio2SetError(HIO2IF_ERROR_WRITE_ONLY, hio2Status[id].nType);
338 
339 	// Not connected to the PC
340 	if ( !hio2Status[id].bConnect )
341 		return hio2SetError(HIO2IF_ERROR_NOT_CONNECT, hio2Status[id].nType);
342 
343 	// When data has not been received
344 	if ( !hio2Status[id].bReceived )
345 		return hio2SetError(HIO2IF_ERROR_NOT_RECV_DATA, hio2Status[id].nType);
346 
347 	hio2Status[id].bReceived = FALSE;
348 
349 	// Synchronous Read
350 	if ( !async )
351 	{
352 		if ( !HIO2Read(hio2Status[id].hHIO, addr, buffer, size) )
353 			return hio2SetFatal(HIO2IF_FATAL_READ,
354 								hio2Status[id].nType, HIO2GetLastError());
355 
356 		DCInvalidateRange(buffer, (u32)size);
357 
358 		// Perform a Read completion notification to the connection target
359 		(void)HIO2WriteMailbox(
360 			hio2Status[id].hHIO,
361 			HIO2IF_SET_PACKET(hio2Status[id].nType, HIO2IF_CMD_SEND_RESULT));
362 	}
363 	// Asynchronous Read
364 	else
365 	{
366 		hio2Status[id].dwAsyncMode		|= HIO2IF_ASYNC_READ;
367 		hio2Status[id].pReadAsyncPtr	= buffer;
368 		hio2Status[id].dwReadAsyncSize	= (u32)size;
369 
370 		if ( !HIO2ReadAsync(hio2Status[id].hHIO, addr, buffer, size,
371 							hio2ReadAsyncCallback) )
372 			return hio2SetFatal(HIO2IF_FATAL_READ,
373 								hio2Status[id].nType, HIO2GetLastError());
374 	}
375 
376 	return HIO2IF_RESULT_SUCCESS;
377 }
378 
379 //-----------------------------------------------------------------------------
HIO2IFReadFree(HIO2IF_ID id,u32 addr,void * buffer,s32 size,BOOL async)380 HIO2IF_RESULT	HIO2IFReadFree( HIO2IF_ID id, u32 addr, void* buffer, s32 size,
381 								BOOL async )
382 {
383 	if ( id == HIO2IF_INVALID_ID ) return hio2SetError(HIO2IF_ERROR_INVALID_ID);
384 	// For the write-only mode
385 	if ( hio2Status[id].nMode == HIO2IF_MODE_WRONLY )
386 		return hio2SetError(HIO2IF_ERROR_WRITE_ONLY, hio2Status[id].nType);
387 
388 	// Not connected to the PC
389 	if ( !hio2Status[id].bConnect )
390 		return hio2SetError(HIO2IF_ERROR_NOT_CONNECT, hio2Status[id].nType);
391 
392 	// Synchronous Read
393 	if ( !async )
394 	{
395 		if ( !HIO2Read(hio2Status[id].hHIO, addr, buffer, size) )
396 			return hio2SetFatal(HIO2IF_FATAL_READ,
397 								hio2Status[id].nType, HIO2GetLastError());
398 
399 		DCInvalidateRange(buffer, (u32)size);
400 	}
401 	// Asynchronous Read
402 	else
403 	{
404 		// The previous ReadAsync or WriteAsync is not completed
405 		if  ( hio2Status[id].dwAsyncMode )
406 			return hio2SetError(HIO2IF_ERROR_BUSY, hio2Status[id].nType);
407 
408 		hio2Status[id].dwAsyncMode		|= HIO2IF_ASYNC_READ_FREE;
409 		hio2Status[id].pReadAsyncPtr	= buffer;
410 		hio2Status[id].dwReadAsyncSize	= (u32)size;
411 
412 		if ( !HIO2ReadAsync(hio2Status[id].hHIO, addr, buffer, size,
413 							hio2ReadAsyncCallback) )
414 			return hio2SetFatal(HIO2IF_FATAL_READ,
415 								hio2Status[id].nType, HIO2GetLastError());
416 
417 	}
418 
419 	return HIO2IF_RESULT_SUCCESS;
420 }
421 
422 //-----------------------------------------------------------------------------
HIO2IFWrite(HIO2IF_ID id,u32 addr,void * buffer,s32 size,BOOL async)423 HIO2IF_RESULT	HIO2IFWrite( HIO2IF_ID id, u32 addr, void* buffer, s32 size,
424 							 BOOL async )
425 {
426 	if ( id == HIO2IF_INVALID_ID ) return hio2SetError(HIO2IF_ERROR_INVALID_ID);
427 	// For the read-only mode
428 	if ( hio2Status[id].nMode == HIO2IF_MODE_RDONLY )
429 		return hio2SetError(HIO2IF_ERROR_READ_ONLY, hio2Status[id].nType);
430 
431 	// Not connected to the PC
432 	if ( !hio2Status[id].bConnect )
433 		return hio2SetError(HIO2IF_ERROR_NOT_CONNECT, hio2Status[id].nType);
434 
435 	// When it can't be sent (when the target cannot receive data)
436 	if ( !hio2Status[id].bSendPossible )
437 	{
438 		return hio2SetError(HIO2IF_ERROR_CANNOT_SEND_DATA,
439 							hio2Status[id].nType);
440 	}
441 
442 	hio2Status[id].bSendPossible = FALSE;
443 
444 	DCFlushRange(buffer, (u32)size);
445 
446 	// Synchronous Write
447 	if ( !async )
448 	{
449 		if ( !HIO2Write(hio2Status[id].hHIO, addr, buffer, size) )
450 			return hio2SetFatal(HIO2IF_FATAL_WRITE,
451 								hio2Status[id].nType, HIO2GetLastError());
452 
453 		// Perform a Write notification to the connection target
454 		(void)HIO2WriteMailbox(
455 			hio2Status[id].hHIO,
456 			HIO2IF_SET_PACKET(hio2Status[id].nType, HIO2IF_CMD_SEND));
457 	}
458 	// Asynchronous Write
459 	else
460 	{
461 		hio2Status[id].dwAsyncMode |= HIO2IF_ASYNC_WRITE;
462 		if ( !HIO2WriteAsync(hio2Status[id].hHIO, addr, buffer, size,
463 							 hio2WriteAsyncCallback) )
464 			return hio2SetFatal(HIO2IF_FATAL_WRITE,
465 								hio2Status[id].nType, HIO2GetLastError());
466 	}
467 
468 	return HIO2IF_RESULT_SUCCESS;
469 }
470 
471 //-----------------------------------------------------------------------------
HIO2IFWriteFree(HIO2IF_ID id,u32 addr,void * buffer,s32 size,BOOL async)472 HIO2IF_RESULT	HIO2IFWriteFree( HIO2IF_ID id, u32 addr, void* buffer,
473 								 s32 size, BOOL async )
474 {
475 	if ( id == HIO2IF_INVALID_ID ) return hio2SetError(HIO2IF_ERROR_INVALID_ID);
476 	// For the read-only mode
477 	if ( hio2Status[id].nMode == HIO2IF_MODE_RDONLY )
478 		return hio2SetError(HIO2IF_ERROR_READ_ONLY, hio2Status[id].nType);
479 
480 	// Not connected to the PC
481 	if ( !hio2Status[id].bConnect )
482 		return hio2SetError(HIO2IF_ERROR_NOT_CONNECT, hio2Status[id].nType);
483 
484 	DCFlushRange(buffer, (u32)size);
485 
486 	// Synchronous Write
487 	if ( !async )
488 	{
489 		if ( !HIO2Write(hio2Status[id].hHIO, addr, buffer, size) )
490 			return hio2SetFatal(HIO2IF_FATAL_WRITE,
491 								hio2Status[id].nType, HIO2GetLastError());
492 	}
493 	// Asynchronous Write
494 	else
495 	{
496 		// The previous ReadAsync or WriteAsync is not completed
497 		if  ( hio2Status[id].dwAsyncMode )
498 			return hio2SetError(HIO2IF_ERROR_BUSY, hio2Status[id].nType);
499 
500 		hio2Status[id].dwAsyncMode |= HIO2IF_ASYNC_WRITE_FREE;
501 		if ( !HIO2WriteAsync(hio2Status[id].hHIO, addr, buffer, size,
502 							 hio2WriteAsyncCallback) )
503 			return hio2SetFatal(HIO2IF_FATAL_WRITE,
504 								hio2Status[id].nType, HIO2GetLastError());
505 	}
506 
507 	return HIO2IF_RESULT_SUCCESS;
508 }
509 
510 //-----------------------------------------------------------------------------
HIO2IFReadStatus(HIO2IF_ID id,u32 * status)511 HIO2IF_RESULT	HIO2IFReadStatus( HIO2IF_ID id, u32* status )
512 {
513 	if ( id == HIO2IF_INVALID_ID ) return hio2SetError(HIO2IF_ERROR_INVALID_ID);
514 	// Not connected to the PC
515 	if ( !hio2Status[id].bConnect )
516 		return hio2SetError(HIO2IF_ERROR_NOT_CONNECT, hio2Status[id].nType);
517 
518 	return HIO2ReadStatus(hio2Status[id].hHIO, status)
519 		? HIO2IF_RESULT_SUCCESS
520 		: hio2SetFatal(HIO2IF_FATAL_READSTATUS, hio2Status[id].nType,
521 					   HIO2GetLastError());
522 }
523 
524 //-----------------------------------------------------------------------------
HIO2IFClose(HIO2IF_ID id)525 HIO2IF_RESULT	HIO2IFClose( HIO2IF_ID id )
526 {
527 	BOOL result;
528 	s32 chan;
529 
530 	if ( id == HIO2IF_INVALID_ID ) return hio2SetError(HIO2IF_ERROR_INVALID_ID);
531 	chan = hio2Status[id].nType;
532 
533 	// Perform a close notification when connected to the target
534 	if ( hio2Status[id].bConnect )
535 	{
536 		(void)HIO2WriteMailbox(hio2Status[id].hHIO,
537 							   HIO2IF_SET_PACKET(chan, HIO2IF_CMD_CLOSE));
538 	}
539 
540 	result = HIO2Close(hio2Status[id].hHIO);
541 
542 	hio2Status[id].nType			= (HIO2DeviceType)HIO2IF_INVALID_ID;
543 	hio2Status[id].nPc				= HIO2IF_INVALID_ID;
544 	hio2Status[id].hHIO				= HIO2_INVALID_HANDLE_VALUE;
545 	hio2Status[id].nMode			= HIO2IF_MODE_NONE;
546 	hio2Status[id].bConnect			= FALSE;
547 	hio2Status[id].bReceived		= FALSE;
548 	hio2Status[id].bSendPossible	= FALSE;
549 	hio2Status[id].fncCallback		= NULL;
550 
551 	return result ? HIO2IF_RESULT_SUCCESS
552 		: hio2SetFatal(HIO2IF_FATAL_CLOSE, chan, HIO2GetLastError());
553 }
554 
555 //-----------------------------------------------------------------------------
HIO2IFSync(void)556 void	HIO2IFSync( void )
557 {
558 	// Perform an open notification when the EXI channel is opened, and a connection to the PC has not been made
559 	//
560 	if ( (hio2Status[0].hHIO != HIO2_INVALID_HANDLE_VALUE)
561 		 && (!hio2Status[0].bConnect) )
562 	{
563 		(void)HIO2WriteMailbox(
564 			hio2Status[0].hHIO,
565 			HIO2IF_SET_PACKET(hio2Status[0].nType,
566 							 hio2PacketCmd[hio2Status[0].nMode]));
567 	}
568 
569 	if ( (hio2Status[1].hHIO != HIO2_INVALID_HANDLE_VALUE)
570 		 && (!hio2Status[1].bConnect) )
571 	{
572 		// Open notification
573 		(void)HIO2WriteMailbox(
574 			hio2Status[1].hHIO,
575 			HIO2IF_SET_PACKET(hio2Status[1].nType,
576 							  hio2PacketCmd[hio2Status[1].nMode]));
577 	}
578 }
579 
580 //-----------------------------------------------------------------------------
HIO2IFExit(void)581 void	HIO2IFExit( void )
582 {
583 	// Perform a close notification when EXI channel is opened, and connection to the PC is available
584 	if ( (hio2Status[0].hHIO != HIO2_INVALID_HANDLE_VALUE)
585 		 && (hio2Status[0].bConnect) )
586 	{
587 		(void)HIO2IFClose(0);
588 	}
589 
590 	if ( (hio2Status[1].hHIO != HIO2_INVALID_HANDLE_VALUE)
591 		 && (hio2Status[1].bConnect) )
592 	{
593 		(void)HIO2IFClose(1);
594 	}
595 
596 	// HIO2Exit() force-closes opened channels
597 	HIO2Exit();
598 
599 	hio2Initialized = FALSE;
600 }
601 
602 //-----------------------------------------------------------------------------
HIO2IFIsConnected(HIO2IF_ID id)603 BOOL	HIO2IFIsConnected( HIO2IF_ID id )
604 {
605 	return  (id != HIO2IF_INVALID_ID) ? hio2Status[id].bConnect : FALSE;
606 }
607 
608 //-----------------------------------------------------------------------------
HIO2IFIsReceived(HIO2IF_ID id)609 BOOL	HIO2IFIsReceived( HIO2IF_ID id )
610 {
611 	return  (id != HIO2IF_INVALID_ID) ? hio2Status[id].bReceived : FALSE;
612 }
613 
614 //-----------------------------------------------------------------------------
HIO2IFIsSendPossible(HIO2IF_ID id)615 BOOL	HIO2IFIsSendPossible( HIO2IF_ID id )
616 {
617 	return  (id != HIO2IF_INVALID_ID) ? hio2Status[id].bSendPossible : FALSE;
618 }
619 
620 //-----------------------------------------------------------------------------
HIO2IFGetDeviceType(HIO2IF_ID id)621 HIO2DeviceType	HIO2IFGetDeviceType( HIO2IF_ID id )
622 {
623 	return (id != HIO2IF_INVALID_ID)
624 		? hio2Status[id].nType : HIO2_DEVICE_INVALID;
625 }
626 
627 //-----------------------------------------------------------------------------
HIO2IFGetPcChan(HIO2IF_ID id)628 s32	HIO2IFGetPcChan( HIO2IF_ID id )
629 {
630 	return (id != HIO2IF_INVALID_ID) ? hio2Status[id].nPc : -1;
631 }
632 
633 //-----------------------------------------------------------------------------
HIO2IFGetLastError(void)634 HIO2IF_ERROR	HIO2IFGetLastError( void )
635 {
636 	return hio2LastError;
637 }
638 
639 //-----------------------------------------------------------------------------
HIO2IFGetErrorMessage(void)640 const char*		HIO2IFGetErrorMessage( void )
641 {
642 	return hio2Message;
643 }
644 
645 // end of Hio2If.c
646