/*******************************************************************
 Copyright © 1995 - 1998, 3Com Corporation or its subsidiaries ("3Com").  
 All rights reserved.
   
 This software may be copied and used solely for developing products for 
 the Palm Computing platform and for archival and backup purposes.  Except 
 for the foregoing, no part of this software may be reproduced or transmitted 
 in any form or by any means or used to make any derivative work (such as 
 translation, transformation or adaptation) without express written consent 
 from 3Com.

 3Com reserves the right to revise this software and to make changes in content 
 from time to time without obligation on the part of 3Com to provide notification 
 of such revision or changes.  
 3COM MAKES NO REPRESENTATIONS OR WARRANTIES THAT THE SOFTWARE IS FREE OF ERRORS 
 OR THAT THE SOFTWARE IS SUITABLE FOR YOUR USE.  THE SOFTWARE IS PROVIDED ON AN 
 "AS IS" BASIS.  3COM MAKES NO WARRANTIES, TERMS OR CONDITIONS, EXPRESS OR IMPLIED, 
 EITHER IN FACT OR BY OPERATION OF LAW, STATUTORY OR OTHERWISE, INCLUDING WARRANTIES, 
 TERMS, OR CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND 
 SATISFACTORY QUALITY.

 TO THE FULL EXTENT ALLOWED BY LAW, 3COM ALSO EXCLUDES FOR ITSELF AND ITS SUPPLIERS 
 ANY LIABILITY, WHETHER BASED IN CONTRACT OR TORT (INCLUDING NEGLIGENCE), FOR 
 DIRECT, INCIDENTAL, CONSEQUENTIAL, INDIRECT, SPECIAL, OR PUNITIVE DAMAGES OF 
 ANY KIND, OR FOR LOSS OF REVENUE OR PROFITS, LOSS OF BUSINESS, LOSS OF INFORMATION 
 OR DATA, OR OTHER FINANCIAL LOSS ARISING OUT OF OR IN CONNECTION WITH THIS SOFTWARE, 
 EVEN IF 3COM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

 3Com, HotSync, Palm Computing, and Graffiti are registered trademarks, and 
 Palm III and Palm OS are trademarks of 3Com Corporation or its subsidiaries.

 IF THIS SOFTWARE IS PROVIDED ON A COMPACT DISK, THE OTHER SOFTWARE AND 
 DOCUMENTATION ON THE COMPACT DISK ARE SUBJECT TO THE LICENSE AGREEMENT 
 ACCOMPANYING THE COMPACT DISK.

 *-------------------------------------------------------------------
 * FileName:
 *		SerialLinkMgr.c
 *
 * Description:
 *		Source for Serial Link Routines on Pilot
 *
 * History:
 *   	2/6/95 replaces DSerial.h from Debugger 
 *
 *******************************************************************/

#ifndef __SERIAL_LINK_H
#define __SERIAL_LINK_H



// Pilot common definitions
#include <Common.h>
#include <SystemMgr.h>



//*************************************************************************
//   Pre-defined, fixxed  Socket ID's
//*************************************************************************
#define		slkSocketDebugger			0			// Debugger Socket
#define		slkSocketConsole			1			// Console Socket
#define		slkSocketRemoteUI			2			// Remote UI Socket
#define		slkSocketDLP				3			// Desktop Link Socket
#define		slkSocketFirstDynamic	4			// first dynamic socket ID


//*************************************************************************
//  Packet Types
//*************************************************************************
#define		slkPktTypeSystem			0			// System packets
#define		slkPktTypeUnused1			1			// used to be: Connection Manager packets
#define		slkPktTypePAD				2			// PAD Protocol packets
#define		slkPktTypeLoopBackTest	3			// Loop-back test packets



//*************************************************************************
//
// Packet structure:
//		header
//		body (0-dbgMaxPacketBodyLength bytes of data)
//		footer
//
//*************************************************************************

//----------------------------------------------------------------------
// packet header
// Fields marked with -> must be filled in by caller
// Fields marked with X  will be filled in by SlkSendPacket.
//----------------------------------------------------------------------

typedef	Byte	SlkPktHeaderChecksum;

