Browse Source

Sicherung des Zwischenstandes.

Rind 5 năm trước cách đây
mục cha
commit
d339616a81

+ 0 - 1
libmininet/dbghlp.h

@@ -25,7 +25,6 @@ extern "C" {
 
 uint64_t Timeval2Us(const struct timeval *ptv);
 const struct timeval* Us2Timeval(uint64_t usTime, struct timeval *ptv);
-
 uint64_t Timespec2Ns(const struct timespec *pts);
 const struct timespec* Ns2Timespec(uint64_t nsTime, struct timespec *pts);
 int64_t TimespecDiff(const struct timespec *pts1, const struct timespec *pts2);

+ 201 - 94
libmininet/gfabootlmast.c

@@ -14,20 +14,19 @@
 ////////////////////////////////////////////////////////////////////////////////////
 
 #define _dword_offset(m)						(offsetof(GFA_APP_IMG_HEADER, m) / sizeof(uint32_t) - 2)
-#define _EXEC_CALLBACK(pfn, ...)				if(pfn) (*pfn)(__FILE__, __LINE__, __VA_ARGS__)
+#define _EXEC_PROGRESS_CALLBACK(pfn, ...)		if(pfn) (*pfn)(__FILE__, __LINE__, __VA_ARGS__)
 
-#define _BOOTLOADER_EXEC_WAIT_TIME				250
 #define _GFA_MAX_DUMP_DWORDS					16
-#define _MAX_SEND_DATA_BLOCK_SIZE				76
-#define _DEF_SEND_DATA_BLOCK_SIZE				64
+#define _BOOTLOADER_DEF_BAUDRATE				19200
 
 ////////////////////////////////////////////////////////////////////////////////////
 
 typedef struct _GFA_BLM
 {
 	HGFAMINEMST hMst;
-	PFN_BU_CMD_DOWNLOAD_STATUS pfnBuCmdDownloadStatus;
-	PFN_BU_CMD_SEND_DATA_STATUS pfnBuCmdSendDataStatus;
+	GFA_BLM_DL_PROGRESS_PARAMS dlpp;
+	PFN_GFA_BLM_DL_PROGRESS pfnDlProgress;
+	void *pUserParam;
 	int nVerbosity;
 }GFA_BLM, *LPGFA_BLM;
 typedef const GFA_BLM *LPCGFA_BLM;
@@ -45,8 +44,8 @@ HGFABLM GfaBlmOpen(LPCGFA_BLM_CFG_PARAMS pblmcfg)
 			LPGFA_BLM pBlm = malloc(sizeof(GFA_BLM));
 			memset(pBlm, 0, sizeof(GFA_BLM));
 			pBlm->hMst = hMst;
-			pBlm->pfnBuCmdDownloadStatus = pblmcfg->pfnBuCmdDownloadStatus;
-			pBlm->pfnBuCmdSendDataStatus = pblmcfg->pfnBuCmdSendDataStatus;
+			pBlm->pfnDlProgress = pblmcfg->pfnDlProgress;
+			pBlm->pUserParam = pblmcfg->pUserParam;
 			return (HGFABLM)pBlm;
 		}
 
@@ -90,18 +89,21 @@ ssize_t GfaBlmBUCmdPollData(HGFABLM hBlm, uint8_t nNodeAddr, void *pData, size_t
 	if(hBlm && pData && nCbData && !NODE_IS_MULTICAST(nNodeAddr))
 	{
 		size_t s, nReceived = 0;
-		struct timeval tvRX;
 		ssize_t nLen, nRet = -1;
 		uint8_t cmd[32];
 		uint8_t txb[32];
 		uint8_t rxb[512];
 		LPGFA_BLM pBlm = (LPGFA_BLM)hBlm;
 		uint8_t *pszData = (uint8_t*)pData;
-		tvRX.tv_sec		= nTimeoutMS / 1000;
-		tvRX.tv_usec	= (nTimeoutMS % 1000) * 1000;
 
-		GfaMininetMasterSaveTimeouts(pBlm->hMst);
-		GfaMininetMasterSetTimeouts(pBlm->hMst, &tvRX, NULL);
+		if(nTimeoutMS > 0)
+		{
+			struct timeval tvRX;
+			tvRX.tv_sec		= nTimeoutMS / 1000;
+			tvRX.tv_usec	= (nTimeoutMS % 1000) * 1000;
+			GfaMininetMasterSaveTimeouts(pBlm->hMst);
+			GfaMininetMasterSetTimeouts(pBlm->hMst, &tvRX, NULL);
+		}
 
 		while(nReceived < nCbData)
 		{
@@ -135,13 +137,11 @@ ssize_t GfaBlmBUCmdPollData(HGFABLM hBlm, uint8_t nNodeAddr, void *pData, size_t
 						{
 							usleep(100000);
 							nTimeoutMS -= 100;
-//							TRACE("\nACK ...\n");
 						}
 						else
 						{
 							usleep(nTimeoutMS * 1000);
 							nTimeoutMS = 0;
-//							TRACE("\nACK ...\n");
 						}
 					}
 					else
@@ -171,7 +171,8 @@ ssize_t GfaBlmBUCmdPollData(HGFABLM hBlm, uint8_t nNodeAddr, void *pData, size_t
 			}
 		}
 
-		GfaMininetMasterRestoreTimeouts(pBlm->hMst);
+		if(nTimeoutMS > 0)
+			GfaMininetMasterRestoreTimeouts(pBlm->hMst);
 		return nReceived;
 	}
 
@@ -181,7 +182,7 @@ ssize_t GfaBlmBUCmdPollData(HGFABLM hBlm, uint8_t nNodeAddr, void *pData, size_t
 
 /////////////////////////////////////////////////////////////////////////////
 
-int GfaBlmBUCmdReset(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nTimeoutMS)
+int GfaBlmBUCmdReset(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nInitialBaudrate)
 {
 	if(hBlm)
 	{
@@ -192,8 +193,8 @@ int GfaBlmBUCmdReset(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nTimeoutMS)
 		uint8_t cmd = COMMAND_RESET;
 		uint8_t cmddata[16];
 		char txb[32], rxb[256], ack[2];
-		
-		if((nRet = GfaBlmBootloaderSetBaudrate(hBlm, nNodeAddr, 19200)) != 0)
+
+		if((nRet = GfaBlmBootloaderSetBaudrate(hBlm, nNodeAddr, nInitialBaudrate)) != 0)
 			return -1;
 
 		s = GfaBlmBuildCmdDataPacket("BU", 0, &cmd, 1, cmddata, sizeof(cmddata), true);
@@ -201,12 +202,12 @@ int GfaBlmBUCmdReset(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nTimeoutMS)
 
 		if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen)
 			return nRet;
-		
+
 		if(NODE_IS_MULTICAST(nNodeAddr))
 			return 0;
 
-		if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) < 0)
-			return nLen;
+		if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) <= 0)
+			return -1;
 
 		nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex);
 
@@ -227,13 +228,13 @@ int GfaBlmBUCmdReset(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nTimeoutMS)
 			if(	(ack[0] == 0) &&
 				(ack[1] == COMMAND_ACK))
 			{
-
+#if 0
 				do
 				{
-					if(nTimeoutMS > _BOOTLOADER_EXEC_WAIT_TIME)
+					if(nTimeoutMS > GFA_BOOTLOADER_EXEC_WAIT_TIME)
 					{
-						usleep(_BOOTLOADER_EXEC_WAIT_TIME * 1000);
-						nTimeoutMS -= _BOOTLOADER_EXEC_WAIT_TIME;
+						usleep(GFA_BOOTLOADER_EXEC_WAIT_TIME * 1000);
+						nTimeoutMS -= GFA_BOOTLOADER_EXEC_WAIT_TIME;
 					}
 					else
 					{
@@ -246,8 +247,9 @@ int GfaBlmBUCmdReset(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nTimeoutMS)
 					GfaMininetMasterPurgeDeviceRXBuffer(pBlm->hMst);
 				}
 				while(nTimeoutMS > 0);
-
-				return nRet;
+#endif
+				GfaMininetMasterPurgeDeviceRXBuffer(pBlm->hMst);
+				return GfaMininetMasterResetLocalIndex(pBlm->hMst, nNodeAddr);
 			}
 		}
 		else if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE)
@@ -265,6 +267,20 @@ int GfaBlmBUCmdReset(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nTimeoutMS)
 
 /////////////////////////////////////////////////////////////////////////////
 
