www.pudn.com > DeviceNet.zip > dnet.c, change:2003-09-19,size:24502b


 
/***************************************************************************** 
 * 
 *              Microchip DeviceNet Stack (DeviceNet Object) 
 * 
 ***************************************************************************** 
 * FileName:        dnet.c 
 * Dependencies:     
 * Processor:       PIC18F with CAN 
 * Compiler:       	C18 02.20.00 or higher 
 * Linker:          MPLINK 03.40.00 or higher 
 * Company:         Microchip Technology Incorporated 
 * 
 * Software License Agreement 
 * 
 * The software supplied herewith by Microchip Technology Incorporated 
 * (the "Company") is intended and supplied to you, the Company's 
 * customer, for use solely and exclusively with products manufactured 
 * by the Company.  
 * 
 * The software is owned by the Company and/or its supplier, and is  
 * protected under applicable copyright laws. All rights are reserved.  
 * Any use in violation of the foregoing restrictions may subject the  
 * user to criminal sanctions under applicable laws, as well as to  
 * civil liability for the breach of the terms and conditions of this  
 * license. 
 * 
 * THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,  
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED  
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A  
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,  
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR  
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. 
 * 
 * 
 * This file contains the DeviceNet object described in section 5-5 of  
 * volume 1 of the DeviceNet specification. 
 * 
 * Author               Date        Comment 
 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 * Ross Fosler			04/03/03	...	 
 *  
 *****************************************************************************/ 
 
#include	"dnet.def"			// Global definitions file 
#include 	"typedefs.h" 
 
#include	"dnet.h"			// Internal prototypes 
#include	"usrdnet.h"			// External prototypes 
 
#include	"services.h"		// Service codes 
#include	"errors.h"			// Error codes 
#include	"class.h"			// Class codes 
 
#include	"conn.h" 
#include	"route.h"			// Global symbols defined by the router 
 
 
 
/********************************************************************* 
 * DeviceNet internal definitions 
 ********************************************************************/ 
#define		_DNET_REVISION				0x02 
 
#define		_ATTRIB_REVISION			0x01 
 
#define		_ATTRIB_MAC_ID				0x01 
#define		_ATTRIB_BAUD_RATE			0x02 
#define		_ATTRIB_BOI					0x03 
#define		_ATTRIB_BO_COUNT			0x04 
#define		_ATTRIB_ALLOC_INFO			0x05 
#define		_ATTRIB_MAC_SW_CH			0x06 
#define		_ATTRIB_BAUD_SW_CH			0x07 
#define		_ATTRIB_MAC_SW_VAL			0x08 
#define		_ATTRIB_BAUD_SW_VAL			0x09 
 
#define		_DNET_ERR_CONFLICT			0x01 
#define		_DNET_ERR_INVALID_PARAM		0x02 
#define		_DNET_ERR_INVALID_SERVICE	0x03 
#define		_DNET_ERR_RSRC_NOT_AVAIL	0x04 
 
 
/********************************************************************* 
 * DeviceNet global parameters 
 ********************************************************************/ 
DNET uDNet; 
 
 
 
 
/********************************************************************* 
 * Function:        unsigned char DNetExplMsgHandler(void) 
 * 
 * PreCondition:    The path (aService, aClassID, aInstanceID) must 
 *					be loaded prior to using this function. If service 
 *					indicates any type of IO then the buffer pointers 
 *					must be initialized. 
 * 
 * Input:       	aHeader, aClassID, aInstanceID, aService 
 *					*pOutBuf, *pInBuf, aOutBufDataLen, aInBufDataLen 
 *					aOutBufLen, aInBufLen		 
 *                   
 * Output:      	aHeader, aService	 
 *					*pOutBuf, *pInBuf, aOutBufDataLen, aInBufDataLen 
 *				 
 *			 
 * 
 * Side Effects:     
 * 
 * Overview:        DeviceNet object explicit messaging handler. This 
 *					fucntion is called by the Router object. It decodes 
 *					the instance and service and performs the requested 
 *					function.   
 * 
 * Note:            None 
 ********************************************************************/ 
