/*******************************************************************
 * 							 Pilot Software
 *
 *	Copyright (c) 1994-1997, Palm Computing Inc., All Rights Reserved  
 *
 *-------------------------------------------------------------------
 * 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