+int GfaBlmMininetPing(HGFABLM hBlm, uint8_t nNodeAddr)
+{
+	if(hBlm && !NODE_IS_MULTICAST(nNodeAddr))
+	{
+		LPGFA_BLM pBlm = (LPGFA_BLM)hBlm;
+		return GfaMininetMasterPingSlave(pBlm->hMst, nNodeAddr);
+	}
+
+	errno = EINVAL;
+	return -1;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
 int GfaBlmBUCmdPing(HGFABLM hBlm, uint8_t nNodeAddr)
 {
 	if(hBlm && !NODE_IS_MULTICAST(nNodeAddr))
@@ -281,8 +297,8 @@ int GfaBlmBUCmdPing(HGFABLM hBlm, uint8_t nNodeAddr)
 		if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) < nLen)
 			return nRet;
 
-		if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) < 0)
-			return nLen;
+		if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) <= 0)
+			return -1;
 
 		nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex);
 
@@ -302,7 +318,7 @@ int GfaBlmBUCmdPing(HGFABLM hBlm, uint8_t nNodeAddr)
 
 			if(ack[0] == 0)
 			{
-				return (ack[1] == COMMAND_ACK);
+                return (ack[1] == COMMAND_ACK) ? 0 : -1;
 			}
 			else
 			{
@@ -341,8 +357,8 @@ int GfaBlmBUCmdGetStatus(HGFABLM hBlm, uint8_t nNodeAddr, uint8_t *pbStatus)
 		if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) < nLen)
 			return nRet;
 
-		if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) < 0)
-			return nLen;
+		if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) <= 0)
+			return -1;
 
 		nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex);
 
@@ -356,7 +372,7 @@ int GfaBlmBUCmdGetStatus(HGFABLM hBlm, uint8_t nNodeAddr, uint8_t *pbStatus)
 			}
 			else
 			{
-				if((nRet = GfaBlmBUCmdPollData(hBlm, nNodeAddr, ack, 2, 200)) != 2)
+				if((nRet = GfaBlmBUCmdPollData(hBlm, nNodeAddr, ack, 2, 500)) != 2)
 					return -1;
 			}
 
@@ -364,7 +380,7 @@ int GfaBlmBUCmdGetStatus(HGFABLM hBlm, uint8_t nNodeAddr, uint8_t *pbStatus)
 			{
 				if(ack[1] == COMMAND_ACK)
 				{
-					if((nRet = GfaBlmBUCmdPollData(hBlm, nNodeAddr, stat, 3, 200)) != 3)
+					if((nRet = GfaBlmBUCmdPollData(hBlm, nNodeAddr, stat, 3, 500)) != 3)
 						return -1;
 
 					if((stat[0] == 3) && (stat[1] == stat[2]))
@@ -377,10 +393,18 @@ int GfaBlmBUCmdGetStatus(HGFABLM hBlm, uint8_t nNodeAddr, uint8_t *pbStatus)
 							return nRet;
 
 						if((nRet = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) <= 0)
-							return nRet;
+							return -1;
 
 						nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nRet, true, &nIndex);
-						return 0;
+
+						if(nRet == MINET_SLAVE_RESPONSE_ACK)
+							return 0;
+						else
+						{
+//							TRACE("");
+							errno = EPROTO;
+							return -1;
+						}
 					}
 					else
 					{
@@ -437,24 +461,34 @@ int GfaBlmBUCmdDownload(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nFlashStartAdd
 
 		GfaMininetMasterSaveTimeouts(pBlm->hMst);
 		GfaMininetMasterSetTimeouts(pBlm->hMst, &tv, NULL);
-		
-		_EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 1, 0);
+
+		memset(&pBlm->dlpp, 0, sizeof(GFA_BLM_DL_PROGRESS_PARAMS));
+		pBlm->dlpp.nCbTotal			= nCbData;
+		pBlm->dlpp.nFlashStartAddr	= nFlashStartAddr;
+		pBlm->dlpp.nCntFlashPages	= (nCbData + GFA_BOOTLOADER_FLASH_PAGE_SIZE - 1) / GFA_BOOTLOADER_FLASH_PAGE_SIZE;
+		pBlm->dlpp.nNodeAddr		= nNodeAddr;
+		pBlm->dlpp.pParam			= pBlm->pUserParam;
+		pBlm->dlpp.nCtx				= GBDPS_StartEraseFlash;
+		_EXEC_PROGRESS_CALLBACK(pBlm->pfnDlProgress, &pBlm->dlpp);
 
 		if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen)
 		{
-			_EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 0, errno);
+			pBlm->dlpp.nCtx			= GBDPS_Error;
+			pBlm->dlpp.nErrorCode	= errno;
+			_EXEC_PROGRESS_CALLBACK(pBlm->pfnDlProgress, &pBlm->dlpp);
 			GfaMininetMasterRestoreTimeouts(pBlm->hMst);
 			return -1;
 		}
-		
+
 		if((nRet = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) <= 0)
 		{
-			_EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 0, errno);
+			pBlm->dlpp.nCtx			= GBDPS_Error;
+			pBlm->dlpp.nErrorCode	= errno;
+			_EXEC_PROGRESS_CALLBACK(pBlm->pfnDlProgress, &pBlm->dlpp);
 			GfaMininetMasterRestoreTimeouts(pBlm->hMst);
 			return -1;
 		}
-		
-		_EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 2, 0);
+
 		GfaMininetMasterRestoreTimeouts(pBlm->hMst);
 		nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nRet, true, &nIndex);
 
@@ -462,7 +496,9 @@ int GfaBlmBUCmdDownload(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nFlashStartAdd
 		{
 			if((nRet = GfaMininetMasterGetDataFromSlaveFrame(rxb, nLen, ack, 2)) != 2)
 			{
-				_EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 0, errno);
+				pBlm->dlpp.nCtx			= GBDPS_Error;
+				pBlm->dlpp.nErrorCode	= errno;
+				_EXEC_PROGRESS_CALLBACK(pBlm->pfnDlProgress, &pBlm->dlpp);
 				return -1;
 			}
 
@@ -470,12 +506,15 @@ int GfaBlmBUCmdDownload(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nFlashStartAdd
 			{
 				if((nRet = GfaBlmBUCmdGetStatus(hBlm, nNodeAddr, &nStatus)))
 				{
-					_EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 0, errno);
+					pBlm->dlpp.nCtx			= GBDPS_Error;
+					pBlm->dlpp.nErrorCode	= errno;
+					_EXEC_PROGRESS_CALLBACK(pBlm->pfnDlProgress, &pBlm->dlpp);
 					return -1;
 				}
 				if(nStatus == COMMAND_RET_SUCCESS)
 				{
-					_EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 3, 0);
+					pBlm->dlpp.nCtx = GBDPS_EndEraseFlash;
+					_EXEC_PROGRESS_CALLBACK(pBlm->pfnDlProgress, &pBlm->dlpp);
 					return 0;
 				}
 			}
@@ -487,7 +526,9 @@ int GfaBlmBUCmdDownload(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nFlashStartAdd
 		{
 			if((nRet = GfaBlmBUCmdPollData(hBlm, nNodeAddr, ack, 2, nTimeoutMS)) != 2)
 			{
-				_EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 0, errno);
+				pBlm->dlpp.nCtx			= GBDPS_Error;
+				pBlm->dlpp.nErrorCode	= errno;
+				_EXEC_PROGRESS_CALLBACK(pBlm->pfnDlProgress, &pBlm->dlpp);
 				return -1;
 			}
 
@@ -495,30 +536,39 @@ int GfaBlmBUCmdDownload(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nFlashStartAdd
 			{
 				if((nRet = GfaBlmBUCmdGetStatus(hBlm, nNodeAddr, &nStatus)))
 				{
-					_EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 0, errno);
+					pBlm->dlpp.nCtx			= GBDPS_Error;
+					pBlm->dlpp.nErrorCode	= errno;
+					_EXEC_PROGRESS_CALLBACK(pBlm->pfnDlProgress, &pBlm->dlpp);
 					return -1;
 				}
 				if(nStatus == COMMAND_RET_SUCCESS)
 				{
-					_EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 3, 0);
+					pBlm->dlpp.nCtx = GBDPS_EndEraseFlash;
+					_EXEC_PROGRESS_CALLBACK(pBlm->pfnDlProgress, &pBlm->dlpp);
 					return 0;
 				}
 			}
 
 			errno = EPROTO;