unsigned char _DNetExplMsgHandler(void) 
{ 
	switch (mRouteGetInstanceID()) 
	{ 
		// The DeviceNet object, class specific  
		case 0: 
			switch(mRouteGetServiceID()) 
			{ 
				case SRVS_GET_ATTRIB_SINGLE: 
					return (_DNetInst0GetAttrib()); 
				default: 
					mRoutePutError(ERR_SERVICE_NOT_SUPPORTED); 
					break; 
			} 
			break; 
			 
		// The DeviceNet object, instance 1 only 
		case 1: 
			switch(mRouteGetServiceID()) 
			{ 
				case SRVS_GET_ATTRIB_SINGLE: 
					return (_DNetInst1GetAttrib()); 
				case SRVS_SET_ATTRIB_SINGLE: 
					return (_DNetInst1SetAttrib()); 
				case SRVS_ALLOCATE_CONN: 
					return (_DNetAllocateConnection()); 
				case SRVS_RELEASE_CONN: 
					return (_DNetReleaseConnection()); 
				default: 
					mRoutePutError(ERR_SERVICE_NOT_SUPPORTED); 
					break; 
			} 
			break; 
			 
		// Handle all other invalid instances		 
		default:	 
			mRoutePutError(ERR_OBJECT_DOES_NOT_EXIST);			 
			break; 
	} 
		 
	return (1); 
}			   
 
 
 
/********************************************************************* 
 * Function:        unsigned char DNetInst0GetAttrib(void) 
 * 
 * PreCondition:    The path (aService, aClassID, aInstanceID) must 
 *					be loaded prior to using this function. If service 
 *					indicates any type of IO then the buffer pointers 
 *					must be initialized. 
 * 
 * Input:       	aHeader, aClassID, aInstanceID, aService 
 *					*pOutBuf, *pInBuf, aOutBufDataLen, aInBufDataLen 
 *					aOutBufLen, aInBufLen		 
 *                   
 * Output:      	aHeader, aService	 
 *					*pOutBuf, *pInBuf, aOutBufDataLen, aInBufDataLen 
 *				 
 *			 
 * 
 * Side Effects:     
 * 
 * Overview:        Get attribute service for instance 0.   
 * 
 * Note:            None 
 ********************************************************************/ 
unsigned char _DNetInst0GetAttrib(void) 
{	 
	switch (mRouteGetAttributeID()) 
	{ 
		case _ATTRIB_REVISION: 
			mRoutePutByte(_DNET_REVISION & 0xFF); 
			mRoutePutByte((_DNET_REVISION & 0xFF00) >> 8); 
			break; 
				 
		default: 
			mRoutePutError(ERR_ATTRIB_NOT_SUPPORTED); 
			break; 
	} 
  	return (1); 
} 
 
 
 
/********************************************************************* 
 * Function:        unsigned char DNetInst1GetAttrib(void) 
 * 
 * PreCondition:    The path (aService, aClassID, aInstanceID) must 
 *					be loaded prior to using this function. If service 
 *					indicates any type of IO then the buffer pointers 
 *					must be initialized. 
 * 
 * Input:       	aHeader, aClassID, aInstanceID, aService 
 *					*pOutBuf, *pInBuf, aOutBufDataLen, aInBufDataLen 
 *					aOutBufLen, aInBufLen		 
 *                   
 * Output:      	aHeader, aService	 
 *					*pOutBuf, *pInBuf, aOutBufDataLen, aInBufDataLen 
 *				 
 *			 
 * 
 * Side Effects:     
 * 
 * Overview:        Get attribute service for instance 1.   
 * 
 * Note:            None 
 ********************************************************************/ 
