1262 lines
29 KiB
C
1262 lines
29 KiB
C
|
/*
|
|||
|
* Copyright (c) 2022 OpenLuat & AirM2M
|
|||
|
*
|
|||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|||
|
* this software and associated documentation files (the "Software"), to deal in
|
|||
|
* the Software without restriction, including without limitation the rights to
|
|||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
|||
|
* subject to the following conditions:
|
|||
|
*
|
|||
|
* The above copyright notice and this permission notice shall be included in all
|
|||
|
* copies or substantial portions of the Software.
|
|||
|
*
|
|||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
*/
|
|||
|
|
|||
|
#include "bsp_common.h"
|
|||
|
|
|||
|
const uint8_t ByteToAsciiTable[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
|
|||
|
|
|||
|
void LoopBuffer_Init(Loop_Buffer *Buf, void *Src, uint32_t MaxLen, uint32_t DataSize)
|
|||
|
{
|
|||
|
uint8_t *Data = (uint8_t *)Src;
|
|||
|
Buf->Data = Data;
|
|||
|
Buf->Len = 0;
|
|||
|
Buf->MaxLength = MaxLen;
|
|||
|
Buf->Offset = 0;
|
|||
|
Buf->DataSize = DataSize;
|
|||
|
}
|
|||
|
|
|||
|
uint32_t LoopBuffer_Query(Loop_Buffer *Buf, void *Src, uint32_t Len)
|
|||
|
{
|
|||
|
uint32_t i, p;
|
|||
|
uint8_t *Data = (uint8_t *)Src;
|
|||
|
if (Buf->Len < Len)
|
|||
|
{
|
|||
|
Len = Buf->Len;
|
|||
|
}
|
|||
|
if (Buf->DataSize > 1)
|
|||
|
{
|
|||
|
for (i = 0, p = Buf->Offset; i < Len; i++, p++)
|
|||
|
{
|
|||
|
if (p >= Buf->MaxLength)
|
|||
|
{
|
|||
|
p -= Buf->MaxLength;
|
|||
|
}
|
|||
|
memcpy(Data + (i * Buf->DataSize), Buf->Data + (p * Buf->DataSize), Buf->DataSize);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
for (i = 0, p = Buf->Offset; i < Len; i++, p++)
|
|||
|
{
|
|||
|
if (p >= Buf->MaxLength)
|
|||
|
{
|
|||
|
p -= Buf->MaxLength;
|
|||
|
}
|
|||
|
Data[i] = Buf->Data[p];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return Len;
|
|||
|
}
|
|||
|
|
|||
|
uint32_t LoopBuffer_Read(Loop_Buffer *Buf, void *Src, uint32_t Len)
|
|||
|
{
|
|||
|
uint32_t l;
|
|||
|
uint8_t *Data = (uint8_t *)Src;
|
|||
|
l = LoopBuffer_Query(Buf, Data, Len);
|
|||
|
Buf->Len -= l;
|
|||
|
Buf->Offset += l;
|
|||
|
if (Buf->Offset >= Buf->MaxLength)
|
|||
|
{
|
|||
|
Buf->Offset -= Buf->MaxLength;
|
|||
|
|
|||
|
}
|
|||
|
if (!Buf->Len) {
|
|||
|
Buf->Offset = 0;
|
|||
|
}
|
|||
|
return l;
|
|||
|
}
|
|||
|
|
|||
|
void LoopBuffer_Del(Loop_Buffer *Buf, uint32_t Len)
|
|||
|
{
|
|||
|
if (Buf->Len < Len)
|
|||
|
{
|
|||
|
Len = Buf->Len;
|
|||
|
}
|
|||
|
|
|||
|
Buf->Len -= Len;
|
|||
|
Buf->Offset += Len;
|
|||
|
if (Buf->Offset >= Buf->MaxLength)
|
|||
|
{
|
|||
|
Buf->Offset -= Buf->MaxLength;
|
|||
|
}
|
|||
|
|
|||
|
if (!Buf->Len) {
|
|||
|
Buf->Offset = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
uint32_t LoopBuffer_Write(Loop_Buffer *Buf, void *Src, uint32_t Len)
|
|||
|
{
|
|||
|
uint32_t i, p, cut_off = 0;
|
|||
|
uint8_t *Data = (uint8_t *)Src;
|
|||
|
if (!Buf->Len && !Buf->Offset && (Len <= Buf->Len))
|
|||
|
{
|
|||
|
memcpy(Buf->Data, Data, Len);
|
|||
|
Buf->Len = Len;
|
|||
|
return Len;
|
|||
|
}
|
|||
|
cut_off = Buf->MaxLength - Buf->Len;
|
|||
|
if (cut_off >= Len)
|
|||
|
{
|
|||
|
cut_off = 0;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
cut_off = Len - cut_off;
|
|||
|
}
|
|||
|
|
|||
|
if (Buf->DataSize > 1)
|
|||
|
{
|
|||
|
for (i = 0, p = Buf->Offset + Buf->Len; i < Len; i++, p++)
|
|||
|
{
|
|||
|
if (p >= Buf->MaxLength)
|
|||
|
{
|
|||
|
p -= Buf->MaxLength;
|
|||
|
}
|
|||
|
memcpy(Buf->Data + (p * Buf->DataSize), Data + (i * Buf->DataSize), Buf->DataSize);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
for (i = 0, p = Buf->Offset + Buf->Len; i < Len; i++, p++)
|
|||
|
{
|
|||
|
if (p >= Buf->MaxLength)
|
|||
|
{
|
|||
|
p -= Buf->MaxLength;
|
|||
|
}
|
|||
|
|
|||
|
Buf->Data[p] = Data[i];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
Buf->Offset += cut_off;
|
|||
|
if (Buf->Offset >= Buf->MaxLength)
|
|||
|
Buf->Offset -= Buf->MaxLength;
|
|||
|
|
|||
|
Buf->Len += Len;
|
|||
|
if (Buf->Len > Buf->MaxLength)
|
|||
|
Buf->Len = Buf->MaxLength;
|
|||
|
|
|||
|
return Len;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void Buffer_StaticInit(Buffer_Struct *Buf, void *Src, uint32_t MaxLen)
|
|||
|
{
|
|||
|
Buf->Data = Src;
|
|||
|
Buf->Pos = 0;
|
|||
|
Buf->MaxLen = MaxLen;
|
|||
|
}
|
|||
|
|
|||
|
int32_t Buffer_StaticWrite(Buffer_Struct *Buf, void *Data, uint32_t Len)
|
|||
|
{
|
|||
|
if (!Len)
|
|||
|
{
|
|||
|
return -1;
|
|||
|
}
|
|||
|
if (!Buf)
|
|||
|
{
|
|||
|
return -1;
|
|||
|
}
|
|||
|
if ((Buf->Pos + Len) > Buf->MaxLen)
|
|||
|
{
|
|||
|
Len = Buf->MaxLen - Buf->Pos;
|
|||
|
}
|
|||
|
if (Len)
|
|||
|
{
|
|||
|
memcpy(&Buf->Data[Buf->Pos], Data, Len);
|
|||
|
}
|
|||
|
Buf->Pos += Len;
|
|||
|
return Len;
|
|||
|
}
|
|||
|
|
|||
|
//void Buffer_Remove(Buffer_Struct *Buf, uint32_t Len)
|
|||
|
//{
|
|||
|
// uint32_t RestLen;
|
|||
|
// uint32_t i;
|
|||
|
// if (!Buf)
|
|||
|
// return ;
|
|||
|
// if (!Buf->Data)
|
|||
|
// return ;
|
|||
|
// if (Len >= Buf->Pos)
|
|||
|
// {
|
|||
|
// Buf->Pos = 0;
|
|||
|
// return ;
|
|||
|
// }
|
|||
|
// RestLen = Buf->Pos - Len;
|
|||
|
// memmove(Buf->Data, Buf->Data + Len, RestLen);
|
|||
|
// Buf->Pos = RestLen;
|
|||
|
//}
|
|||
|
|
|||
|
|
|||
|
/*****************************************************************************
|
|||
|
* FUNCTION
|
|||
|
* command_parse_param()
|
|||
|
* DESCRIPTION
|
|||
|
* Parse AT command string to parameters
|
|||
|
* PARAMETERS
|
|||
|
* char* pStr
|
|||
|
* RETURNS
|
|||
|
* pCmdParam
|
|||
|
*****************************************************************************/
|
|||
|
uint32_t CmdParseParam(int8_t* pStr, CmdParam *CP, int8_t Cut)
|
|||
|
{
|
|||
|
uint32_t paramStrLen = strlen((char *)pStr);
|
|||
|
uint32_t paramIndex = 0;
|
|||
|
uint32_t paramCharIndex = 0;
|
|||
|
uint32_t index = 0;
|
|||
|
|
|||
|
while ((pStr[index] != '\r')
|
|||
|
&& (index < paramStrLen)
|
|||
|
&& (paramIndex < CP->param_max_num)) {
|
|||
|
if (pStr[index] == Cut) {
|
|||
|
/* Next param string */
|
|||
|
paramCharIndex = 0;
|
|||
|
paramIndex++;
|
|||
|
}
|
|||
|
else {
|
|||
|
if (pStr[index] != '"')
|
|||
|
{
|
|||
|
if (paramCharIndex >= CP->param_max_len)
|
|||
|
return (0);
|
|||
|
|
|||
|
/*Get each of command param char, the param char except char ' " '*/
|
|||
|
CP->param_str[paramIndex * CP->param_max_len + paramCharIndex] = pStr[index];
|
|||
|
paramCharIndex++;
|
|||
|
}
|
|||
|
}
|
|||
|
index++;
|
|||
|
}
|
|||
|
|
|||
|
CP->param_num = paramIndex + 1;
|
|||
|
|
|||
|
return (1);
|
|||
|
}
|
|||
|
|
|||
|
__attribute__((weak)) uint8_t OS_CheckInIrq(void)
|
|||
|
{
|
|||
|
return __get_IPSR();
|
|||
|
}
|
|||
|
|
|||
|
__attribute__((weak)) void OS_BufferRemove(Buffer_Struct *Buf, uint32_t Len)
|
|||
|
{
|
|||
|
uint32_t RestLen;
|
|||
|
uint32_t i;
|
|||
|
if (!Buf)
|
|||
|
return ;
|
|||
|
if (!Buf->Data)
|
|||
|
return ;
|
|||
|
if (Len >= Buf->Pos)
|
|||
|
{
|
|||
|
Buf->Pos = 0;
|
|||
|
return ;
|
|||
|
}
|
|||
|
RestLen = Buf->Pos - Len;
|
|||
|
memmove(Buf->Data, Buf->Data + Len, RestLen);
|
|||
|
Buf->Pos = RestLen;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
int32_t BSP_SetBit(uint8_t *Data, uint32_t Sn, uint8_t Value)
|
|||
|
{
|
|||
|
uint32_t Mask,Pos1,Pos2;
|
|||
|
|
|||
|
Pos1 = Sn/8;
|
|||
|
Pos2 = Sn%8;
|
|||
|
|
|||
|
Mask = ~(1 << Pos2);
|
|||
|
if (Value)
|
|||
|
{
|
|||
|
Value = (1 << Pos2);
|
|||
|
}
|
|||
|
Data[Pos1] = (Data[Pos1] & Mask) | Value;
|
|||
|
//DBG("%d %d %d %d", Sn, Pos1, Pos2, Value);
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
int32_t BSP_GetBit(uint8_t *Data, uint32_t Sn, uint8_t *Value)
|
|||
|
{
|
|||
|
uint32_t Mask,Pos1,Pos2;
|
|||
|
|
|||
|
Pos1 = Sn/8;
|
|||
|
Pos2 = Sn%8;
|
|||
|
Mask = (1 << Pos2);
|
|||
|
if (Data[Pos1] & Mask)
|
|||
|
{
|
|||
|
*Value = 1;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
*Value = 0;
|
|||
|
}
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
uint8_t BSP_TestBit(uint8_t *Data, uint32_t Sn)
|
|||
|
{
|
|||
|
uint32_t Mask,Pos1,Pos2;
|
|||
|
|
|||
|
Pos1 = Sn/8;
|
|||
|
Pos2 = Sn%8;
|
|||
|
Mask = (1 << Pos2);
|
|||
|
if (Data[Pos1] & Mask)
|
|||
|
{
|
|||
|
return 1;
|
|||
|
}
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
uint8_t XorCheck(void *Src, uint32_t Len, uint8_t CheckStart)
|
|||
|
{
|
|||
|
uint8_t Check = CheckStart;
|
|||
|
uint8_t *Data = (uint8_t *)Src;
|
|||
|
uint32_t i;
|
|||
|
for (i = 0; i < Len; i++)
|
|||
|
{
|
|||
|
Check ^= Data[i];
|
|||
|
}
|
|||
|
return Check;
|
|||
|
}
|
|||
|
|
|||
|
uint8_t SumCheck(uint8_t *Data, uint32_t Len)
|
|||
|
{
|
|||
|
uint8_t Check = 0;
|
|||
|
uint32_t i;
|
|||
|
for (i = 0; i < Len; i++)
|
|||
|
{
|
|||
|
Check += Data[i];
|
|||
|
}
|
|||
|
return Check;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
uint8_t CRC8Cal(void *Data, uint16_t Len, uint8_t CRC8Last, uint8_t CRCRoot, uint8_t IsReverse)
|
|||
|
{
|
|||
|
uint16_t i;
|
|||
|
uint8_t CRC8 = CRC8Last;
|
|||
|
uint8_t wTemp = CRCRoot;
|
|||
|
uint8_t *Src = (uint8_t *)Data;
|
|||
|
if (IsReverse)
|
|||
|
{
|
|||
|
CRCRoot = 0;
|
|||
|
for (i = 0; i < 8; i++)
|
|||
|
{
|
|||
|
if (wTemp & (1 << (7 - i)))
|
|||
|
{
|
|||
|
CRCRoot |= 1 << i;
|
|||
|
}
|
|||
|
}
|
|||
|
while (Len--)
|
|||
|
{
|
|||
|
|
|||
|
CRC8 ^= *Src++;
|
|||
|
for (i = 0; i < 8; i++)
|
|||
|
{
|
|||
|
if ((CRC8 & 0x01))
|
|||
|
{
|
|||
|
CRC8 >>= 1;
|
|||
|
CRC8 ^= CRCRoot;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
CRC8 >>= 1;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
while (Len--)
|
|||
|
{
|
|||
|
|
|||
|
CRC8 ^= *Src++;
|
|||
|
for (i = 8; i > 0; --i)
|
|||
|
{
|
|||
|
if ((CRC8 & 0x80))
|
|||
|
{
|
|||
|
CRC8 <<= 1;
|
|||
|
CRC8 ^= CRCRoot;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
CRC8 <<= 1;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return CRC8;
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************/
|
|||
|
/* CRC16 */
|
|||
|
/************************************************************************/
|
|||
|
uint16_t CRC16Cal(void *Data, uint16_t Len, uint16_t CRC16Last, uint16_t CRCRoot, uint8_t IsReverse)
|
|||
|
{
|
|||
|
uint16_t i;
|
|||
|
uint16_t CRC16 = CRC16Last;
|
|||
|
uint16_t wTemp = CRCRoot;
|
|||
|
uint8_t *Src = (uint8_t *)Data;
|
|||
|
if (IsReverse)
|
|||
|
{
|
|||
|
CRCRoot = 0;
|
|||
|
for (i = 0; i < 16; i++)
|
|||
|
{
|
|||
|
if (wTemp & (1 << (15 - i)))
|
|||
|
{
|
|||
|
CRCRoot |= 1 << i;
|
|||
|
}
|
|||
|
}
|
|||
|
while (Len--)
|
|||
|
{
|
|||
|
for (i = 0; i < 8; i++)
|
|||
|
{
|
|||
|
if ((CRC16 & 0x0001) != 0)
|
|||
|
{
|
|||
|
CRC16 >>= 1;
|
|||
|
CRC16 ^= CRCRoot;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
CRC16 >>= 1;
|
|||
|
}
|
|||
|
if ((*Src&(1 << i)) != 0)
|
|||
|
{
|
|||
|
CRC16 ^= CRCRoot;
|
|||
|
}
|
|||
|
}
|
|||
|
Src++;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
while (Len--)
|
|||
|
{
|
|||
|
for (i = 8; i > 0; i--)
|
|||
|
{
|
|||
|
if ((CRC16 & 0x8000) != 0)
|
|||
|
{
|
|||
|
CRC16 <<= 1;
|
|||
|
CRC16 ^= CRCRoot;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
CRC16 <<= 1;
|
|||
|
}
|
|||
|
if ((*Src&(1 << (i - 1))) != 0)
|
|||
|
{
|
|||
|
CRC16 ^= CRCRoot;
|
|||
|
}
|
|||
|
}
|
|||
|
Src++;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return CRC16;
|
|||
|
}
|
|||
|
|
|||
|
uint32_t AsciiToU32(uint8_t *Src, uint32_t Len)
|
|||
|
{
|
|||
|
uint32_t i = 0;
|
|||
|
uint32_t Temp = 0;
|
|||
|
for (i = 0; i < Len; i++)
|
|||
|
{
|
|||
|
|
|||
|
if (Src[i])
|
|||
|
{
|
|||
|
Temp *= 10;
|
|||
|
Temp += Src[i] - '0';
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
return Temp;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* @brief 反转数据
|
|||
|
* @param ref 需要反转的变量
|
|||
|
* @param ch 反转长度,多少位
|
|||
|
* @retval N反转后的数据
|
|||
|
*/
|
|||
|
static LongInt Reflect(LongInt ref, uint8_t ch)
|
|||
|
{
|
|||
|
LongInt value = 0;
|
|||
|
LongInt i;
|
|||
|
for (i = 1; i < (LongInt)(ch + 1); i++)
|
|||
|
{
|
|||
|
if (ref & 1)
|
|||
|
value |= (LongInt)1 << (ch - i);
|
|||
|
ref >>= 1;
|
|||
|
}
|
|||
|
return value;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* @brief 建立CRC32的查询表
|
|||
|
* @param Tab 表缓冲
|
|||
|
* @param Gen CRC32根
|
|||
|
* @retval None
|
|||
|
*/
|
|||
|
void CRC32_CreateTable(uint32_t *Tab, uint32_t Gen)
|
|||
|
{
|
|||
|
uint32_t crc;
|
|||
|
uint32_t i, j, temp, t1, t2, flag;
|
|||
|
if (Tab[1] != 0)
|
|||
|
return;
|
|||
|
for (i = 0; i < 256; i++)
|
|||
|
{
|
|||
|
temp = Reflect(i, 8);
|
|||
|
Tab[i] = temp << 24;
|
|||
|
for (j = 0; j < 8; j++)
|
|||
|
{
|
|||
|
flag = Tab[i] & 0x80000000;
|
|||
|
t1 = Tab[i] << 1;
|
|||
|
if (0 == flag)
|
|||
|
{
|
|||
|
t2 = 0;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
t2 = Gen;
|
|||
|
}
|
|||
|
Tab[i] = t1 ^ t2;
|
|||
|
}
|
|||
|
crc = Tab[i];
|
|||
|
Tab[i] = Reflect(crc, 32);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* @brief 计算buffer的crc校验码
|
|||
|
* @param CRC32_Table CRC32表
|
|||
|
* @param Buf 缓冲
|
|||
|
* @param Size 缓冲区长度
|
|||
|
* @param CRC32 初始CRC32值
|
|||
|
* @retval 计算后的CRC32
|
|||
|
*/
|
|||
|
uint32_t CRC32_Cal(uint32_t *CRC32_Table, uint8_t *Buf, uint32_t Size, uint32_t CRC32Last)
|
|||
|
{
|
|||
|
uint32_t i;
|
|||
|
for (i = 0; i < Size; i++)
|
|||
|
{
|
|||
|
CRC32Last = CRC32_Table[(CRC32Last ^ Buf[i]) & 0xff] ^ (CRC32Last >> 8);
|
|||
|
}
|
|||
|
return CRC32Last;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/************************************************************************/
|
|||
|
/*时间与时间戳转换,C语言实现 */
|
|||
|
/************************************************************************/
|
|||
|
/************************************************************************/
|
|||
|
uint8_t IsLeapYear(uint32_t Year)
|
|||
|
{
|
|||
|
if ((Year % 400) == 0)
|
|||
|
return 1;
|
|||
|
if ((((Year % 4) == 0) && (Year % 100) != 0))
|
|||
|
return 1;
|
|||
|
else
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
const uint32_t DayTable[2][12] = { { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }, { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 } };
|
|||
|
//const uint32_t DayTable[2][12] = { { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }, { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 } };
|
|||
|
LongInt UTC2Tamp(Date_UserDataStruct *Date, Time_UserDataStruct *Time)
|
|||
|
{
|
|||
|
|
|||
|
LongInt DYear, DDay, DSec;
|
|||
|
uint32_t Year100;
|
|||
|
DYear = Date->Year - 1970;
|
|||
|
if (DYear) //1970年以后,1972是第一个闰年,1973年是第一年需要增加一天,2100年是非闰年
|
|||
|
{
|
|||
|
DDay = DYear * 365 + ((DYear + 1) / 4) + DayTable[IsLeapYear(Date->Year)][Date->Mon - 1] + (Date->Day - 1);
|
|||
|
// if (IsLeapYear(Date->Year))
|
|||
|
// {
|
|||
|
// DDay--;
|
|||
|
// }
|
|||
|
if (Date->Year >= 2100)
|
|||
|
{
|
|||
|
Year100 = Date->Year - 2100;
|
|||
|
DDay -= (1 + Year100 / 100);
|
|||
|
if (Date->Year >= 2400)
|
|||
|
{
|
|||
|
Year100 = Date->Year - 2400;
|
|||
|
DDay += 1 + Year100 / 400;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
DDay = DayTable[IsLeapYear(Date->Year)][Date->Mon - 1] + (Date->Day - 1);
|
|||
|
}
|
|||
|
DSec = DDay * 86400 + Time->Hour * 3600 + Time->Min * 60 + Time->Sec;
|
|||
|
return DSec;
|
|||
|
}
|
|||
|
#define YEAR_1_DAY_BEFORE2000 365
|
|||
|
#define YEAR_2_DAY_BEFORE2000 730
|
|||
|
#define YEAR_3_DAY_BEFORE2000 1096
|
|||
|
|
|||
|
|
|||
|
#define YEAR_1_DAY_AFTER2000 365
|
|||
|
#define YEAR_2_DAY_AFTER2000 730
|
|||
|
#define YEAR_3_DAY_AFTER2000 1095
|
|||
|
|
|||
|
#define YEAR_4_DAY 1461
|
|||
|
#define YEAR_31_DAY 11323
|
|||
|
|
|||
|
#define YEAR_100_DAY 36524
|
|||
|
#define YEAR_400_DAY 146097
|
|||
|
|
|||
|
uint32_t Tamp2UTC(LongInt Sec, Date_UserDataStruct *Date, Time_UserDataStruct *Time, uint32_t LastDDay)
|
|||
|
{
|
|||
|
|
|||
|
uint32_t DYear,i, LeapFlag, Temp;
|
|||
|
uint32_t DDay;
|
|||
|
DDay = Sec / 86400;
|
|||
|
if (DDay != LastDDay)
|
|||
|
{
|
|||
|
DYear = 0;
|
|||
|
Time->Week = (4 + DDay) % 7;
|
|||
|
if (DDay >= YEAR_31_DAY)
|
|||
|
{
|
|||
|
DDay -= YEAR_31_DAY;
|
|||
|
DYear = 31;
|
|||
|
|
|||
|
if (DDay >= YEAR_400_DAY)
|
|||
|
{
|
|||
|
Temp = DDay / YEAR_400_DAY;
|
|||
|
DYear += Temp * 400;
|
|||
|
DDay -= Temp * YEAR_400_DAY;
|
|||
|
}
|
|||
|
|
|||
|
if (DDay >= YEAR_100_DAY)
|
|||
|
{
|
|||
|
Temp = DDay / YEAR_100_DAY;
|
|||
|
DYear += Temp * 100;
|
|||
|
DDay -= Temp * YEAR_100_DAY;
|
|||
|
}
|
|||
|
|
|||
|
if (DDay >= YEAR_4_DAY)
|
|||
|
{
|
|||
|
Temp = DDay / YEAR_4_DAY;
|
|||
|
DYear += Temp * 4;
|
|||
|
DDay -= Temp * YEAR_4_DAY;
|
|||
|
}
|
|||
|
|
|||
|
if (DDay >= YEAR_3_DAY_AFTER2000)
|
|||
|
{
|
|||
|
DYear += 3;
|
|||
|
DDay -= YEAR_3_DAY_AFTER2000;
|
|||
|
}
|
|||
|
else if (DDay >= YEAR_2_DAY_AFTER2000)
|
|||
|
{
|
|||
|
DYear += 2;
|
|||
|
DDay -= YEAR_2_DAY_AFTER2000;
|
|||
|
}
|
|||
|
else if (DDay >= YEAR_1_DAY_AFTER2000)
|
|||
|
{
|
|||
|
DYear += 1;
|
|||
|
DDay -= YEAR_1_DAY_AFTER2000;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (DDay >= YEAR_4_DAY)
|
|||
|
{
|
|||
|
Temp = DDay / YEAR_4_DAY;
|
|||
|
DYear += Temp * 4;
|
|||
|
DDay -= Temp * YEAR_4_DAY;
|
|||
|
}
|
|||
|
|
|||
|
if (DDay >= YEAR_3_DAY_BEFORE2000)
|
|||
|
{
|
|||
|
DYear += 3;
|
|||
|
DDay -= YEAR_3_DAY_BEFORE2000;
|
|||
|
}
|
|||
|
else if (DDay >= YEAR_2_DAY_BEFORE2000)
|
|||
|
{
|
|||
|
DYear += 2;
|
|||
|
DDay -= YEAR_2_DAY_BEFORE2000;
|
|||
|
}
|
|||
|
else if (DDay >= YEAR_1_DAY_BEFORE2000)
|
|||
|
{
|
|||
|
DYear += 1;
|
|||
|
DDay -= YEAR_1_DAY_BEFORE2000;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Date->Year = DYear + 1970;
|
|||
|
LeapFlag = IsLeapYear(Date->Year);
|
|||
|
Date->Mon = 12;
|
|||
|
for (i = 1; i < 12; i++)
|
|||
|
{
|
|||
|
if (DDay < DayTable[LeapFlag][i])
|
|||
|
{
|
|||
|
Date->Mon = i;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
Date->Day = DDay - DayTable[LeapFlag][Date->Mon - 1] + 1;
|
|||
|
}
|
|||
|
|
|||
|
Sec = Sec % 86400;
|
|||
|
Time->Hour = Sec / 3600;
|
|||
|
Sec = Sec % 3600;
|
|||
|
Time->Min = Sec / 60;
|
|||
|
Time->Sec = Sec % 60;
|
|||
|
return DDay;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/**
|
|||
|
* \brief get a byte (8bits) from a pointer
|
|||
|
*
|
|||
|
* Caller should ensure parameters are valid.
|
|||
|
*
|
|||
|
* \param ptr the pointer
|
|||
|
* \return the byte value
|
|||
|
*/
|
|||
|
uint8_t BytesGet8(const void *ptr)
|
|||
|
{
|
|||
|
const uint8_t *p = (const uint8_t *)ptr;
|
|||
|
return p[0];
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* \brief put a byte (8bits) to a pointer
|
|||
|
*
|
|||
|
* Caller should ensure parameters are valid.
|
|||
|
*
|
|||
|
* \param ptr the pointer
|
|||
|
* \param v the byte value
|
|||
|
*/
|
|||
|
void BytesPut8(void *ptr, uint8_t v)
|
|||
|
{
|
|||
|
uint8_t *p = (uint8_t *)ptr;
|
|||
|
p[0] = v;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* \brief get a big endian short (16bits) from a pointer
|
|||
|
*
|
|||
|
* Caller should ensure parameters are valid.
|
|||
|
*
|
|||
|
* \param ptr the pointer, may be unaligned
|
|||
|
* \return the short value
|
|||
|
*/
|
|||
|
uint16_t BytesGetBe16(const void *ptr)
|
|||
|
{
|
|||
|
const uint8_t *p = (const uint8_t *)ptr;
|
|||
|
return (p[0] << 8) | p[1];
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* \brief put a big endian short (16bits) to a pointer
|
|||
|
*
|
|||
|
* Caller should ensure parameters are valid.
|
|||
|
*
|
|||
|
* \param ptr the pointer, may be unaligned
|
|||
|
* \param v the short value
|
|||
|
*/
|
|||
|
void BytesPutBe16(void *ptr, uint16_t v)
|
|||
|
{
|
|||
|
uint8_t *p = (uint8_t *)ptr;
|
|||
|
p[0] = (v >> 8) & 0xff;
|
|||
|
p[1] = v & 0xff;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* \brief get a big endian word (32bits) from a pointer
|
|||
|
*
|
|||
|
* Caller should ensure parameters are valid.
|
|||
|
*
|
|||
|
* \param ptr the pointer, may be unaligned
|
|||
|
* \return the word value
|
|||
|
*/
|
|||
|
uint32_t BytesGetBe32(const void *ptr)
|
|||
|
{
|
|||
|
const uint8_t *p = (const uint8_t *)ptr;
|
|||
|
return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* \brief put a big endian word (32bits) to a pointer
|
|||
|
*
|
|||
|
* Caller should ensure parameters are valid.
|
|||
|
*
|
|||
|
* \param ptr the pointer, may be unaligned
|
|||
|
* \param v the word value
|
|||
|
*/
|
|||
|
void BytesPutBe32(void *ptr, uint32_t v)
|
|||
|
{
|
|||
|
uint8_t *p = (uint8_t *)ptr;
|
|||
|
p[0] = (v >> 24) & 0xff;
|
|||
|
p[1] = (v >> 16) & 0xff;
|
|||
|
p[2] = (v >> 8) & 0xff;
|
|||
|
p[3] = v & 0xff;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* \brief get a little endian short (16bits) from a pointer
|
|||
|
*
|
|||
|
* Caller should ensure parameters are valid.
|
|||
|
*
|
|||
|
* \param ptr the pointer, may be unaligned
|
|||
|
* \return the short value
|
|||
|
*/
|
|||
|
uint16_t BytesGetLe16(const void *ptr)
|
|||
|
{
|
|||
|
const uint8_t *p = (const uint8_t *)ptr;
|
|||
|
return p[0] | (p[1] << 8);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* \brief put a little endian short (16bits) to a pointer
|
|||
|
*
|
|||
|
* Caller should ensure parameters are valid.
|
|||
|
*
|
|||
|
* \param ptr the pointer, may be unaligned
|
|||
|
* \param v the short value
|
|||
|
*/
|
|||
|
void BytesPutLe16(void *ptr, uint16_t v)
|
|||
|
{
|
|||
|
uint8_t *p = (uint8_t *)ptr;
|
|||
|
p[0] = v & 0xff;
|
|||
|
p[1] = (v >> 8) & 0xff;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* \brief get a little endian word (32bits) from a pointer
|
|||
|
*
|
|||
|
* Caller should ensure parameters are valid.
|
|||
|
*
|
|||
|
* \param ptr the pointer, may be unaligned
|
|||
|
* \return the word value
|
|||
|
*/
|
|||
|
uint32_t BytesGetLe32(const void *ptr)
|
|||
|
{
|
|||
|
const uint8_t *p = (const uint8_t *)ptr;
|
|||
|
return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* \brief put a little endian word (32bits) to a pointer
|
|||
|
*
|
|||
|
* Caller should ensure parameters are valid.
|
|||
|
*
|
|||
|
* \param ptr the pointer, may be unaligned
|
|||
|
* \param v the word value
|
|||
|
*/
|
|||
|
void BytesPutLe32(void *ptr, uint32_t v)
|
|||
|
{
|
|||
|
uint8_t *p = (uint8_t *)ptr;
|
|||
|
p[0] = v & 0xff;
|
|||
|
p[1] = (v >> 8) & 0xff;
|
|||
|
p[2] = (v >> 16) & 0xff;
|
|||
|
p[3] = (v >> 24) & 0xff;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* \brief get a little endian long long (64bits) from a pointer
|
|||
|
*
|
|||
|
* Caller should ensure parameters are valid.
|
|||
|
*
|
|||
|
* \param ptr the pointer, may be unaligned
|
|||
|
* \return the long long value
|
|||
|
*/
|
|||
|
uint64_t BytesGetLe64(const void *ptr)
|
|||
|
{
|
|||
|
const uint8_t *p = (const uint8_t *)ptr;
|
|||
|
return BytesGetLe32(p) | ((uint64_t)BytesGetLe32(p + 4) << 32);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* \brief put a little endian long long (64bits) to a pointer
|
|||
|
*
|
|||
|
* Caller should ensure parameters are valid.
|
|||
|
*
|
|||
|
* \param ptr the pointer, may be unaligned
|
|||
|
* \param v the long long value
|
|||
|
*/
|
|||
|
void BytesPutLe64(void *ptr, uint64_t v)
|
|||
|
{
|
|||
|
uint8_t *p = (uint8_t *)ptr;
|
|||
|
BytesPutLe32(p, v & 0xffffffff);
|
|||
|
BytesPutLe32(p + 4, (v >> 32) & 0xffffffff);
|
|||
|
}
|
|||
|
|
|||
|
uint8_t BytesGet8FromBuf(Buffer_Struct *Buf)
|
|||
|
{
|
|||
|
Buf->Pos++;
|
|||
|
return Buf->Data[Buf->Pos - 1];
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void BytesPut8ToBuf(Buffer_Struct *Buf, uint8_t v)
|
|||
|
{
|
|||
|
Buf->Data[Buf->Pos] = v;
|
|||
|
Buf->Pos++;
|
|||
|
}
|
|||
|
|
|||
|
uint16_t BytesGetBe16FromBuf(Buffer_Struct *Buf)
|
|||
|
{
|
|||
|
Buf->Pos += 2;
|
|||
|
return (Buf->Data[Buf->Pos - 2] << 8) | Buf->Data[Buf->Pos - 1];
|
|||
|
}
|
|||
|
|
|||
|
void BytesPutBe16ToBuf(Buffer_Struct *Buf, uint16_t v)
|
|||
|
{
|
|||
|
Buf->Data[Buf->Pos] = (v >> 8) & 0xff;
|
|||
|
Buf->Data[Buf->Pos + 1] = v & 0xff;
|
|||
|
Buf->Pos += 2;
|
|||
|
}
|
|||
|
|
|||
|
uint32_t BytesGetBe32FromBuf(Buffer_Struct *Buf)
|
|||
|
{
|
|||
|
Buf->Pos += 4;
|
|||
|
return (Buf->Data[Buf->Pos - 4] << 24) | (Buf->Data[Buf->Pos - 3] << 16) | (Buf->Data[Buf->Pos - 2] << 8) | Buf->Data[Buf->Pos - 1];
|
|||
|
}
|
|||
|
|
|||
|
void BytesPutBe32ToBuf(Buffer_Struct *Buf, uint32_t v)
|
|||
|
{
|
|||
|
Buf->Data[Buf->Pos] = (v >> 24) & 0xff;
|
|||
|
Buf->Data[Buf->Pos + 1] = (v >> 16) & 0xff;
|
|||
|
Buf->Data[Buf->Pos + 2] = (v >> 8) & 0xff;
|
|||
|
Buf->Data[Buf->Pos + 3] = v & 0xff;
|
|||
|
Buf->Pos += 4;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
uint16_t BytesGetLe16FromBuf(Buffer_Struct *Buf)
|
|||
|
{
|
|||
|
Buf->Pos += 2;
|
|||
|
return Buf->Data[Buf->Pos - 2] | (Buf->Data[Buf->Pos - 1] << 8);
|
|||
|
}
|
|||
|
|
|||
|
void BytesPutLe16ToBuf(Buffer_Struct *Buf, uint16_t v)
|
|||
|
{
|
|||
|
Buf->Data[Buf->Pos] = v & 0xff;
|
|||
|
Buf->Data[Buf->Pos + 1] = (v >> 8) & 0xff;
|
|||
|
Buf->Pos+= 2;
|
|||
|
}
|
|||
|
|
|||
|
uint32_t BytesGetLe32FromBuf(Buffer_Struct *Buf)
|
|||
|
{
|
|||
|
Buf->Pos += 4;
|
|||
|
return Buf->Data[Buf->Pos - 4] | (Buf->Data[Buf->Pos - 3] << 8) | (Buf->Data[Buf->Pos - 2] << 16) | (Buf->Data[Buf->Pos - 1] << 24);
|
|||
|
}
|
|||
|
|
|||
|
void BytesPutLe32ToBuf(Buffer_Struct *Buf, uint32_t v)
|
|||
|
{
|
|||
|
Buf->Data[Buf->Pos] = v & 0xff;
|
|||
|
Buf->Data[Buf->Pos + 1] = (v >> 8) & 0xff;
|
|||
|
Buf->Data[Buf->Pos + 2] = (v >> 16) & 0xff;
|
|||
|
Buf->Data[Buf->Pos + 3] = (v >> 24) & 0xff;
|
|||
|
Buf->Pos += 4;
|
|||
|
}
|
|||
|
|
|||
|
uint64_t BytesGetLe64FromBuf(Buffer_Struct *Buf)
|
|||
|
{
|
|||
|
uint64_t Temp = BytesGetLe32FromBuf(Buf);
|
|||
|
return Temp | ((uint64_t)BytesGetLe32FromBuf(Buf) << 32);
|
|||
|
}
|
|||
|
|
|||
|
void BytesPutLe64ToBuf(Buffer_Struct *Buf, uint64_t v)
|
|||
|
{
|
|||
|
|
|||
|
BytesPutLe32ToBuf(Buf, v & 0xffffffff);
|
|||
|
BytesPutLe32ToBuf(Buf, (v >> 32) & 0xffffffff);
|
|||
|
}
|
|||
|
|
|||
|
float BytesGetFloatFromBuf(Buffer_Struct *Buf)
|
|||
|
{
|
|||
|
float Temp;
|
|||
|
Buf->Pos += 4;
|
|||
|
memcpy(&Temp, &Buf->Data[Buf->Pos - 4], 4);
|
|||
|
return Temp;
|
|||
|
}
|
|||
|
|
|||
|
void BytesPutFloatToBuf(Buffer_Struct *Buf, float v)
|
|||
|
{
|
|||
|
memcpy(&Buf->Data[Buf->Pos], &v, 4);
|
|||
|
Buf->Pos += 4;
|
|||
|
}
|
|||
|
|
|||
|
double BytesGetDoubleFromBuf(Buffer_Struct *Buf)
|
|||
|
{
|
|||
|
double Temp;
|
|||
|
Buf->Pos += 8;
|
|||
|
memcpy(&Temp, &Buf->Data[Buf->Pos - 8], 8);
|
|||
|
return Temp;
|
|||
|
}
|
|||
|
|
|||
|
void BytesPutDoubleToBuf(Buffer_Struct *Buf, double v)
|
|||
|
{
|
|||
|
memcpy(&Buf->Data[Buf->Pos], &v, 8);
|
|||
|
Buf->Pos += 8;
|
|||
|
}
|
|||
|
|
|||
|
void BytesGetMemoryFromBuf(Buffer_Struct *Buf, uint8_t *Data, uint32_t Len)
|
|||
|
{
|
|||
|
memcpy(Data, &Buf->Data[Buf->Pos], Len);
|
|||
|
Buf->Pos += Len;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* 转义打包
|
|||
|
* 标识Flag,即包头包尾加入Flag
|
|||
|
* 数据中遇到Flag -> Code F1
|
|||
|
* 数据中遇到Code -> Code F2
|
|||
|
*/
|
|||
|
|
|||
|
uint32_t TransferPack(uint8_t Flag, uint8_t Code, uint8_t F1, uint8_t F2, uint8_t *InBuf, uint32_t Len, uint8_t *OutBuf)
|
|||
|
{
|
|||
|
uint32_t TxLen = 0;
|
|||
|
uint32_t i;
|
|||
|
OutBuf[0] = Flag;
|
|||
|
TxLen = 1;
|
|||
|
for (i = 0; i < Len; i++)
|
|||
|
{
|
|||
|
if (InBuf[i] == Flag)
|
|||
|
{
|
|||
|
OutBuf[TxLen++] = Code;
|
|||
|
OutBuf[TxLen++] = F1;
|
|||
|
}
|
|||
|
else if (InBuf[i] == Code)
|
|||
|
{
|
|||
|
OutBuf[TxLen++] = Code;
|
|||
|
OutBuf[TxLen++] = F2;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
OutBuf[TxLen++] = InBuf[i];
|
|||
|
}
|
|||
|
}
|
|||
|
OutBuf[TxLen++] = Flag;
|
|||
|
return TxLen;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*
|
|||
|
* 转义解包
|
|||
|
* 标识Flag,即包头包尾加入Flag
|
|||
|
* 数据中遇到Code F1 -> Flag
|
|||
|
* 数据中遇到Code F2 -> Code
|
|||
|
* 数据中遇到Flag 出错返回0
|
|||
|
*/
|
|||
|
uint32_t TransferUnpack(uint8_t Flag, uint8_t Code, uint8_t F1, uint8_t F2, uint8_t *InBuf, uint32_t Len, uint8_t *OutBuf)
|
|||
|
{
|
|||
|
uint32_t RxLen = 0;
|
|||
|
uint32_t i = 0;
|
|||
|
while (i < Len)
|
|||
|
{
|
|||
|
if (InBuf[i] == Code)
|
|||
|
{
|
|||
|
if (InBuf[i+1] == F1)
|
|||
|
{
|
|||
|
OutBuf[RxLen++] = Flag;
|
|||
|
}
|
|||
|
else if (InBuf[i+1] == F2)
|
|||
|
{
|
|||
|
OutBuf[RxLen++] = Code;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return 0;
|
|||
|
}
|
|||
|
i += 2;
|
|||
|
}
|
|||
|
else if (InBuf[i] == Flag)
|
|||
|
{
|
|||
|
return 0;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
OutBuf[RxLen++] = InBuf[i++];
|
|||
|
}
|
|||
|
}
|
|||
|
return RxLen;
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Insert a new entry between two known consecutive entries.
|
|||
|
*
|
|||
|
* This is only for internal llist manipulation where we know
|
|||
|
* the prev/next entries already!
|
|||
|
*/
|
|||
|
void __llist_add(llist_head *p,
|
|||
|
llist_head *prev,
|
|||
|
llist_head *next)
|
|||
|
{
|
|||
|
next->prev = p;
|
|||
|
p->next = next;
|
|||
|
p->prev = prev;
|
|||
|
prev->next = p;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* llist_add - add a new entry
|
|||
|
* @new: new entry to be added
|
|||
|
* @head: llist head to add it after
|
|||
|
*
|
|||
|
* Insert a new entry after the specified head.
|
|||
|
* This is good for implementing stacks.
|
|||
|
*/
|
|||
|
void llist_add(llist_head *p, llist_head *head)
|
|||
|
{
|
|||
|
__llist_add(p, head, head->next);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* llist_add_tail - add a new entry
|
|||
|
* @new: new entry to be added
|
|||
|
* @head: llist head to add it before
|
|||
|
*
|
|||
|
* Insert a new entry before the specified head.
|
|||
|
* This is useful for implementing queues.
|
|||
|
*/
|
|||
|
void llist_add_tail(llist_head *p, llist_head *head)
|
|||
|
{
|
|||
|
__llist_add(p, head->prev, head);
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
* Delete a llist entry by making the prev/next entries
|
|||
|
* point to each other.
|
|||
|
*
|
|||
|
* This is only for internal llist manipulation where we know
|
|||
|
* the prev/next entries already!
|
|||
|
*/
|
|||
|
void __llist_del(llist_head * prev, llist_head * next)
|
|||
|
{
|
|||
|
next->prev = prev;
|
|||
|
prev->next = next;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* llist_del - deletes entry from llist.
|
|||
|
* @entry: the element to delete from the llist.
|
|||
|
* Note: llist_empty on entry does not return true after this, the entry is
|
|||
|
* in an undefined state.
|
|||
|
*/
|
|||
|
void llist_del(llist_head *entry)
|
|||
|
{
|
|||
|
if (entry->prev && entry->next)
|
|||
|
{
|
|||
|
__llist_del(entry->prev, entry->next);
|
|||
|
}
|
|||
|
entry->next = LLIST_POISON1;
|
|||
|
entry->prev = LLIST_POISON2;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* llist_del_init - deletes entry from llist and reinitialize it.
|
|||
|
* @entry: the element to delete from the llist.
|
|||
|
*/
|
|||
|
void llist_del_init(llist_head *entry)
|
|||
|
{
|
|||
|
__llist_del(entry->prev, entry->next);
|
|||
|
INIT_LLIST_HEAD(entry);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* llist_move - delete from one llist and add as another's head
|
|||
|
* @llist: the entry to move
|
|||
|
* @head: the head that will precede our entry
|
|||
|
*/
|
|||
|
void llist_move(llist_head *llist, llist_head *head)
|
|||
|
{
|
|||
|
__llist_del(llist->prev, llist->next);
|
|||
|
llist_add(llist, head);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* llist_move_tail - delete from one llist and add as another's tail
|
|||
|
* @llist: the entry to move
|
|||
|
* @head: the head that will follow our entry
|
|||
|
*/
|
|||
|
void llist_move_tail(llist_head *llist,
|
|||
|
llist_head *head)
|
|||
|
{
|
|||
|
__llist_del(llist->prev, llist->next);
|
|||
|
llist_add_tail(llist, head);
|
|||
|
}
|
|||
|
|
|||
|
void *llist_traversal(llist_head *head, CBFuncEx_t cb, void *pData)
|
|||
|
{
|
|||
|
llist_head *node = head->next;
|
|||
|
llist_head *del;
|
|||
|
int32_t result;
|
|||
|
while (!llist_empty(head) && (node != head))
|
|||
|
{
|
|||
|
result = cb((void *)node, pData);
|
|||
|
if (result > 0)
|
|||
|
{
|
|||
|
return node;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
del = node;
|
|||
|
node = node->next;
|
|||
|
if (result < 0)
|
|||
|
{
|
|||
|
llist_del(del);
|
|||
|
cb((void *)del, NULL);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* llist_empty - tests whether a llist is empty
|
|||
|
* @head: the llist to test.
|
|||
|
*/
|
|||
|
int llist_empty(const llist_head *head)
|
|||
|
{
|
|||
|
return head->next == head;
|
|||
|
}
|
|||
|
|
|||
|
uint32_t llist_num(const llist_head *head)
|
|||
|
{
|
|||
|
llist_head *node = head->next;
|
|||
|
uint32_t num = 0;
|
|||
|
if (!node)
|
|||
|
return num;
|
|||
|
while(node != head)
|
|||
|
{
|
|||
|
num++;
|
|||
|
node = node->next;
|
|||
|
}
|
|||
|
return num;
|
|||
|
}
|