-			_EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 0, errno);
+			pBlm->dlpp.nCtx			= GBDPS_Error;
+			pBlm->dlpp.nErrorCode	= errno;
+			_EXEC_PROGRESS_CALLBACK(pBlm->pfnDlProgress, &pBlm->dlpp);
 			return -1;
 		}
 		else if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE)
 		{
 			errno = -(int)nIndex;
-			_EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 0, errno);
+			pBlm->dlpp.nCtx			= GBDPS_Error;
+			pBlm->dlpp.nErrorCode	= errno;
+			_EXEC_PROGRESS_CALLBACK(pBlm->pfnDlProgress, &pBlm->dlpp);
 			return -1;
 		}
 		else
 		{
 			errno = EPROTO;
-			_EXEC_CALLBACK(pBlm->pfnBuCmdDownloadStatus, nNodeAddr, nFlashStartAddr, nCbData, 0, errno);
+			pBlm->dlpp.nCtx			= GBDPS_Error;
+			pBlm->dlpp.nErrorCode	= errno;
+			_EXEC_PROGRESS_CALLBACK(pBlm->pfnDlProgress, &pBlm->dlpp);
 			return -1;
 		}
 	}
@@ -540,7 +590,7 @@ int GfaBlmBUCmdSendDataBlock(HGFABLM hBlm, uint8_t nNodeAddr, const void *pDataB
 		tv.tv_usec	= 500000;
 		GfaMininetMasterSaveTimeouts(pBlm->hMst);
 		GfaMininetMasterSetTimeouts(pBlm->hMst, &tv, NULL);
-		
+
 		do
 		{
 			size_t s;
@@ -633,7 +683,7 @@ int GfaBlmBUCmdSendDataBlock(HGFABLM hBlm, uint8_t nNodeAddr, const void *pDataB
 			}
 		}
 		while(false);
-		
+
 		GfaMininetMasterRestoreTimeouts(pBlm->hMst);
 		return nRet;
 	}
@@ -652,42 +702,61 @@ int GfaBlmBUCmdSendData(HGFABLM hBlm, uint8_t nNodeAddr, const void *pData, size
 		LPGFA_BLM pBlm = (LPGFA_BLM)hBlm;
 		const uint8_t *pbData = (const uint8_t*)pData;
 		uint32_t nSent = 0;
+		
+		if(pBlm->dlpp.nNodeAddr != nNodeAddr)
+		{
+			errno = EINVAL;
+			return -1;
+		}
 
-		if(!nCbBlock || nCbBlock < 4 || nCbBlock > _MAX_SEND_DATA_BLOCK_SIZE)
-			nCbBlock = _DEF_SEND_DATA_BLOCK_SIZE;
+		if(!nCbBlock || nCbBlock < 4 || nCbBlock > GFA_BOOTLOADER_MAX_SEND_DATA_BLOCK_SIZE)
+			nCbBlock = GFA_BOOTLOADER_MAX_SEND_DATA_BLOCK_SIZE;
 		else
 			nCbBlock &= ~0x03;
 
-		_EXEC_CALLBACK(pBlm->pfnBuCmdSendDataStatus, nNodeAddr, nCbBlock, nSent, 1, 0);
-		
+		pBlm->dlpp.nCtx		= GBDPS_StartUploadBlocks;
+		pBlm->dlpp.nCbBlock	= nCbBlock;
+		pBlm->dlpp.nCbSent	= nSent;
+		_EXEC_PROGRESS_CALLBACK(pBlm->pfnDlProgress, &pBlm->dlpp);
+
 		while(nCbData >= nCbBlock)
 		{
 			if((nRet = GfaBlmBUCmdSendDataBlock(hBlm, nNodeAddr, pbData, nCbBlock)) != 0)
 			{
-				_EXEC_CALLBACK(pBlm->pfnBuCmdSendDataStatus, nNodeAddr, nCbBlock, nSent, 0, errno);
+				pBlm->dlpp.nCtx			= GBDPS_Error;
+				pBlm->dlpp.nErrorCode	= errno;
+				_EXEC_PROGRESS_CALLBACK(pBlm->pfnDlProgress, &pBlm->dlpp);
 				return -1;
 			}
 			nCbData -= nCbBlock;
 			pbData += nCbBlock;
 			nSent += nCbBlock;
 
-			_EXEC_CALLBACK(pBlm->pfnBuCmdSendDataStatus, nNodeAddr, nCbBlock, nSent, 2, 0);
+			pBlm->dlpp.nCtx		= GBDPS_UploadBlock;
+			pBlm->dlpp.nCbSent	= nSent;
+			_EXEC_PROGRESS_CALLBACK(pBlm->pfnDlProgress, &pBlm->dlpp);
 		}
-		
+
 		if(nCbData)
 		{
 			if((nRet = GfaBlmBUCmdSendDataBlock(hBlm, nNodeAddr, pbData, nCbData)) != 0)
 			{
-				_EXEC_CALLBACK(pBlm->pfnBuCmdSendDataStatus, nNodeAddr, nCbBlock, nSent, 0, errno);
+				pBlm->dlpp.nCtx			= GBDPS_Error;
+				pBlm->dlpp.nErrorCode	= errno;
+				_EXEC_PROGRESS_CALLBACK(pBlm->pfnDlProgress, &pBlm->dlpp);
 				return -1;
 			}
 			nSent += nCbData;
 			nCbData = 0;
 
-			_EXEC_CALLBACK(pBlm->pfnBuCmdSendDataStatus, nNodeAddr, nCbBlock, nSent, 2, 0);
+			pBlm->dlpp.nCtx		= GBDPS_UploadBlock;
+			pBlm->dlpp.nCbSent	= nSent;
+			_EXEC_PROGRESS_CALLBACK(pBlm->pfnDlProgress, &pBlm->dlpp);
 		}
 
-		_EXEC_CALLBACK(pBlm->pfnBuCmdSendDataStatus, nNodeAddr, nCbBlock, nSent, 3, 0);
+		pBlm->dlpp.nCtx		= GBDPS_EndUploadBlocks;
+		pBlm->dlpp.nCbSent	= nSent;
+		_EXEC_PROGRESS_CALLBACK(pBlm->pfnDlProgress, &pBlm->dlpp);
 		return 0;
 	}
 
@@ -705,7 +774,7 @@ int GfaBlmBUCmdSendDataFile(HGFABLM hBlm, uint8_t nNodeAddr, const char *pszFile
 		ssize_t nFileLen;
 		FILE *pf = NULL;
 		uint8_t *pBuf = NULL;
-		
+
 		do
 		{
 			if(!(pf = fopen(pszFilename, "rb")))
@@ -725,7 +794,7 @@ int GfaBlmBUCmdSendDataFile(HGFABLM hBlm, uint8_t nNodeAddr, const char *pszFile
 		    }
 		}
 		while(false);
-		
+
 		if(pBuf)
 			free(pBuf);
 		if(pf)
@@ -744,24 +813,29 @@ GFA_BLM_EXEC_CONTEXT GfaBlmGetExecutionContext(HGFABLM hBlm, uint8_t nNodeAddr)
 {
 	if(hBlm && !NODE_IS_MULTICAST(nNodeAddr))
 	{
+		uint32_t nLoops = 0;
 		uint8_t nIndex;
 		ssize_t nRet, nLen;
 		LPGFA_BLM pBlm = (LPGFA_BLM)hBlm;
-		char txb[32], rxb[32];
+		char txb[32], rxb[256];
 
-	    nLen = GfaMininetMasterBuildFrame(pBlm->hMst, nNodeAddr, 0, "BU", 2, txb, sizeof(txb));
+		do
+		{
+		    nLen = GfaMininetMasterBuildFrame(pBlm->hMst, nNodeAddr, 0, "BU", 2, txb, sizeof(txb));
 
-		if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen)
-			return GfaBlmCtx_Err;
+			if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen)
+				return GfaBlmCtx_Err;
 
-		if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) <= 0)
-			return GfaBlmCtx_Err;
+			if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) <= 0)
+				return GfaBlmCtx_Err;
 
-		nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex);
+			nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex);
+		}
+		while((nRet == MINET_SLAVE_RESPONSE_SUCCESS) && (nLoops++ < 10));
 
 		if(nRet == MINET_SLAVE_RESPONSE_SUCCESS)
 			return GfaBlmCtx_Err;