unsigned char _DNetInst1GetAttrib(void) 
{ 
	switch (mRouteGetAttributeID()) 
	{ 
		#if	ALLOW_MAC_ID 
		case _ATTRIB_MAC_ID: 
			mRoutePutByte(uDNet.MACID); 
			break; 
		#endif 
	 
		#if	ALLOW_BAUD_RATE 
		case _ATTRIB_BAUD_RATE: 
			mRoutePutByte(uDNet.BaudRate); 
			break; 
		#endif 
				 
		#if	ALLOW_BOI 
		case _ATTRIB_BOI: 
			mRoutePutByte(uDNet.BOI); 
			break; 
		#endif 
				 
		#if	ALLOW_BUS_OFF_COUNT 
		case _ATTRIB_BO_COUNT: 
			mRoutePutByte(uDNet.BusOffCount); 
			break; 
		#endif 
				 
		case _ATTRIB_ALLOC_INFO: 
			mRoutePutByte(uDNet.AllocInfo.AllocChoice.byte); 
			mRoutePutByte(uDNet.AllocInfo.MasterMACID); 
			break; 
									 
		#if	ALLOW_MAC_ID_SW_CH 
		case _ATTRIB_MAC_SW_CH: 
			mRoutePutByte(uDNet.MACSwChange); 
			break; 
		#endif 
				 
		#if	ALLOW_BAUD_RATE_SW_CH 
		case _ATTRIB_BAUD_SW_CH: 
			mRoutePutByte(uDNet.BaudSwChange); 
			break; 
		#endif 
				 
		#if	ALLOW_MAC_ID_SW_VAL 
		case _ATTRIB_MAC_SW_VAL: 
			mRoutePutByte(uDNet.MACSwValue); 
			break; 
		#endif 
				 
		#if	ALLOW_BAUD_RATE_SW_VAL 
		case _ATTRIB_BAUD_SW_VAL: 
			mRoutePutByte(uDNet.BaudSwValue); 
			break; 
		#endif 
				 
		default: 
			mRoutePutError(ERR_ATTRIB_NOT_SUPPORTED); 
			break; 
	} 
		 
	return (1); 
} 
 
 
 
 
/********************************************************************* 
 * Function:        unsigned char DNetInst1SetAttrib(void) 
 * 
 * PreCondition:    The path (aService, aClassID, aInstanceID) must 
 *					be loaded prior to using this function. If service 
 *					indicates any type of IO then the buffer pointers 
 *					must be initialized. 
 * 
 * Input:       	aHeader, aClassID, aInstanceID, aService 
 *					*pOutBuf, *pInBuf, aOutBufDataLen, aInBufDataLen 
 *					aOutBufLen, aInBufLen		 
 *                   
 * Output:      	aHeader, aService	 
 *					*pOutBuf, *pInBuf, aOutBufDataLen, aInBufDataLen 
 *				 
 *			 
 * 
 * Side Effects:     
 * 
 * Overview:        Set attribute service for instance 1.   
 * 
 * Note:            None 
 ********************************************************************/ 