typedef struct SlkPktHeaderType {
	Word						signature1;				// X  first 2 bytes of signature
	Byte						signature2;				// X  3 and final byte of signature
	Byte						dest;						// -> destination socket Id
	Byte						src;						// -> src socket Id
	Byte						type;						// -> packet type
	Word						bodySize;				// X  size of body
	Byte						transId;					// -> transaction Id
															//    if 0 specified, it will be replaced 
	SlkPktHeaderChecksum	checksum;				// X  check sum of header
	} SlkPktHeaderType;

typedef SlkPktHeaderType*	SlkPktHeaderPtr;

#define	slkPktHeaderSignature1	0xBEEF
#define	slkPktHeaderSignature2	0xED

#define	slkPktHeaderSigFirst		0xBE			// First byte
#define	slkPktHeaderSigSecond	0xEF			// second byte
#define	slkPktHeaderSigThird		0xED			// third byte

//----------------------------------------------------------------------
// packet footer
//----------------------------------------------------------------------
typedef struct SlkPktFooterType {
	Word		crc16;				// header and body crc
	} SlkPktFooterType;

typedef SlkPktFooterType*	SlkPktFooterPtr;


//*************************************************************************
//
// Write Data Structure passed to SlkSendPacket. This structure 
//  Tells SlkSendPacket where each of the chunks that comprise the body are
//  and the size of each. SlkSendPacket accepts a pointer to an array
//  of SlkWriteDataTypes, the last one has a size field of 0.
//
//*************************************************************************
typedef struct SlkWriteDataType {
	Word		size;					// last one has size of 0
	void*		dataP;				// pointer to data
	} SlkWriteDataType;
typedef SlkWriteDataType*	SlkWriteDataPtr;




//*************************************************************************
//
// CPU-dependent macros for getting/setting values from/to packets
//
//*************************************************************************

//--------------------------------------------------------------------
// macros to get packet values
//--------------------------------------------------------------------

#define	slkGetPacketByteVal(srcP)	(*(BytePtr)(srcP))


#if (CPU_TYPE == CPU_x86)
#define	slkGetPacketWordVal(srcP)								\
	(	(Word)															\
		(																	\
		((Word)((BytePtr)(srcP))[0] << 8) |						\
		((Word)((BytePtr)(srcP))[1])								\
		)																	\
	)
#else
#define	slkGetPacketWordVal(srcP)								\
	( *((WordPtr)(srcP)) )
#endif	//CPU_TYPE == CPU_x86


#if (CPU_TYPE == CPU_x86)
#define	slkGetPacketDWordVal(srcP)								\
	(	(DWord)															\
		(																	\
		((DWord)((BytePtr)(srcP))[0] << 24) |					\
		((DWord)((BytePtr)(srcP))[1] << 16) |					\
		((DWord)((BytePtr)(srcP))[2] << 8) |					\
		((DWord)((BytePtr)(srcP))[3])								\
		)																	\
	)
#else
#define	slkGetPacketDWordVal(srcP)								\
	( *((DWordPtr)(srcP)) )
#endif	//CPU_TYPE == CPU_x86


#define	slkGetPacketSignature1(sigP)							\
	slkGetPacketWordVal(sigP)

#define	slkGetPacketSignature2(sigP)							\
	slkGetPacketByteVal(sigP)


#define	slkGetPacketDest(addressP)								\
	slkGetPacketByteVal(addressP)
	
#define	slkGetPacketSrc(addressP)								\
	slkGetPacketByteVal(addressP)
	
#define	slkGetPacketType(commandP)								\
	slkGetPacketByteVal(commandP)
	

#define	slkGetPacketBodySize(lengthP)							\
	slkGetPacketWordVal(lengthP)

#define	slkGetPacketTransId(transIDP)							\
	slkGetPacketByteVal(transIDP)

#define	slkGetPacketHdrChecksum(checksumP)					\
	slkGetPacketByteVal(checksumP)


#define	slkGetPacketTotalChecksum(checksumP)				\
	slkGetPacketWordVal(checksumP)






//--------------------------------------------------------------------
// macros to set packet values
//--------------------------------------------------------------------


#define	slkSetPacketByteVal(srcByteVal, destP)					\
	( *(BytePtr)(destP) = (Byte)(srcByteVal) )