-		else if(nRet == MINET_SLAVE_RESPONSE_ACK)
+		if(nRet == MINET_SLAVE_RESPONSE_ACK)
 			return GfaBlmCtx_Boot;
 		else if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE)
 			return GfaBlmCtx_App;
@@ -790,8 +864,8 @@ int GfaBlmBootloaderExecute(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t *pnImgCRC3
 		if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen)
 			return -1;
 
-		if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) < 0)
-			return nLen;
+		if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) <= 0)
+			return -1;
 
 		nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex);
 
@@ -802,12 +876,14 @@ int GfaBlmBootloaderExecute(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t *pnImgCRC3
 				if(pnImgCRC32)
 					*pnImgCRC32 = bswap_32(nImgCRC32);
 
+				GfaBlmSetDeviceBaudrate(hBlm, _BOOTLOADER_DEF_BAUDRATE);
+
 				do
 				{
-					if(nTimeoutMS > _BOOTLOADER_EXEC_WAIT_TIME)
+					if(nTimeoutMS > GFA_BOOTLOADER_EXEC_WAIT_TIME)
 					{
-						usleep(_BOOTLOADER_EXEC_WAIT_TIME * 1000);
-						nTimeoutMS -= _BOOTLOADER_EXEC_WAIT_TIME;
+						usleep(GFA_BOOTLOADER_EXEC_WAIT_TIME * 1000);
+						nTimeoutMS -= GFA_BOOTLOADER_EXEC_WAIT_TIME;
 					}
 					else
 					{
@@ -843,6 +919,34 @@ int GfaBlmBootloaderExecute(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t *pnImgCRC3
 
 /////////////////////////////////////////////////////////////////////////////
 
+int GfaBlmGetDeviceBaudrate(HGFABLM hBlm, uint32_t *pnBaudrate)
+{
+	if(hBlm)
+	{
+		LPGFA_BLM pBlm = (LPGFA_BLM)hBlm;
+		return GfaMininetMasterGetBaudrate(pBlm->hMst, pnBaudrate);
+	}
+
+	errno = EINVAL;
+	return -1;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+int GfaBlmSetDeviceBaudrate(HGFABLM hBlm, uint32_t nBaudrate)
+{
+	if(hBlm)
+	{
+		LPGFA_BLM pBlm = (LPGFA_BLM)hBlm;
+		return GfaMininetMasterSetBaudrate(pBlm->hMst, nBaudrate);
+	}
+
+	errno = EINVAL;
+	return -1;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
 int GfaBlmBootloaderSetBaudrate(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nBaudrate)
 {
 	if(hBlm)
@@ -851,7 +955,7 @@ int GfaBlmBootloaderSetBaudrate(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nBaudr
 		size_t s;
 		ssize_t nRet, nLen;
 		LPGFA_BLM pBlm = (LPGFA_BLM)hBlm;
-		
+
 		if(GfaMininetMasterIsValidBaudrate(pBlm->hMst, nBaudrate))
 		{
 			char txb[32], rxb[32], cmd[8];
@@ -862,12 +966,12 @@ int GfaBlmBootloaderSetBaudrate(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nBaudr
 
 			if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen)
 				return nRet;
-			
+
 			if(NODE_IS_MULTICAST(nNodeAddr))
 				return 0;
 
-			if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) < 0)
-				return nLen;
+			if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) <= 0)
+				return -1;
 
 			nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex);
 
@@ -923,8 +1027,8 @@ int GfaBlmBootloaderDump(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nAddress, uin
 		if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen)
 			return nRet;
 
-		if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) < 0)
-			return nLen;
+		if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) <= 0)
+			return -1;
 
 		nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex);
 
@@ -1161,7 +1265,7 @@ int GfaBlmGetImgInfo(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nDumpAddr, bool b
 
 /////////////////////////////////////////////////////////////////////////////
 
-int GfaBlmGetInfoBD(HGFABLM hBlm, uint8_t nNodeAddr, LPGFA_BL_APP_IMG_INFO paii)
+int GfaBlmGetInfoBD(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nAppBaseAddr, LPGFA_BL_APP_IMG_INFO paii)
 {
 	if(hBlm && paii && !NODE_IS_MULTICAST(nNodeAddr))
 	{
@@ -1173,7 +1277,7 @@ int GfaBlmGetInfoBD(HGFABLM hBlm, uint8_t nNodeAddr, LPGFA_BL_APP_IMG_INFO paii)
 			paii->bl.nImgLength = paii->bl.nImgCRC32 = 0xFFFFFFFF;
 		}
 
-		if((nRet2 = GfaBlmGetImgInfo(hBlm, nNodeAddr, GFA_APP_APPLICATION_START_ADDRESS, true, &paii->app)) < 0)
+		if((nRet2 = GfaBlmGetImgInfo(hBlm, nNodeAddr, nAppBaseAddr, true, &paii->app)) < 0)
 		{
 			memset(&paii->app, 0, sizeof(paii->app));
 			paii->app.nImgLength = paii->app.nImgCRC32 = 0xFFFFFFFF;
@@ -1202,8 +1306,8 @@ int GfaBlmGetInfoBI(HGFABLM hBlm, uint8_t nNodeAddr, LPGFA_BL_APP_IMG_INFO paii)
 		if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen)
 			return nRet;
 
-		if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) < 0)
-			return nLen;
+		if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) <= 0)
+			return -1;
 
 		nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex);
 
@@ -1256,8 +1360,8 @@ int GfaBlmReadMaterialAndSerialID(HGFABLM hBlm, uint8_t nNodeAddr, char *pszMate
 		if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen)
 			return nRet;
 
-		if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) < 0)
-			return nLen;
+		if((nLen = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) <= 0)
+			return -1;
 
 		nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nLen, true, &nIndex);
 