unsigned char _DNetInst1SetAttrib(void) 
{ 
	// Ignore the first byte (it is actually the attribute ID)  
	mRouteGetByte(); 
 
	switch (mRouteGetAttributeID()) 
	{ 
		#if ALLOW_MAC_ID && SETTABLE_MAC_ID 
		case _ATTRIB_MAC_ID: 
			if (mRouteTestValidInputDataLen(1)) 
			{ 
				// Perform system functions to be defined by the application 
				UsrDNetSetAttribEvent();	 
			} 
			break; 
		#endif 
				 
		#if ALLOW_BAUD_RATE && SETTABLE_BAUD_RATE 
		case _ATTRIB_BAUD_RATE: 
			if (mRouteTestValidInputDataLen(1)) 
			{ 
				// Perform system functions to be defined by the application 
				UsrDNetSetAttribEvent(); 
			} 
			break; 
		#endif 
			 
		#if ALLOW_BOI && SETTABLE_BOI 
		case _ATTRIB_BOI: 
			if (mRouteTestValidInputDataLen(1)) 
			{ 
				// Perform system functions to be defined by the application 
				UsrDNetSetAttribEvent(); 
			} 
			break; 
		#endif 
				 
		#if ALLOW_BUS_OFF_COUNT && SETTABLE_BUS_OFF_COUNT 
		case _ATTRIB_BO_COUNT: 
			if (mRouteTestValidInputDataLen(1)) 
			{ 
				uDNet.BusOffCount = 0; 
			} 
			break; 
		#endif 
		 
				 
		#if ALLOW_MAC_ID && !SETTABLE_MAC_ID 
		case _ATTRIB_MAC_ID: 
		#endif 
		#if ALLOW_BAUD_RATE && !SETTABLE_BAUD_RATE 
		case _ATTRIB_BAUD_RATE: 
		#endif 
		#if ALLOW_BOI && !SETTABLE_BOI 
		case _ATTRIB_BOI: 
		#endif 
		#if ALLOW_BUS_OFF_COUNT && !SETTABLE_BUS_OFF_COUNT 
		case _ATTRIB_BO_COUNT: 
		#endif 
		case _ATTRIB_ALLOC_INFO: 
		#if ALLOW_MAC_ID_SW_CH 
		case _ATTRIB_MAC_SW_CH: 
		#endif 
		#if ALLOW_BAUD_RATE_SW_CH 
		case _ATTRIB_BAUD_SW_CH: 
		#endif 
		#if ALLOW_MAC_ID_SW_VAL 
		case _ATTRIB_MAC_SW_VAL: 
		#endif 
		#if ALLOW_BAUD_RATE_SW_VAL 
		case _ATTRIB_BAUD_SW_VAL: 
		#endif 
			mRoutePutError(ERR_ATTRIB_NOT_SETTABLE); 
			break; 
			 
		default: 
			mRoutePutError(ERR_ATTRIB_NOT_SUPPORTED); 
			break; 
	} 
 
	return (1); 
} 
 
 
 
/********************************************************************* 
 * Function:        unsigned char DNetAllocateConnection(void) 
 * 
 * PreCondition:    The path (aService, aClassID, aInstanceID) must 
 *					be loaded prior to using this function. If service 
 *					indicates any type of IO then the buffer pointers 
 *					must be initialized. 
 * 
 * Input:       	aHeader, aClassID, aInstanceID, aService 
 *					*pOutBuf, *pInBuf, aOutBufDataLen, aInBufDataLen 
 *					aOutBufLen, aInBufLen		 
 *                   
 * Output:      	aHeader, aService	 
 *					*pOutBuf, *pInBuf, aOutBufDataLen, aInBufDataLen	 
 * 
 * Side Effects:     
 * 
 * Overview:        Allocate predefined master/slave connection set.   
 * 
 * Note:            None 
 ********************************************************************/ 
