first submission
This commit is contained in:
@@ -0,0 +1,317 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : PING.c
|
||||
* Author : WCH
|
||||
* Version : V1.0.0
|
||||
* Date : 2022/06/11
|
||||
* Description : ping related functions.
|
||||
*********************************************************************************
|
||||
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
|
||||
* Attention: This software (modified or not) and binary are used for
|
||||
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
|
||||
*******************************************************************************/
|
||||
#include "PING.h"
|
||||
|
||||
u8 sendErrCnt;
|
||||
u8 unreachCnt;
|
||||
u8 timeoutCnt;
|
||||
u8 sucRecCnt;
|
||||
u8 sendBuf[100];
|
||||
u8 ICMPCnt = 0;
|
||||
u8 ICMPSeq = 0;
|
||||
u8 ICMPSuc = 0;
|
||||
u8 ICMPTmpVal = 0;
|
||||
u32 timeCnt;
|
||||
extern u8 SocketId;
|
||||
/*********************************************************************
|
||||
* @fn InitParameter
|
||||
*
|
||||
* @brief Initializes parameters.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void InitParameter(void)
|
||||
{
|
||||
unreachCnt = 0;
|
||||
timeoutCnt = 0;
|
||||
sucRecCnt = 0;
|
||||
ICMPSuc = ICMP_KEEP_NO;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn InitPING
|
||||
*
|
||||
* @brief Initializes PING.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void InitPING(void)
|
||||
{
|
||||
IcmpHeader head;
|
||||
u32 check_sum = 0;
|
||||
u8 i;
|
||||
|
||||
ICMPCnt++;
|
||||
ICMPSeq += 1;
|
||||
head.i_type = ICMP_HEAD_TYPE;
|
||||
head.i_code = ICMP_HEAD_CODE;
|
||||
head.i_id = ICMP_HEAD_ID;
|
||||
head.i_seq = ICMP_HEAD_SEQ + ICMPSeq;
|
||||
memset(head.i_data, 0, sizeof(head.i_data));
|
||||
for(i = 0; i < ICMP_DATA_BYTES; i++) {
|
||||
if(i < 26)
|
||||
head.i_data[i] = i + 'a';
|
||||
else
|
||||
head.i_data[i] = i + 'a' - 26;
|
||||
if(i % 2 == 0)
|
||||
check_sum += head.i_data[i] << 8;
|
||||
else
|
||||
check_sum += head.i_data[i];
|
||||
}
|
||||
check_sum += head.i_type << 8;
|
||||
check_sum += head.i_code;
|
||||
check_sum += head.i_id;
|
||||
check_sum += head.i_seq;
|
||||
head.i_cksum = check_sum >> 16;
|
||||
head.i_cksum += check_sum & 0xffff;
|
||||
head.i_cksum = 0xffff - head.i_cksum;
|
||||
memset(sendBuf, 0, sizeof(sendBuf));
|
||||
memcpy(sendBuf, &head, sizeof(head));
|
||||
sendBuf[2] = head.i_cksum >> 8;
|
||||
sendBuf[3] = head.i_cksum & 0xff;
|
||||
sendBuf[4] = head.i_id >> 8;
|
||||
sendBuf[5] = head.i_id & 0xff;
|
||||
sendBuf[6] = head.i_seq >> 8;
|
||||
sendBuf[7] = head.i_seq & 0xff;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn Respond_PING
|
||||
*
|
||||
* @brief Respond to PING request.
|
||||
*
|
||||
* @param pDat - ACK data.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void Respond_PING(u8 *pDat)
|
||||
{
|
||||
IcmpHeader head;
|
||||
u32 check_sum = 0;
|
||||
u8 i;
|
||||
|
||||
head.i_type = ICMP_HEAD_REPLY;
|
||||
head.i_code = pDat[1];
|
||||
head.i_id = (pDat[4] << 8) + pDat[5];
|
||||
head.i_seq = (pDat[6] << 8) + pDat[7];
|
||||
|
||||
check_sum += head.i_type << 8;
|
||||
check_sum += head.i_code;
|
||||
check_sum += head.i_id;
|
||||
check_sum += head.i_seq;
|
||||
for (i = 0; i < 32; i++) {
|
||||
head.i_data[i] = pDat[i + 8];
|
||||
if (i % 2 == 0)
|
||||
check_sum += head.i_data[i] << 8;
|
||||
else
|
||||
check_sum += head.i_data[i];
|
||||
}
|
||||
head.i_cksum = check_sum >> 16;
|
||||
head.i_cksum += check_sum & 0xffff;
|
||||
head.i_cksum = 0xffff - head.i_cksum;
|
||||
memset(sendBuf, 0, sizeof(sendBuf));
|
||||
memcpy(sendBuf, &head, sizeof(head));
|
||||
sendBuf[2] = head.i_cksum >> 8;
|
||||
sendBuf[3] = head.i_cksum & 0xff;
|
||||
sendBuf[4] = head.i_id >> 8;
|
||||
sendBuf[5] = head.i_id & 0xff;
|
||||
sendBuf[6] = head.i_seq >> 8;
|
||||
sendBuf[7] = head.i_seq & 0xff;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_ICMPRecvData
|
||||
*
|
||||
* @brief receive and parse data.
|
||||
*
|
||||
* @param len - data length.
|
||||
* pDat - data buff
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void WCHNET_ICMPRecvData(u32 len, u8 *pDat)
|
||||
{
|
||||
u16 tmp = 0;
|
||||
|
||||
ICMPTmpVal = ICMPSuc;
|
||||
ICMPSuc = 3;
|
||||
if (len == 40) {
|
||||
if (pDat[0] == ICMP_HEAD_REPLY) {
|
||||
if (pDat[1] == ICMP_HEAD_CODE) {
|
||||
tmp = pDat[4];
|
||||
tmp = tmp << 8;
|
||||
tmp += pDat[5];
|
||||
if (tmp == ICMP_HEAD_ID) {
|
||||
tmp = pDat[6];
|
||||
tmp = (tmp << 8);
|
||||
tmp += pDat[7] - ICMPSeq;
|
||||
if (tmp == ICMP_HEAD_SEQ) {
|
||||
ICMPSuc = ICMP_RECV_SUC;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pDat[0] == ICMP_HEAD_TYPE) {
|
||||
if (pDat[1] == ICMP_HEAD_CODE) {
|
||||
Respond_PING(pDat);
|
||||
ICMPSuc = ICMP_REPLY;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (pDat[0] == 3) {
|
||||
if (pDat[1] == 1) {
|
||||
ICMPSuc = ICMP_UNRECH;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_PINGSendData
|
||||
*
|
||||
* @brief send PING command.
|
||||
*
|
||||
* @param PSend - data buff.
|
||||
* Len - data length
|
||||
* id - socket id
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void WCHNET_PINGSendData( u8 *PSend, u32 Len,u8 id )
|
||||
{
|
||||
u32 length;
|
||||
u8 i,count=0;
|
||||
|
||||
length = Len;
|
||||
count = 0;
|
||||
|
||||
while(1){
|
||||
Len = length;
|
||||
i = WCHNET_SocketSend(id,PSend,&Len);
|
||||
mStopIfError(i);
|
||||
if(Len == 0){
|
||||
count++;
|
||||
if(count>2){
|
||||
return;
|
||||
}
|
||||
}
|
||||
length -= Len;
|
||||
PSend += Len; //offset buffer pointer
|
||||
if(length)continue; //If the data is not sent, continue to send
|
||||
break;
|
||||
}
|
||||
ICMPSuc++;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @fn WCHNET_PINGCmd
|
||||
*
|
||||
* @brief Query status and execute corresponding commands.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void WCHNET_PINGCmd(void)
|
||||
{
|
||||
if (ICMPSuc < ICMP_KEEP_NO) {
|
||||
switch (ICMPSuc) {
|
||||
case ICMP_SOKE_CON:
|
||||
ICMPSuc = 1;
|
||||
timeCnt = 0;
|
||||
WCHNET_PINGSendData(sendBuf, 40, SocketId);
|
||||
printf("Ping %d.%d.%d.%d with %d bytes of data.\r\n",
|
||||
(u16) DESIP[0], (u16) DESIP[1], (u16) DESIP[2],
|
||||
(u16) DESIP[3], (u16) ICMP_DATA_BYTES);
|
||||
break;
|
||||
case ICMP_SEND_ERR:
|
||||
if (sendErrCnt > 10) {
|
||||
ICMPSuc = ICMP_KEEP_NO;
|
||||
sendErrCnt = 0;
|
||||
}
|
||||
if (timeCnt > 250) {
|
||||
printf("send data fail!\n");
|
||||
timeCnt = 0;
|
||||
sendErrCnt++;
|
||||
WCHNET_PINGSendData(sendBuf, 40, SocketId);
|
||||
}
|
||||
break;
|
||||
case ICMP_SEND_SUC:
|
||||
if (timeCnt > 100) {
|
||||
printf("Request timeout.\n");
|
||||
timeoutCnt++;
|
||||
if (ICMPCnt < PING_SEND_CNT) {
|
||||
ICMPSuc = 1;
|
||||
InitPING();
|
||||
timeCnt = 0;
|
||||
WCHNET_PINGSendData(sendBuf, 40, SocketId);
|
||||
} else {
|
||||
printf("PING end!\r\n");
|
||||
printf("send = %d Received = %d", PING_SEND_CNT, sucRecCnt);
|
||||
ICMPSuc = ICMP_KEEP_NO;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ICMP_RECV_ERR: // error unknown
|
||||
printf("receive unknown data.\r\n");
|
||||
ICMPSuc = ICMP_KEEP_NO;
|
||||
break;
|
||||
case ICMP_RECV_SUC: // success
|
||||
printf("Reply from %d.%d.%d.%d: bytes=%d time<4ms\r\n",
|
||||
(u16) DESIP[0], (u16) DESIP[1], (u16) DESIP[2],
|
||||
(u16) DESIP[3], (u16) ICMP_DATA_BYTES);
|
||||
sucRecCnt++;
|
||||
if (ICMPCnt < PING_SEND_CNT) {
|
||||
ICMPSuc = 1;
|
||||
InitPING();
|
||||
timeCnt = 0;
|
||||
WCHNET_PINGSendData(sendBuf, 40, SocketId);
|
||||
} else {
|
||||
printf(
|
||||
"Ping statistics for %d.%d.%d.%d:\r\nPackets: Sent = %d,Received = %d,Lost = %d<%d%% loss>.\r\n",
|
||||
(u16) DESIP[0], (u16) DESIP[1], (u16) DESIP[2],
|
||||
(u16) DESIP[3], PING_SEND_CNT, (u16) sucRecCnt,
|
||||
(u16) (PING_SEND_CNT - sucRecCnt),
|
||||
(u16) ((PING_SEND_CNT - sucRecCnt) * 100 / PING_SEND_CNT));
|
||||
ICMPSuc = ICMP_KEEP_NO;
|
||||
}
|
||||
break;
|
||||
case ICMP_UNRECH: // unreachable
|
||||
printf("Reply from %d.%d.%d.%d: Destination host unreachable.\r\n",
|
||||
(u16) DESIP[0], (u16) DESIP[1], (u16) DESIP[2],
|
||||
(u16) DESIP[3]);
|
||||
unreachCnt++;
|
||||
if (ICMPCnt < PING_SEND_CNT) {
|
||||
ICMPSuc = 1;
|
||||
InitPING();
|
||||
timeCnt = 0;
|
||||
WCHNET_PINGSendData(sendBuf, 40, SocketId);
|
||||
} else {
|
||||
printf("PING end!\r\n");
|
||||
printf("send = %d Received = %d", PING_SEND_CNT, sucRecCnt);
|
||||
ICMPSuc = ICMP_KEEP_NO;
|
||||
}
|
||||
break;
|
||||
case ICMP_REPLY:
|
||||
WCHNET_PINGSendData(sendBuf, 40, SocketId);
|
||||
break;
|
||||
case ICMP_REPLY_SUC:
|
||||
printf("Reply ping.\r\n");
|
||||
ICMPSuc = ICMPTmpVal;
|
||||
break;
|
||||
case ICMP_KEEP_NO:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************** endfile **********************************/
|
||||
Reference in New Issue
Block a user