@@ -1317,7 +1421,10 @@ int GfaBlmWriteMaterialAndSerialID(HGFABLM hBlm, uint8_t nNodeAddr, const char *
 		nLenSerial		= strlen(pszSerial);
 
 		if((nLenMaterial > 15) || (nLenSerial > 15))
+		{
+			errno = EINVAL;
 			return -1;
+		}
 
 		memcpy(ts.szMaterial, pszMaterial, nLenMaterial);
 		if(nLenMaterial < 15)
@@ -1335,8 +1442,8 @@ int GfaBlmWriteMaterialAndSerialID(HGFABLM hBlm, uint8_t nNodeAddr, const char *
 		if((nRet = GfaMininetMasterTransmitFrame(pBlm->hMst, txb, nLen)) != nLen)
 			return nRet;
 
-		if((nRet = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) < 0)
-			return nRet;
+		if((nRet = GfaMininetMasterReceiveFrame(pBlm->hMst, rxb, sizeof(rxb), true)) <= 0)
+			return -1;
 
 		nRet = GfaMininetMasterEvaluateSlaveResponse(pBlm->hMst, nNodeAddr, rxb, nRet, true, &nIndex);
 

+ 43 - 8
libmininet/gfabootlmast.h

@@ -31,7 +31,11 @@ typedef void													*HGFABLM;
 ////////////////////////////////////////////////////////////////////////////////////
 
 #define GFA_APP_BOOTLOADER_START_ADDRESS						((uint32_t)0x00000000)
-#define GFA_APP_APPLICATION_START_ADDRESS						((uint32_t)0x00002000)
+#define GFA_BOOTLOADER_FLASH_PAGE_SIZE							((uint32_t)1024)
+#define GFA_BOOTLOADER_MIN_SEND_DATA_BLOCK_SIZE					4
+#define GFA_BOOTLOADER_MAX_SEND_DATA_BLOCK_SIZE					76
+#define GFA_BOOTLOADER_DEF_SEND_DATA_BLOCK_SIZE					GFA_BOOTLOADER_MAX_SEND_DATA_BLOCK_SIZE
+#define GFA_BOOTLOADER_EXEC_WAIT_TIME							250
 
 ////////////////////////////////////////////////////////////////////////////////////
 
@@ -60,16 +64,42 @@ typedef const GFA_APP_IMG_HEADER *LPCGFA_APP_IMG_HEADER;
 
 /////////////////////////////////////////////////////////////////////////////
 
-typedef void (*PFN_BU_CMD_DOWNLOAD_STATUS)(const char *pszFile, int nLine, uint8_t nNodeAddr, uint32_t nFlashStartAddr, uint32_t nCbData, int nCtx, int nErrorCode);
-typedef void (*PFN_BU_CMD_SEND_DATA_STATUS)(const char *pszFile, int nLine, uint8_t nNodeAddr, uint32_t nCbBlock, uint32_t nCbData, int nCtx, int nErrorCode);
+typedef enum _GfaBlmDlProgressStatus
+{
+	GBDPS_Error,
+	GBDPS_StartEraseFlash,
+	GBDPS_EndEraseFlash,
+	GBDPS_StartUploadBlocks,
+	GBDPS_UploadBlock,
+	GBDPS_EndUploadBlocks
+}GfaBlmDlProgressStatus;
+
+/////////////////////////////////////////////////////////////////////////////
+
+typedef struct _GFA_BLM_DL_PROGRESS_PARAMS
+{
+	int nCtx;
+	int nErrorCode;
+	uint32_t nCbBlock;
+	uint32_t nBlockNr;
+	uint32_t nCbTotal;
+	uint32_t nCbSent;
+	uint32_t nFlashStartAddr;
+	uint32_t nCntFlashPages;
+	uint8_t nNodeAddr;
+	void *pParam;
+}GFA_BLM_DL_PROGRESS_PARAMS, *LPGFA_BLM_DL_PROGRESS_PARAMS;
+typedef const GFA_BLM_DL_PROGRESS_PARAMS *LPCGFA_BLM_DL_PROGRESS_PARAMS;
+
+typedef void (*PFN_GFA_BLM_DL_PROGRESS)(const char *pszFile, int nLine, LPGFA_BLM_DL_PROGRESS_PARAMS pDlProgress);
 
 /////////////////////////////////////////////////////////////////////////////
 
 typedef struct _GFA_BLM_CFG_PARAMS
 {
 	GFA_MININET_MST_CFG_PARAMS mmcp;
-	PFN_BU_CMD_DOWNLOAD_STATUS pfnBuCmdDownloadStatus;
-	PFN_BU_CMD_SEND_DATA_STATUS pfnBuCmdSendDataStatus;
+	PFN_GFA_BLM_DL_PROGRESS pfnDlProgress;
+	void *pUserParam;
 }GFA_BLM_CFG_PARAMS, *LPGFA_BLM_CFG_PARAMS;
 typedef const GFA_BLM_CFG_PARAMS *LPCGFA_BLM_CFG_PARAMS;
 
@@ -79,7 +109,8 @@ typedef enum _GFA_BLM_EXEC_CONTEXT
 {
 	GfaBlmCtx_Err = -1,
 	GfaBlmCtx_Boot,
-	GfaBlmCtx_App
+	GfaBlmCtx_App,
+	GfaBlmCtx_ModB
 }GFA_BLM_EXEC_CONTEXT, *LPGFA_BLM_EXEC_CONTEXT;
 
 /////////////////////////////////////////////////////////////////////////////
@@ -119,15 +150,16 @@ int GfaBlmBootloaderExecute(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t *pnImgCRC3
 int GfaBlmBootloaderSetBaudrate(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nBaudrate);
 int GfaBlmBootloaderDump(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nAddress, uint32_t nCntDwords, void *pBuffer, size_t nCbBuffer);
 int GfaBlmGetImgInfo(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nDumpAddr, bool bCtxIsApp, LPGFA_IMG_INFO pii);
-int GfaBlmGetInfoBD(HGFABLM hBlm, uint8_t nNodeAddr, LPGFA_BL_APP_IMG_INFO paii);
+int GfaBlmGetInfoBD(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nAppBaseAddr, LPGFA_BL_APP_IMG_INFO paii);
 int GfaBlmGetInfoBI(HGFABLM hBlm, uint8_t nNodeAddr, LPGFA_BL_APP_IMG_INFO paii);
 int GfaBlmReadMaterialAndSerialID(HGFABLM hBlm, uint8_t nNodeAddr, char *pszMaterial, size_t nCbMaterial, char *pszSerial, size_t nCbSerial);
 int GfaBlmWriteMaterialAndSerialID(HGFABLM hBlm, uint8_t nNodeAddr, const char *pszMaterial, const char *pszSerial);
+int GfaBlmMininetPing(HGFABLM hBlm, uint8_t nNodeAddr);
 
 /////////////////////////////////////////////////////////////////////////////
 // TI commands
 
-int GfaBlmBUCmdReset(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nTimeoutMS);
+int GfaBlmBUCmdReset(HGFABLM hBlm, uint8_t nNodeAddr, uint32_t nInitialBaudrate);
 int GfaBlmBUCmdPing(HGFABLM hBlm, uint8_t nNodeAddr);
 int GfaBlmBUCmdGetStatus(HGFABLM hBlm, uint8_t nNodeAddr, uint8_t *pbStatus);
 ssize_t GfaBlmBUCmdPollData(HGFABLM hBlm, uint8_t nNodeAddr, void *pData, size_t nCbData, uint32_t nTimeoutMS);
@@ -139,6 +171,9 @@ int GfaBlmBUCmdSendDataFile(HGFABLM hBlm, uint8_t nNodeAddr, const char *pszFile
 
 /////////////////////////////////////////////////////////////////////////////
 
+int GfaBlmGetDeviceBaudrate(HGFABLM hBlm, uint32_t *pnBaudrate);
+int GfaBlmSetDeviceBaudrate(HGFABLM hBlm, uint32_t nBaudrate);
+
 int GfaBlmSetVerbosity(HGFABLM hBlm, int nVerbosity);
 HGFAMINEMST GfaBlmGetMininetMasterHandle(HGFABLM hBlm);
 uint8_t	GfaBlmDataCheckSum(const void *pData, size_t nCbData);

+ 2 - 0
libmininet/gfagenericdev.h

@@ -23,6 +23,7 @@ typedef void		(*PFN_GFA_GENERIC_DEV_CLOSE)			(HGFADEVICE hDev);
 typedef ssize_t		(*PFN_GFA_GENERIC_DEV_GET_CONFIG)		(HGFADEVICE hDev, void *pcp, size_t nSizeCfgParams);
 typedef int			(*PFN_GFA_GENERIC_DEV_SET_CONFIG)		(HGFADEVICE hDev, const void *pcp, size_t nSizeCfgParams);
 typedef bool		(*PFN_GFA_GENERIC_DEV_IS_VALID_BAUD)	(uint32_t nBaudrate);
+typedef int			(*PFN_GFA_GENERIC_DEV_GET_BAUDRATE)		(HGFADEVICE hDev, uint32_t *pnBaudrate);
 typedef int			(*PFN_GFA_GENERIC_DEV_SET_BAUDRATE)		(HGFADEVICE hDev, uint32_t nBaudrate);
 typedef bool		(*PFN_GFA_GENERIC_DEV_GET_TIMEOUTS)		(HGFADEVICE hDev, struct timeval *ptvRX, struct timeval *ptvTX);
 typedef bool		(*PFN_GFA_GENERIC_DEV_SET_TIMEOUTS)		(HGFADEVICE hDev, const struct timeval *ptvRX, const struct timeval *ptvTX);
@@ -44,6 +45,7 @@ typedef struct _GFA_GENERIC_DEVICE_INTERFACE
 	PFN_GFA_GENERIC_DEV_GET_CONFIG		pfnGetConfig;
 	PFN_GFA_GENERIC_DEV_SET_CONFIG		pfnSetConfig;
 	PFN_GFA_GENERIC_DEV_IS_VALID_BAUD	pfnIsValidBaudrate;
+	PFN_GFA_GENERIC_DEV_GET_BAUDRATE	pfnGetBaudrate;
 	PFN_GFA_GENERIC_DEV_SET_BAUDRATE	pfnSetBaudrate;
 	PFN_GFA_GENERIC_DEV_GET_TIMEOUTS	pfnGetTimeouts;
 	PFN_GFA_GENERIC_DEV_SET_TIMEOUTS	pfnSetTimeouts;

+ 18 - 0
libmininet/gfamininetdev.c

@@ -107,6 +107,24 @@ bool GfaMininetDeviceIsValidBaudrate(HMINETDEV hDev, uint32_t nBaudrate)
 
 /////////////////////////////////////////////////////////////////////////////
 
+int GfaMininetDeviceGetBaudrate(HMINETDEV hDev, uint32_t *pnBaudrate)
+{
+	if(hDev)
+	{
+		LPGFA_MININET_DEVICE pDev = (LPGFA_MININET_DEVICE)hDev;
+		if(pDev->itf.pfnGetBaudrate)
+			return (*pDev->itf.pfnGetBaudrate)(pDev->hDev, pnBaudrate);
+
+		errno = EOPNOTSUPP;
+		return -1;
+	}
+
+	errno = EINVAL;
+	return -1;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
 int GfaMininetDeviceSetBaudrate(HMINETDEV hDev, uint32_t nBaudrate)
 {
 	if(hDev)

+ 1 - 0
libmininet/gfamininetdev.h

@@ -34,6 +34,7 @@ void	GfaMininetDeviceClose(HMINETDEV hDev);
 ssize_t	GfaMininetDeviceGetConfigParams(HMINETDEV hDev, void *pDevParams, size_t nSizeDevParams);
 int		GfaMininetDeviceSetConfigParams(HMINETDEV hDev, const void *pDevParams, size_t nSizeDevParams);
 bool	GfaMininetDeviceIsValidBaudrate(HMINETDEV hDev, uint32_t nBaudrate);
+int		GfaMininetDeviceGetBaudrate(HMINETDEV hDev, uint32_t *pnBaudrate);
 int		GfaMininetDeviceSetBaudrate(HMINETDEV hDev, uint32_t nBaudrate);
 
 bool	GfaMininetDeviceGetTimeouts(HMINETDEV hDev, struct timeval *ptvRX, struct timeval *ptvTX);

+ 123 - 5
libmininet/gfamininetmst.c

@@ -28,6 +28,8 @@
 #define MAX_DATA_PAYLOAD_LENGTH		250
 #define MAX_SAVE_TIMOUT_DEPTH		8
 
+#define _TRACE_UNEXPECTED			1
+
 /////////////////////////////////////////////////////////////////////////////
 
 typedef enum _GfaMininetRxStates
@@ -41,6 +43,23 @@ typedef enum _GfaMininetRxStates
 	GfaRxMNS_Check
 }GfaMininetRxStates, *LPGfaMininetRxStates;
 
+#if _TRACE_UNEXPECTED
+static const char *g_pszExpected[] =
+{
+	"STX or ACK",
+	"Length (>= 5)",
+	"Node Addr.",
+	"Index (< 0x3F)",
+	"Data",
+	"STX-Zero",
+	"CRC32"
+};
+#define TRACE_UNEXPECTED(p, s, b)				if(p->nVerbosity >= 4) \
+													fprintf(p->pDumpCtx, "%s: Expected: %s - Received: 0x%02hhX\n", __FUNCTION__, g_pszExpected[s], b)
+#else	//	_TRACE_UNEXPECTED
+#define TRACE_UNEXPECTED(p, s, b)				(void)0
+#endif	//	_TRACE_UNEXPECTED
+
 /////////////////////////////////////////////////////////////////////////////
 
 typedef struct _GFA_MININET_MASTER
@@ -63,6 +82,8 @@ static bool _IsValidIndex(uint8_t nIndex)
 	return ((nIndex >= MIN_INDEX) && (nIndex <= MAX_INDEX));
 }
 
+/////////////////////////////////////////////////////////////////////////////
+
 static uint8_t _GetNextIndex(HGFAMINEMST hMst, uint8_t nNode)
 {
 	if(hMst)
@@ -79,6 +100,8 @@ static uint8_t _GetNextIndex(HGFAMINEMST hMst, uint8_t nNode)
 	return 0xFF;
 }
 
+/////////////////////////////////////////////////////////////////////////////
+
 static uint8_t _GetCurIndex(HGFAMINEMST hMst, uint8_t nNode)
 {
 	if(hMst)
@@ -91,6 +114,30 @@ static uint8_t _GetCurIndex(HGFAMINEMST hMst, uint8_t nNode)
 
 /////////////////////////////////////////////////////////////////////////////
 
+static int _CountStxBytes(const void *pData, size_t nCbData)
+{
+	int nStx = 0;
+	const uint8_t *pbData = (const uint8_t*)pData;
+	uint8_t b, n = 0;
+
+	while(nCbData > 0)
+	{
+		b = *pbData++;
+		if((n == STX) && (b == 0))
+		{
+			++nStx;
+			++nCbData;
+		}
+		n = b;
+		
+		--nCbData;
+	}
+
+	return nStx;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
 HGFAMINEMST GfaMininetMasterOpen(LPCGFA_MININET_MST_CFG_PARAMS pmmcp)
 {
 	if(pmmcp)
@@ -245,6 +292,20 @@ bool GfaMininetMasterIsValidBaudrate(HGFAMINEMST hMst, uint32_t nBaudrate)
 
 /////////////////////////////////////////////////////////////////////////////
 
+int GfaMininetMasterGetBaudrate(HGFAMINEMST hMst, uint32_t *pnBaudrate)
+{
+	if(hMst)
+	{
+		LPGFA_MININET_MASTER pMst = (LPGFA_MININET_MASTER)hMst;
+		return GfaMininetDeviceGetBaudrate(pMst->hDev, pnBaudrate);
+	}
+
+	errno = EINVAL;
+	return -1;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
 int GfaMininetMasterSetBaudrate(HGFAMINEMST hMst, uint32_t nBaudrate)
 {
 	if(hMst)
@@ -254,7 +315,7 @@ int GfaMininetMasterSetBaudrate(HGFAMINEMST hMst, uint32_t nBaudrate)
 	}
 
 	errno = EINVAL;
-	return false;
+	return -1;
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -445,16 +506,59 @@ int	GfaMininetMasterPurgeDeviceRXBuffer(HGFAMINEMST hMst)
 
 /////////////////////////////////////////////////////////////////////////////
 
+int GfaMininetMasterPingSlave(HGFAMINEMST hMst, uint8_t nNode)
+{
+	if(hMst)
+	{
+		uint8_t nIndex;
+		ssize_t nRet, nLen;
+		char txb[32], rxb[32];
+
+	    nLen = GfaMininetMasterBuildFrame(hMst, nNode, 0, NULL, 0, txb, sizeof(txb));
+
+		if((nRet = GfaMininetMasterTransmitFrame(hMst, txb, nLen)) < nLen)
+			return -1;
+
+		if((nLen = GfaMininetMasterReceiveFrame(hMst, rxb, sizeof(rxb), true)) <= 0)
+			return -1;
+
+		nRet = GfaMininetMasterEvaluateSlaveResponse(hMst, nNode, rxb, nLen, true, &nIndex);
+
+		if(nRet == MINET_SLAVE_RESPONSE_INDEX_IS_STATUS_CODE)
+		{
+			if(nIndex == MINET_SLAVE_STATUS_INDEX_INVALID_PARAM)
+				return 0;
+			else
+			{
+				errno = -(int)nIndex;
+				return -1;
+			}
+	    }
+
+		return -1;
+	}
+
+	errno = EINVAL;
+	return -1;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
 int GfaMininetMasterEvaluateSlaveResponse(HGFAMINEMST hMst, uint8_t nNode, const void *pFrame, size_t nCbFrame, bool bAckPossible, uint8_t *pbIndex)
 {
-	if(hMst && pFrame && nCbFrame > 0)
+	if(hMst && pFrame)
 	{
 		bool bIsStatusIndex = false;
 		LPCGFA_MININET_FRAME pf = (LPCGFA_MININET_FRAME)pFrame;
 
 		/////////////////////////////////////////////////////////////////////
 
-		if((nCbFrame < 6))
+		if(nCbFrame == 0)
+		{
+			errno = MINET_SLAVE_RESPONSE_ERROR_INVALID_LENGTH;
+			return -1;
+		}
+		else if(nCbFrame < 6)
 		{
 			if(bAckPossible && (pf->stx == ACK))
 			{
@@ -559,7 +663,7 @@ int GfaMininetMasterEvaluateSlaveResponse(HGFAMINEMST hMst, uint8_t nNode, const
 		}
 	}
 
-	errno = MINET_SLAVE_RESPONSE_ERROR_INVALID_ARGUMENT;
+	errno = EINVAL;
 	return -1;
 }
 
@@ -618,6 +722,10 @@ ssize_t GfaMininetMasterReceiveFrame(HGFAMINEMST hMst, void *pBuffer, size_t nCb
                         bLoop = false;
 						GfaMininetMasterDumpFrame(hMst, pMst->pDumpCtx, (LPCGFA_MININET_FRAME)pBuffer, false, NULL);
                         break;
+                    }
+                    else
+                    {
+                    	TRACE_UNEXPECTED(pMst, nState, b);
                     }
 					continue;
 				}
@@ -635,6 +743,7 @@ ssize_t GfaMininetMasterReceiveFrame(HGFAMINEMST hMst, void *pBuffer, size_t nCb
 				}
 				if(b < 5)
 				{
+                   	TRACE_UNEXPECTED(pMst, nState, b);
 					if(b == STX)
 						continue;
 					else
@@ -658,6 +767,7 @@ ssize_t GfaMininetMasterReceiveFrame(HGFAMINEMST hMst, void *pBuffer, size_t nCb
 				}
 				if(b == STX)
 				{
+                   	TRACE_UNEXPECTED(pMst, nState, b);
 					nState = GfaRxMNS_Len;
 					continue;
 				}
@@ -675,11 +785,13 @@ ssize_t GfaMininetMasterReceiveFrame(HGFAMINEMST hMst, void *pBuffer, size_t nCb
 				}
 				if(b == STX)
 				{
+                   	TRACE_UNEXPECTED(pMst, nState, b);
 					nState = GfaRxMNS_Len;
 					continue;
 				}
 				else if(b < MIN_INDEX)
 				{
+                   	TRACE_UNEXPECTED(pMst, nState, b);
 					nState = GfaRxMNS_Stx;
 					continue;
 				}
@@ -723,12 +835,14 @@ ssize_t GfaMininetMasterReceiveFrame(HGFAMINEMST hMst, void *pBuffer, size_t nCb
 				}
 				else if(b == STX)
 				{
+                   	TRACE_UNEXPECTED(pMst, nState, b);
 					nCbDataPayloadRcv = nCbDataPayloadExp = 0;
 					nState = GfaRxMNS_Len;
 					continue;
 				}
 				else if(b >= 5)
 				{
+                   	TRACE_UNEXPECTED(pMst, nState, b);
 					pFrameRx->len = b;
 					nCbDataPayloadRcv = 0;
 					nCbDataPayloadExp = b - 5;
@@ -737,6 +851,7 @@ ssize_t GfaMininetMasterReceiveFrame(HGFAMINEMST hMst, void *pBuffer, size_t nCb
 				}
 				else
 				{
+                   	TRACE_UNEXPECTED(pMst, nState, b);
 					nCbDataPayloadRcv = nCbDataPayloadExp = 0;
 					nState = GfaRxMNS_Stx;
 					continue;
@@ -752,6 +867,7 @@ ssize_t GfaMininetMasterReceiveFrame(HGFAMINEMST hMst, void *pBuffer, size_t nCb
 				}
 				if(b == STX)
 				{
+                   	TRACE_UNEXPECTED(pMst, nState, b);
 					nCbDataPayloadRcv = nCbDataPayloadExp = 0;
 					nState = GfaRxMNS_Len;
 					continue;
@@ -906,9 +1022,11 @@ void GfaMininetMasterDumpFrame(HGFAMINEMST hMst, FILE *pf, LPCGFA_MININET_FRAME
 					fprintf(pf, "Index:  %02hhX (%hhu)\n", pFrame->index, pFrame->index);
 					fprintf(pf, "Data:   ");
 
+					nCbData += _CountStxBytes(pFrame->data.by, nCbData);
+
 					for(i = 0; i < nCbData; i++)
 					{
-						if(pFrame->data.by[i] >= 0x41 && pFrame->data.by[i] <= 0x5A)
+						if((i < 2) && (pFrame->data.by[i] >= 0x41) && (pFrame->data.by[i] <= 0x5A))
 							fprintf(pf, "<%c>", (char)pFrame->data.by[i]);
 						else
 							fprintf(pf, "[%02hhX]", (char)pFrame->data.by[i]);

+ 2 - 0
libmininet/gfamininetmst.h

@@ -90,6 +90,7 @@ int		GfaMininetMasterEvaluateSlaveResponse(HGFAMINEMST hMst, uint8_t nNode, cons
 int		GfaMininetMasterResetSlaveIndex(HGFAMINEMST hMst, uint8_t nNode);
 int		GfaMininetMasterResetLocalIndex(HGFAMINEMST hMst, uint8_t nNode);
 int		GfaMininetMasterPurgeDeviceRXBuffer(HGFAMINEMST hMst);
+int		GfaMininetMasterPingSlave(HGFAMINEMST hMst, uint8_t nNode);
 
 bool	GfaMininetMasterGetTimeouts(HGFAMINEMST hMst, struct timeval *ptvRX, struct timeval *ptvTX);
 bool	GfaMininetMasterSetTimeouts(HGFAMINEMST hMst, const struct timeval *ptvRX, const struct timeval *ptvTX);
@@ -99,6 +100,7 @@ bool	GfaMininetMasterRestoreTimeouts(HGFAMINEMST hMst);
 ssize_t	GfaMininetMasterGetConfigParams(HGFAMINEMST hMst, void *pDevParams, size_t nSizeDevParams);
 int		GfaMininetMasterSetConfigParams(HGFAMINEMST hMst, const void *pDevParams, size_t nSizeDevParams);
 bool	GfaMininetMasterIsValidBaudrate(HGFAMINEMST hMst, uint32_t nBaudrate);
+int		GfaMininetMasterGetBaudrate(HGFAMINEMST hMst, uint32_t *pnBaudrate);
 int		GfaMininetMasterSetBaudrate(HGFAMINEMST hMst, uint32_t nBaudrate);
 
 HMINETDEV GfaMininetMasterGetDeviceHandle(HGFAMINEMST hMst);

+ 110 - 12
libmininet/gfaserial.c

@@ -8,6 +8,7 @@
 #include <unistd.h>
 #include <ctype.h>
 #include <sys/file.h>
+#include <dirent.h>
 #include "gfaserial.h"
 
 #define min(a, b)			(((a) < (b)) ? (a) : (b))
@@ -19,6 +20,8 @@
 typedef struct _GFA_SERIAL_DEVICE
 {
 	int fd;
+	bool bFdLocked;
+	bool bAttrSet;
 	char *pszDeviceName;
 	GFA_SER_CFG_PARAMS cfg;
 	struct termios tty;
@@ -66,6 +69,58 @@ static speed_t _MapBaudrate(uint32_t b)
 
 /////////////////////////////////////////////////////////////////////////////
 
+static int _GetDeviceAccess(const char *pszDev)
+{
+	int nRet = 0;
+
+	if(pszDev && *pszDev)
+	{
+		DIR *pd;
+		const char *pszRp;
+		const struct dirent *pde, *pde2;
+		char szDir[512], szPath[512], szRealPath[512];
+		
+		if((pd = opendir("/proc")))
+		{
+			while((pde = readdir(pd)))
+			{
+				if(pde->d_type == DT_DIR && isdigit(*pde->d_name))
+				{
+					DIR *pd2;
+					sprintf(szDir, "/proc/%s/fd", pde->d_name);
+
+					if((pd2 = opendir(szDir)))
+					{
+						while((pde2 = readdir(pd2)))
+						{
+							if(pde2->d_type == DT_LNK)
+							{
+								sprintf(szPath, "%s/%s", szDir, pde2->d_name);
+
+								if((pszRp = realpath(szPath, szRealPath)))
+								{
+									if(!strcmp(szRealPath, pszDev))
+										++nRet;
+								}
+							}
+						}
+
+						closedir(pd2);
+					}
+					
+					
+				}
+			}
+
+			closedir(pd);
+		}
+	}
+
+	return nRet;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
 static void _SetDefaultTimeouts(LPGFA_SERIAL_DEVICE psd)
 {
 	if(psd)
@@ -77,10 +132,12 @@ static void _SetDefaultTimeouts(LPGFA_SERIAL_DEVICE psd)
 		psd->tvEcho.tv_sec		= 0;
 		psd->tvEcho.tv_usec		= 50000;
 		psd->tvPurge.tv_sec		= 0;
-		psd->tvPurge.tv_usec	= 10000;
+		psd->tvPurge.tv_usec	= 20000;
 	}
 }
 
+/////////////////////////////////////////////////////////////////////////////
+
 static void _CopyTimeval(struct timeval *ptvTo, const struct timeval *ptvFrom)
 {
 	ptvTo->tv_sec	= ptvFrom->tv_sec;
@@ -135,13 +192,27 @@ HGFADEVICE GfaSerialOpen(const char *pszDeviceName, LPCGFA_SER_CFG_PARAMS pscp,
 {
 	if(pszDeviceName && *pszDeviceName && pscp && nSizeCfgParams >= sizeof(GFA_SER_CFG_PARAMS))
 	{
+		int nDevAcc, nFlags;
 		LPGFA_SERIAL_DEVICE psd = malloc(sizeof(GFA_SERIAL_DEVICE));
 		memset(psd, 0, sizeof(GFA_SERIAL_DEVICE));
+		psd->fd = -1;
+		
+		if((nDevAcc = _GetDeviceAccess(pszDeviceName)) > 0)
+		{
+			GfaSerialClose(psd);
+			errno = EBUSY;
+			return NULL;
+		}
 		
 		/////////////////////////////////////////////////////////////////////
 		// Open the device
 
-		if((psd->fd = open(pszDeviceName, O_RDWR | O_NONBLOCK)) < 0)
+		nFlags = O_RDWR | O_NONBLOCK | O_NOCTTY | O_NDELAY | O_SYNC | O_EXCL;
+#ifdef O_CLOEXEC
+		nFlags |= O_CLOEXEC;
+#endif
+
+		if((psd->fd = open(pszDeviceName, nFlags)) < 0)
 		{
 			GfaSerialClose(psd);
 		    return NULL;
@@ -156,16 +227,16 @@ HGFADEVICE GfaSerialOpen(const char *pszDeviceName, LPCGFA_SER_CFG_PARAMS pscp,
 		    return NULL;
 		}
 		
+		psd->bFdLocked = true;
+		
 		/////////////////////////////////////////////////////////////////////
 		// Get current config and save it for restore on close
 
-		if(tcgetattr(psd->fd, &psd->tty) != 0)
+		if(tcgetattr(psd->fd, &psd->ttySave) != 0)
 		{
 			GfaSerialClose(psd);
 		    return NULL;
 		}
-
-		memcpy(&psd->ttySave, &psd->tty, sizeof(struct termios));
 		
 		/////////////////////////////////////////////////////////////////////
 		// Set new config
@@ -176,6 +247,8 @@ HGFADEVICE GfaSerialOpen(const char *pszDeviceName, LPCGFA_SER_CFG_PARAMS pscp,
 		    return NULL;
 		}
 
+		psd->bAttrSet = true;
+
 		/////////////////////////////////////////////////////////////////////
 		// Set deault timeouts.
 
@@ -203,8 +276,10 @@ void GfaSerialClose(HGFADEVICE hSer)
 		LPGFA_SERIAL_DEVICE psd = (LPGFA_SERIAL_DEVICE)hSer;
 		if(psd->fd >= 0)
 		{
-			tcsetattr(psd->fd, TCSAFLUSH, &psd->ttySave);
-			flock(psd->fd, LOCK_UN | LOCK_NB);
+			if(psd->bAttrSet)
+				tcsetattr(psd->fd, TCSAFLUSH, &psd->ttySave);
+			if(psd->bFdLocked)
+				flock(psd->fd, LOCK_UN | LOCK_NB);
 			close(psd->fd);
 		}
 		if(psd->pszDeviceName)
@@ -303,13 +378,16 @@ int GfaSerialSetConfig(HGFADEVICE hSer, LPCGFA_SER_CFG_PARAMS pscp, size_t nSize
 		{
 		case 'N':
 			psd->tty.c_cflag &= ~(PARENB | PARODD);	// Clear parity bit, disabling parity
+	        psd->tty.c_iflag &= ~INPCK;
 			break;
 		case 'E':
-			psd->tty.c_cflag |= PARENB;		// Set parity bit, enabling parity
-			psd->tty.c_cflag &= ~PARODD;	// Clear odd parity bit, enabling even parity
+			psd->tty.c_cflag |= PARENB;				// Set parity bit, enabling parity
+			psd->tty.c_cflag &= ~PARODD;			// Clear odd parity bit, enabling even parity
+	        psd->tty.c_iflag |= INPCK;
 			break;
 		case 'O':
-			psd->tty.c_cflag |= (PARENB | PARODD);	// Set parity bits, enabling odd parity
+			psd->tty.c_cflag |= (PARENB | PARODD);	// Set parity and odd bit, enabling odd parity
+	        psd->tty.c_iflag |= INPCK;
 			break;
 		default:
 			errno = EINVAL;
@@ -330,7 +408,7 @@ int GfaSerialSetConfig(HGFADEVICE hSer, LPCGFA_SER_CFG_PARAMS pscp, size_t nSize
 		/////////////////////////////////////////////////////////////////////
 		// Setting CLOCAL disables modem-specific signal lines such as carrier detect. It also
 		// prevents the controlling process from getting sent a SIGHUP signal when a modem disconnect
-		// is detected, which is usually a good thing here. Setting CLOCAL allows us to read data (we definitely want that!).
+		// is detected, which is usually a good thing here. Setting CREAD allows us to read data (we definitely want that!).
 
 		psd->tty.c_cflag |= (CREAD | CLOCAL); // Turn on READ & ignore ctrl lines (CLOCAL = 1)
 
@@ -390,7 +468,7 @@ int GfaSerialSetConfig(HGFADEVICE hSer, LPCGFA_SER_CFG_PARAMS pscp, size_t nSize
 		/////////////////////////////////////////////////////////////////////
 		// set configuration
 
-		if((nRet = tcsetattr(psd->fd, TCSAFLUSH, &psd->tty)) == 0)
+		if((nRet = tcsetattr(psd->fd, TCSANOW/*TCSAFLUSH*/, &psd->tty)) == 0)
 			memcpy(&psd->cfg, pscp, sizeof(GFA_SER_CFG_PARAMS));
 		return nRet;
 	}
@@ -401,6 +479,25 @@ int GfaSerialSetConfig(HGFADEVICE hSer, LPCGFA_SER_CFG_PARAMS pscp, size_t nSize
 
 /////////////////////////////////////////////////////////////////////////////
 
+int GfaSerialGetBaudrate(HGFADEVICE hSer, uint32_t *pnBaudrate)
+{
+	if(hSer && pnBaudrate)
+	{
+		GFA_SER_CFG_PARAMS scp;
+
+		if(GfaSerialGetConfig(hSer, &scp, sizeof(scp)) == sizeof(scp))
+		{
+			*pnBaudrate = scp.baud;
+			return 0;
+		}
+	}
+
+	errno = EINVAL;
+    return -1;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
 int GfaSerialSetBaudrate(HGFADEVICE hSer, uint32_t nBaudrate)
 {
 	if(hSer && GfaSerialIsValidBaudrate(nBaudrate))
@@ -429,6 +526,7 @@ bool GfaSerialGetDeviceInterface(LPGFA_GENERIC_DEVICE_INTERFACE pDevItf)
 		pDevItf->pfnGetConfig		= (PFN_GFA_GENERIC_DEV_GET_CONFIG)GfaSerialGetConfig;
 		pDevItf->pfnSetConfig		= (PFN_GFA_GENERIC_DEV_SET_CONFIG)GfaSerialSetConfig;
 		pDevItf->pfnIsValidBaudrate = GfaSerialIsValidBaudrate;
+		pDevItf->pfnGetBaudrate		= GfaSerialGetBaudrate;
 		pDevItf->pfnSetBaudrate		= GfaSerialSetBaudrate;
 		pDevItf->pfnGetTimeouts		= GfaSerialGetTimeouts;
 		pDevItf->pfnSetTimeouts		= GfaSerialSetTimeouts;

+ 1 - 0
libmininet/gfaserial.h

@@ -38,6 +38,7 @@ bool GfaSerialIsValidBaudrate(uint32_t nBaudrate);
 
 ssize_t GfaSerialGetConfig(HGFADEVICE hSer, LPGFA_SER_CFG_PARAMS pscp, size_t nSizeCfgParams);
 int GfaSerialSetConfig(HGFADEVICE hSer, LPCGFA_SER_CFG_PARAMS pscp, size_t nSizeCfgParams);
+int GfaSerialGetBaudrate(HGFADEVICE hSer, uint32_t *pnBaudrate);
 int GfaSerialSetBaudrate(HGFADEVICE hSer, uint32_t nBaudrate);
 
 bool GfaSerialGetTimeouts(HGFADEVICE hSer, struct timeval *ptvRX, struct timeval *ptvTX);