unsigned char _DNetAllocateConnection(void) 
{ 
	unsigned char allocMAC; 
	BYTE allocChoice; 
 
	// Pull the data from the buffer for validation 
	allocChoice.byte = mRouteGetByte(); 
	allocMAC = mRouteGetByte();   
	  
	// Connection not allocated 
	if (uDNet.AllocInfo.MasterMACID == 0xFF)  
	{ 
		// Since the device is not allocated then no connections  
		uDNet.AllocInfo.AllocChoice.byte = 0; 
 
		// A NULL allocation choice is not valid 
		if (allocChoice.byte == 0) 
		{ 
			mRoutePutError(ERR_INVALID_ATTRIB_VALUE); 
			mRoutePutByte(_DNET_ERR_INVALID_PARAM); 
 
			return (1); 
		} 
 
		// Check for connection support 
		if (_DNetAllocNoSupportChk(allocChoice)) 
	   	{ 
	   		mRoutePutError(ERR_RESOURCE_UNAVAILABLE); 
	   		mRoutePutByte(_DNET_ERR_INVALID_PARAM); 
 
			return (1); 
	   	} 
 
		// Cannot allocate both COS and cyclic 
	   	if ((allocChoice.byte & 0x30) == 0x30) 
	   	{ 
	   		mRoutePutError(ERR_INVALID_ATTRIB_VALUE); 
	   		mRoutePutByte(_DNET_ERR_INVALID_PARAM); 
 
			return (1); 
	   	} 
 
		// Cannot support acknowledge supression if COS or cyclic not enabled 
		if ((allocChoice.byte & 0x70) == 0x40) 
		{ 
	   		mRoutePutError(ERR_INVALID_ATTRIB_VALUE); 
	   		mRoutePutByte(_DNET_ERR_INVALID_PARAM); 
 
			return (1); 
		} 
		 
		// Cannot continue if a parent has not been allocated 
		if (!allocChoice.bits.b0) 
		{ 
			mRoutePutError(ERR_INVALID_ATTRIB_VALUE); 
			mRoutePutByte(_DNET_ERR_INVALID_PARAM); 
			return (1); 
		} 
		 
		// Set the master's MAC before attempting to create any  
		// connections because the Master's MAC is needed for the 
		// bit-strobe connection upon creation. 
		uDNet.AllocInfo.MasterMACID = allocMAC; 
		 
		// Try to create the connections 
		if (!_DNetCreateConnections(allocChoice)) 
		{ 
	   		mRoutePutError(ERR_RESOURCE_UNAVAILABLE); 
	   		mRoutePutByte(_DNET_ERR_RSRC_NOT_AVAIL); 
 
			// Reset the Master's MAC 
			uDNet.AllocInfo.MasterMACID = 0xFF; 
 
			return (1); 
		} 
		 
		uDNet.AllocInfo.AllocChoice.byte = allocChoice.byte; 
	} 
 
	// Connection is allocated 
	else  
	{ 
		// Verify the request is from the allocated master 
		if (uDNet.AllocInfo.MasterMACID != allocMAC) 
		{ 
			mRoutePutError(ERR_OBJECT_STATE_CONFLICT); 
			mRoutePutByte(_DNET_ERR_CONFLICT); 
 
			return (1); 
		} 
 
		 // A NULL allocation choice is not valid 
		if (allocChoice.byte == 0) 
		{ 
			mRoutePutError(ERR_INVALID_ATTRIB_VALUE); 
			mRoutePutByte(_DNET_ERR_INVALID_PARAM); 
 
			return (1); 
		} 
 
		// Check for connection support 
		if (_DNetAllocNoSupportChk(allocChoice)) 
	   	{ 
	   		mRoutePutError(ERR_RESOURCE_UNAVAILABLE); 
	   		mRoutePutByte(_DNET_ERR_INVALID_PARAM); 
 
			return (1); 
	   	} 
 
		#if SUPPORT_COS && SUPPORT_CYCLIC 
		// Cannot allocate both COS and cyclic 
	   	if (((allocChoice.byte | uDNet.AllocInfo.AllocChoice.byte) & 0x30) == 0x30) 
	   	{ 
	   		mRoutePutError(ERR_INVALID_ATTRIB_VALUE); 
	   		mRoutePutByte(_DNET_ERR_INVALID_PARAM); 
 
			return (1); 
	   	} 
		#endif 
 
 
		#if (SUPPORT_COS || SUPPORT_CYCLIC) && SUPPORT_POLLED 
		// Cannot support polling if COS or cyclic is already enabled 
		if ((uDNet.AllocInfo.AllocChoice.byte & 0x30) && (allocChoice.byte & 0x02)) 
		{ 
	   		mRoutePutError(ERR_RESOURCE_UNAVAILABLE); 
	   		mRoutePutByte(_DNET_ERR_RSRC_NOT_AVAIL); 
 
			return (1); 
		} 
		#endif 
 
		// Cannot support acknowledge supression if COS or cyclic not enabled 
		if (((allocChoice.byte | uDNet.AllocInfo.AllocChoice.byte) & 0x70) == 0x40) 
		{ 
	   		mRoutePutError(ERR_INVALID_ATTRIB_VALUE); 
	   		mRoutePutByte(_DNET_ERR_INVALID_PARAM); 
 
			return (1); 
		} 
		 
		// Cannot continue if the request matches existing connections 
		if ((allocChoice.byte & uDNet.AllocInfo.AllocChoice.byte) & 0x3F) 
		{ 
			mRoutePutError(ERR_OBJECT_STATE_CONFLICT); 
			mRoutePutByte(_DNET_ERR_CONFLICT); 
 
			return (1); 
		} 
 
		// Try to create the connections 
		if (!_DNetCreateConnections(allocChoice)) 
		{ 
	   		mRoutePutError(ERR_RESOURCE_UNAVAILABLE); 
	   		mRoutePutByte(_DNET_ERR_RSRC_NOT_AVAIL); 
 
			return (1); 
		} 
		 
		// Set the alloc choice 
		uDNet.AllocInfo.AllocChoice.byte |= allocChoice.byte; 
	} 
	 
	// Set the responce format   (Message Body Format) 
	#if ((!CLASS_WIDTH_16BIT) && (!INSTANCE_WIDTH_16BIT)) 
	mRoutePutByte(0); 
	#endif 
	#if ((!CLASS_WIDTH_16BIT) && INSTANCE_WIDTH_16BIT) 
	mRoutePutByte(1); 
	#endif 
	#if (CLASS_WIDTH_16BIT && INSTANCE_WIDTH_16BIT) 
	mRoutePutByte(2); 
	#endif 
	#if (CLASS_WIDTH_16BIT && (!INSTANCE_WIDTH_16BIT)) 
	mRoutePutByte(3); 
	#endif 
	 
	return (1); 
} 
 
 
 