#if (CPU_TYPE == CPU_x86)
#define	slkSetPacketWordVal(srcWordVal, destP)					\
																				\
	do {																		\
		Word	___srcVal;													\
		BytePtr	___srcValP;												\
																				\
		___srcVal = (Word)(srcWordVal);								\
		___srcValP = (BytePtr)(&___srcVal);							\
																				\
		((BytePtr)(destP))[0] = ___srcValP[1];						\
		((BytePtr)(destP))[1] = ___srcValP[0];						\
	} while( false )
#else
#define	slkSetPacketWordVal(srcWordVal, destP)					\
	( *((WordPtr)(destP)) = (Word)(srcWordVal) )
#endif	//CPU_TYPE == CPU_x86


#if (CPU_TYPE == CPU_x86)
#define	slkSetPacketDWordVal(srcDWordVal, destP)				\
	do {																		\
		DWord	___srcVal;													\
		BytePtr	___srcValP;												\
																				\
		___srcVal = (DWord)(srcDWordVal);							\
		___srcValP = (BytePtr)(&___srcVal);							\
																				\
		((BytePtr)(destP))[0] = ___srcValP[3];						\
		((BytePtr)(destP))[1] = ___srcValP[2];						\
		((BytePtr)(destP))[2] = ___srcValP[1];						\
		((BytePtr)(destP))[3] = ___srcValP[0];						\
	} while( false )
#else
#define	slkSetPacketDWordVal(srcDWordVal, destP)				\
	( *((DWordPtr)(destP)) = (DWord)(srcDWordVal) )
#endif	//CPU_TYPE == CPU_x86



#define slkSetPacketSignature1(magic, destP)						\
	slkSetPacketWordVal(magic, destP)

#define slkSetPacketSignature2(magic, destP)						\
	slkSetPacketByteVal(magic, destP)


#define slkSetPacketDest(dest, destP)								\
	slkSetPacketByteVal(dest, destP)

#define slkSetPacketSrc(src, destP)									\
	slkSetPacketByteVal(src, destP)


#define slkSetPacketType(type, destP)								\
	slkSetPacketByteVal(type, destP)


#define slkSetPacketBodySize(numBytes, destP)					\
	slkSetPacketWordVal(numBytes, destP)


#define slkSetPacketTransId(transID, destP)						\
	slkSetPacketByteVal(transID, destP)

#define slkSetPacketHdrChecksum(checksum, destP)				\
	slkSetPacketByteVal(checksum, destP)

#define slkSetPacketTotalChecksum(checksum, destP)				\
	slkSetPacketWordVal(checksum, destP)






/*******************************************************************
 * Serial Link Manager Errors
 * the constant slkErrorClass is defined in SystemMgr.h
 *******************************************************************/
#define	slkErrChecksum				(slkErrorClass | 1)
#define	slkErrFormat				(slkErrorClass | 2)
#define	slkErrBuffer				(slkErrorClass | 3)
#define	slkErrTimeOut				(slkErrorClass | 4)
#define	slkErrHandle				(slkErrorClass | 5)
#define	slkErrBodyLimit			(slkErrorClass | 6)
#define	slkErrTransId				(slkErrorClass | 7)
#define	slkErrResponse				(slkErrorClass | 8)
#define	slkErrNoDefaultProc		(slkErrorClass | 9)
#define	slkErrWrongPacketType	(slkErrorClass | 10)
#define 	slkErrBadParam				(slkErrorClass | 11)
#define 	slkErrAlreadyOpen			(slkErrorClass | 12)
#define	slkErrOutOfSockets		(slkErrorClass | 13)
#define	slkErrSocketNotOpen		(slkErrorClass | 14)
#define	slkErrWrongDestSocket	(slkErrorClass | 15)
#define	slkErrWrongPktType		(slkErrorClass | 16)
#define	slkErrBusy					(slkErrorClass | 17)	// called while sending a packet
																		// only returned on single-threaded
																		// emulation implementations 
#define	slkErrNotOpen				(slkErrorClass | 18)



/*******************************************************************
 * Type definition for a Serial Link Socket Listener
 *
 *******************************************************************/
typedef	void (*SlkSocketListenerProcPtr)
			(SlkPktHeaderPtr headerP, void* bodyP);
			