/********************************************************************* 
 * Function:        unsigned char DNetReleaseConnection(void) 
 * 
 * PreCondition:    The path (aService, aClassID, aInstanceID) must 
 *					be loaded prior to using this function. If service 
 *					indicates any type of IO then the buffer pointers 
 *					must be initialized. 
 * 
 * Input:       	aHeader, aClassID, aInstanceID, aService 
 *					*pOutBuf, *pInBuf, aOutBufDataLen, aInBufDataLen 
 *					aOutBufLen, aInBufLen		 
 *                   
 * Output:      	aHeader, aService	 
 *					*pOutBuf, *pInBuf, aOutBufDataLen, aInBufDataLen 
 *				 
 * Side Effects:     
 * 
 * Overview:        Release predefined master/slave connection set.   
 * 
 * Note:            None 
 ********************************************************************/ 
unsigned char _DNetReleaseConnection(void) 
{ 
	BYTE releaseChoice; 
 
	releaseChoice.byte = mRouteGetByte(); 
	 
	// Check for connection support 
	if (_DNetAllocNoSupportChk(releaseChoice)) 
   	{ 
   		mRoutePutError(ERR_RESOURCE_UNAVAILABLE); 
   		mRoutePutByte(_DNET_ERR_INVALID_PARAM); 
 
   		return (1); 
   	} 
 
	 // A NULL release choice is not valid 
  	if (releaseChoice.byte == 0) 
  	{ 
  		mRoutePutError(ERR_INVALID_ATTRIB_VALUE); 
  		mRoutePutByte(_DNET_ERR_INVALID_PARAM); 
 
  		return (1); 
  	} 
	 
   	// Cannot continue if the request matches non-existant connections 
   	if (((releaseChoice.byte) & (~uDNet.AllocInfo.AllocChoice.byte)) & 0x3F) 
   	{ 
   		mRoutePutError(ERR_OBJECT_STATE_CONFLICT); 
   		mRoutePutByte(_DNET_ERR_CONFLICT); 
 
   		return (1); 
   	} 
	 
	// Close the connections 
	_DNetCloseConnections(releaseChoice); 
	 
	// Release the connection(s) 
	uDNet.AllocInfo.AllocChoice.byte &= (~(releaseChoice.byte));	  
	 
	// If all connections are released then reset the master MAC ID 
	if (uDNet.AllocInfo.AllocChoice.byte == 0) uDNet.AllocInfo.MasterMACID = 0xFF; 													  
	 
	// If ack supression is set and cyclic/COS is not then clear the bit 
	if ((uDNet.AllocInfo.AllocChoice.byte & 0x70) == 0x40) uDNet.AllocInfo.AllocChoice.byte &= 0x0F; 
														  
	return (1);											  
} 
 
 
 
/********************************************************************* 
 * Function:        unsigned char _DNetAllocNoSupportChk(BYTE choice) 
 * 
 * PreCondition:    None 
 * 
 * Input:       	The allocation choice as a bitmap	 
 *                   
 * Output:      	1 or 0 
 *				 
 * Side Effects:    None 
 * 
 * Overview:       	Validates the allocation choice to determine if a 
 *					connection is not supported. Returns TRUE if the 
 *					any of the connections are not supported. 
 * 
 * Note:            None 
 ********************************************************************/ 
unsigned char _DNetAllocNoSupportChk(BYTE choice) 
{	 
	#if SUPPORT_POLLED == 0 
	if (choice.bits.b1) return (1);		// Polled messgae not supported 
	#endif 
 
	#if SUPPORT_BIT_STROBED == 0 
	if (choice.bits.b2) return (1);		// Bit Strobed not supported 
	#endif 
 
	#if SUPPORT_MULTICAST_POLL == 0 
	if (choice.bits.b3) return (1);		// Multicast Polled Message not supported 
	#endif 
 
	#if SUPPORT_COS == 0 
	if (choice.bits.b4) return (1);		// COS Message not supported 
	#endif 
	  
	#if SUPPORT_CYCLIC == 0 
	if (choice.bits.b5) return (1);		// Cyclic Message not supported 
	#endif	 
 
	if (choice.bits.b7) return (1);		// Reserved bit	never supported							    
	 
	return (0); 
}  
 
 
 
/********************************************************************* 
 * Function:        void _DNetCreateConnections(BYTE choice) 
 * 
 * PreCondition:    None 
 * 
 * Input:       	The allocation choice as a bitmap 
 *                   
 * Output:      	None 
 *				 
 * Side Effects:    This function will call to individual connection 
 *					objects to open. If any open request fails then  
 *					any objects that were just opened will be closed  
 *					immediately. 
 * 
 * Overview:      	This function decodes the request and calls 
 *					the appropriate functions to create the connection. 
 * 
 * Note:            None 
 ********************************************************************/ 