typedef struct SlkSocketListenType {
	SlkSocketListenerProcPtr 	listenerP;
	SlkPktHeaderPtr				headerBufferP;		// App allocated buffer for header
	void*								bodyBufferP;		// App allocated buffer for body
	ULong								bodyBufferSize;
	} SlkSocketListenType;
typedef SlkSocketListenType*	SlkSocketListenPtr;



/*******************************************************************
 * Prototypes
 *******************************************************************/
#ifdef __cplusplus
extern "C" {
#endif

//-------------------------------------------------------------------
// Initializes the Serial Link Manager
//-------------------------------------------------------------------
Err			SlkOpen(void)
					SYS_TRAP(sysTrapSlkOpen);

//-------------------------------------------------------------------
// Close down the Serial Link Manager
//-------------------------------------------------------------------
Err			SlkClose(void)
					SYS_TRAP(sysTrapSlkClose);




//-------------------------------------------------------------------
// Open up another Serial Link socket. The caller must have already
//  opened the comm library and set it to the right settings.
//-------------------------------------------------------------------
Err			SlkOpenSocket(UInt libRefNum, UIntPtr socketP, Boolean staticSocket)
					SYS_TRAP(sysTrapSlkOpenSocket);

//-------------------------------------------------------------------
// Close up a Serial Link socket. 
//  Warning: This routine is assymetrical with SlkOpenSocket because it
//   WILL CLOSE the library for the caller (unless the refNum is the
//   refNum of the debugger comm library).
//-------------------------------------------------------------------
Err			SlkCloseSocket(UInt socket)
					SYS_TRAP(sysTrapSlkCloseSocket);
					

//-------------------------------------------------------------------
// Get the library refNum for a particular Socket
//-------------------------------------------------------------------
Err			SlkSocketRefNum(UInt socket, UIntPtr refNumP)
					SYS_TRAP(sysTrapSlkSocketRefNum);


//-------------------------------------------------------------------
// Set the in-packet timeout for a socket
//-------------------------------------------------------------------
Err			SlkSocketSetTimeout(UInt socket, Long timeout)
					SYS_TRAP(sysTrapSlkSocketSetTimeout);





//-------------------------------------------------------------------
// Flush a Socket
//-------------------------------------------------------------------
Err			SlkFlushSocket(UInt socket, Long timeout)
					SYS_TRAP(sysTrapSlkFlushSocket);


//-------------------------------------------------------------------
// Set up a Socket Listener
//-------------------------------------------------------------------
Err			SlkSetSocketListener(UInt socket,  SlkSocketListenPtr socketP)
					SYS_TRAP(sysTrapSlkSetSocketListener);


//-------------------------------------------------------------------
// Sends a packet's header, body, footer.  Stuffs the header's
// magic number and checksum fields.  Expects all other
// header fields to be filled in by caller.
// errors returned: dseHandle, dseLine, dseIO, dseParam, dseBodyLimit,
//					dseOther
//-------------------------------------------------------------------
Err 			SlkSendPacket(SlkPktHeaderPtr headerP, SlkWriteDataPtr writeList)
					SYS_TRAP(sysTrapSlkSendPacket);


//-------------------------------------------------------------------
// Receives and validates an entire packet.
// errors returned: dseHandle, dseParam, dseLine, dseIO, dseFormat,
//					dseChecksum, dseBuffer, dseBodyLimit, dseTimeOut,
//					dseOther
//-------------------------------------------------------------------
Err			SlkReceivePacket( UInt socket, Boolean andOtherSockets, 
						SlkPktHeaderPtr headerP, void* bodyP,  UInt bodySize,  
						Long timeout)
					SYS_TRAP(sysTrapSlkReceivePacket);


//-------------------------------------------------------------------
// Do Default processing of a System packet
//-------------------------------------------------------------------
Err 			SlkSysPktDefaultResponse(SlkPktHeaderPtr headerP, void* bodyP)
					SYS_TRAP(sysTrapSlkSysPktDefaultResponse);

//-------------------------------------------------------------------
// Do RPC call
//-------------------------------------------------------------------
Err 			SlkProcessRPC(SlkPktHeaderPtr headerP, void* bodyP)
					SYS_TRAP(sysTrapSlkProcessRPC);



#ifdef __cplusplus
}
#endif
	
	
#endif	//__SERIAL_LINK_H