unsigned char _DNetCreateConnections(BYTE choice) 
{ 
	BYTE allocProgress; 
	unsigned char err_stat; 
 
	err_stat = 1; 
	allocProgress.byte = 0; 
 
	// Allocate Explicit Messaging if not already allocated 
	if (choice.bits.b0) 					// Explicit message 
	{ 
		if (_Conn1Create()) allocProgress.bits.b0 = 1; 
		else err_stat = 0; 
	} 
		 
	#if SUPPORT_POLLED 
	if (choice.bits.b1) 					// Polled message 
	{ 
		if (_Conn2Create()) allocProgress.bits.b1 = 1; 
		else err_stat = 0; 
	} 
	#endif		 
		 
	#if SUPPORT_BIT_STROBED 
	if (choice.bits.b2) 					// Bit Strobed Message 
	{ 
		if (_Conn3Create()) allocProgress.bits.b2 = 1; 
		else err_stat = 0; 
	} 
	#endif	 
	 
	#if SUPPORT_MULTICAST_POLL 
	if (choice.bits.b3) 					// Multicast Polled Message 
	{ 
		if (_Conn5Create()) allocProgress.bits.b4 = 1; 
		else err_stat = 0; 
	} 
	#endif		 
		 
	#if SUPPORT_COS 
	if (choice.bits.b4) 					// COS Message 
	{ 
		if (_Conn4Create())  
		{ 
			allocProgress.bits.b3 = 1; 
			 
			#if SUPPORT_COS_BOTH_DIR		 
			#if SUPPORT_POLLED 
			if (!uDNet.AllocInfo.AllocChoice.bits.poll) 
			{ 
				if (_Conn2Create()) allocProgress.bits.b1 = 1; 
				else err_stat = 0;  
			} 
			#else 
			if (_Conn2Create()) allocProgress.bits.b1 = 1; 
			else err_stat = 0;  
			#endif 
			#endif 
		} 
		else err_stat = 0; 
	} 
	#endif	 
		 
	#if SUPPORT_CYCLIC 
	if (choice.bits.b5) 					// Cyclic Message 
	{ 
		if (_Conn4Create())  
		{ 
			allocProgress.bits.b3 = 1; 
			 
			#if SUPPORT_COS_BOTH_DIR		 
			#if SUPPORT_POLLED 
			if (!uDNet.AllocInfo.AllocChoice.bits.poll) 
			{ 
				if (_Conn2Create()) allocProgress.bits.b1 = 1; 
				else err_stat = 0;  
			} 
			#else 
			if (_Conn2Create()) allocProgress.bits.b1 = 1; 
			else err_stat = 0;  
			#endif 
			#endif 
		} 
		else err_stat = 0; 
	} 
	#endif 
	 
	// Close all just opened connections if there was an error 
	if (err_stat == 0) 
	{ 
		if (allocProgress.bits.b0) _Conn1Close(); 
		 
		#if SUPPORT_POLLED || SUPPORT_COS_BOTH_DIR 
		if (allocProgress.bits.b1) _Conn2Close(); 
		#endif 
		 
		#if SUPPORT_BIT_STROBED 
		if (allocProgress.bits.b2) _Conn3Close(); 
		#endif 
		 
		#if SUPPORT_COS || SUPPORT_CYCLIC 
		if (allocProgress.bits.b3) _Conn4Close(); 
		#endif 
		 
		#if SUPPORT_MULTICAST_POLL 
		if (allocProgress.bits.b4) _Conn5Close(); 
		#endif 
	} 
			 
	return (err_stat); 
} 
 
 
 
 
/********************************************************************* 
 * Function:        void _DNetCreateConnections(BYTE choice) 
 * 
 * PreCondition:     
 * 
 * Input:       			 
 *                   
 * Output:      	 
 *				 
 * Side Effects:     
 * 
 * Overview:     	This function decodes the choice byte and calls 
 *					the appropriate functions to delete the connections.      
 * 
 * Note:            None 
 ********************************************************************/ 
void _DNetCloseConnections(BYTE choice) 
{	 
	if (choice.bits.b0) _Conn1Close();		// Explicit message  
 
	#if SUPPORT_POLLED 
	if (choice.bits.b1) _Conn2Close();		// Polled messgae 
	#endif 
 
	#if SUPPORT_BIT_STROBED 
	if (choice.bits.b2) _Conn3Close();		// Bit Strobed 
	#endif 
 
	#if SUPPORT_MULTICAST_POLL 
	if (choice.bits.b3) _Conn5Close();		// Multicast Polled Message 
	#endif 
 
	#if SUPPORT_COS 
	if (choice.bits.b4) 					// COS Message 
	{ 
		_Conn4Close(); 
		 
		#if SUPPORT_COS_BOTH_DIR		 
		#if SUPPORT_POLLED 
		if (!uDNet.AllocInfo.AllocChoice.bits.poll) 
		{ 
			_Conn2Close();  
		} 
		#else 
		_Conn2Close(); 
		#endif 
		#endif 
		 
				 
		#if SUPPORT_POLLED 
		if (!uDNet.AllocInfo.AllocChoice.bits.poll)  
		#endif 
			#if SUPPORT_COS_BOTH_DIR 
			_Conn2Close(); 
			#endif 
	} 
	#endif 
	  
	#if SUPPORT_CYCLIC 
	if (choice.bits.b5) 					// Cyclic Message 
	{ 
		_Conn4Close();		 
		#if SUPPORT_POLLED 
		if (!uDNet.AllocInfo.AllocChoice.bits.poll)  
		#endif 
			#if SUPPORT_COS_BOTH_DIR 
			_Conn2Close(); 
			#endif 
	} 
	#endif 
}