⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zl5011xpackettx.c

📁 Zalink50114----TDMoIP芯片驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:

 Function:
   zl5011xAddCDHeader

 Description:
   Modify the structure information passed in to setup header for
   Context Descriptor

 Inputs:
   layer2and3Header  Pointer to zl5011xLanTxSetLayer2and3HeaderS structure to
                     check CD position
   layer4and5Header  Pointer to zl5011xLanTxSetLayer4and5HeaderS structure to
                     check CD position
   par               Pointer to the zl5011xPacketTxSetHeaderS structure.

 Outputs:
   None

 Returns:
   zlStatusE

 Remarks:
   None

******************************************************************************/

zlStatusE zl5011xAddCDHeader(zl5011xLanTxSetLayer2and3HeaderS *layer2and3Header,
      zl5011xLanTxSetLayer4and5HeaderS *layer4and5Header, zl5011xPacketTxSetHeaderS *par,
      Uint8T *cdPos)
{
   zlStatusE status = ZL5011X_OK;
   zl5011xBooleanE noHighHeader = ZL5011X_FALSE;

   ZL5011X_TRACE(ZL5011X_PACKET_FN_ID,
         "zl5011xAddCDHeader:",
         0, 0, 0, 0, 0, 0);

   if (par->protocolType == ZL5011X_IP_UDP_CD)
   {
      /* if CD is being used on top of UDP, then it must immediately
         follow the UDP header */
      par->contextDescriptorOffset = layer4and5Header->header.txHighLength +
            layer2and3Header->header.txLowLength;
   }
   else
   {
      if (par->contextDescriptorOffset == (Uint32T)ZL5011X_INVALID)
      {
         par->contextDescriptorOffset = par->headerLength - ZL5011X_PKT_CD_HDR_LEN;
      }
   }

   if ((par->headerLength < (par->contextDescriptorOffset + ZL5011X_PKT_CD_HDR_LEN)) ||
         ((Uint8T)par->contextDescriptorOffset < (layer4and5Header->header.txHighLength + layer2and3Header->header.txLowLength)))
   {
      status = ZL5011X_PARAMETER_INVALID;
   }
   else
   {
      if (par->contextDescriptorTeardown == ZL5011X_TRUE)
      {
         /* setting the silence control to 0, will allow only one packet to be transmitted
            by the RTP block. After this packet, the RTP will discard all further packets */
         layer4and5Header->header.highSilenceCtrl = 0;
      }

      /* if there is no high header at the moment, then remember since that allows
         more tweaking of the low and high header lengths */
      if (layer4and5Header->header.txHighLength == 0)
      {
         noHighHeader = ZL5011X_TRUE;

         /* put the CD field at the start of the header in the RTP block */
         layer2and3Header->header.txLowLength = (Uint8T)par->contextDescriptorOffset;
         layer4and5Header->header.txHighLength = (Uint8T)(par->headerLength - par->contextDescriptorOffset);
      }
      else
      {
         /* leave the RTP header as it is, but change the length to
            account for the CD + padding */
         layer4and5Header->header.txHighLength = (Uint8T)(par->headerLength - layer2and3Header->header.txLowLength);
      }
   }

   if (status == ZL5011X_OK)
   {
      if (noHighHeader == ZL5011X_TRUE)
      {
         /* can only include an even number of bytes in the RTP block */
         if ((layer4and5Header->header.txHighLength % 2) == 1)
         {
            layer2and3Header->header.txLowLength--;
            layer4and5Header->header.txHighLength++;
         }
      }

      /* return the position of the CD header in the RTP header */
      *cdPos = (Uint8T)(par->contextDescriptorOffset - layer2and3Header->header.txLowLength);
   }

   return(status);
}

/******************************************************************************

 Function:
   zl5011xUpdateIPChecksum

 Description:
   In IPv4 mode, the checksum needs to be presented to the device, based on the
   length and the identification fields being zero for the partial checksum.
   This function re-calculates the checksum based on these fields being zero.

 Inputs:
    layer2and3Header  Pointer to the zl5011xLanTxSetLayer2and3HeaderS structure.
    par               Pointer to the zl5011xPacketTxSetHeaderS structure.

 Outputs:
    None

 Returns:
    zlStatusE

 Remarks:
   The PTX uses the length field from a seperate register in the control
   header. The value in the header itself is as set by the calling function
   - and as used for calculating the checksum. So, change this field to
   zero and re-calculate the checksum.

******************************************************************************/

zlStatusE zl5011xUpdateIPChecksum(zl5011xLanTxSetLayer2and3HeaderS *layer2and3Header,
      zl5011xLanTxSetLayer4and5HeaderS *layer4and5Header,
      zl5011xPacketTxSetHeaderS * par)
{
   zlStatusE status = ZL5011X_OK;
   Uint16T chkChange, tempPos, newLength = 0;

   ZL5011X_TRACE(ZL5011X_PACKET_FN_ID,
         "zl5011xUpdateIPChecksum:",
         0, 0, 0, 0, 0, 0);

   chkChange = 0;

   if (par->fixIpv4Header == ZL5011X_TRUE)
   {
      /* check that the payload length is non-zero, to be sure that a value
         has been set */
      if (par->payloadLength == 0)
      {
         status = ZL5011X_PARAMETER_INVALID;
      }
      else
      {
         newLength = layer2and3Header->header.layer3LengthValue +
               layer4and5Header->header.txHighLength + par->payloadLength;
      }
   }
   else
   {
      newLength = 0;
   }

   if (status == ZL5011X_OK)
   {
      /* change the length field to 0 */
      status = zl5011xPacketChangeField(layer2and3Header->header.txLowData,
            layer2and3Header->header.layer3LengthPos,
            newLength, 0xffff, &chkChange);
   }

   if (status == ZL5011X_OK)
   {
      if (par->fixIpv4Header != ZL5011X_TRUE)
      {
         /* change the identification field to 0 */
         tempPos = layer2and3Header->header.layer3LengthPos + (ZL5011X_PKT_IPV4_IDENT_POS - ZL5011X_PKT_IPV4_LEN_POS);
         layer2and3Header->header.txLowData[tempPos] = 0;
         layer2and3Header->header.txLowData[tempPos + 1] = 0;
      }

      /* change the checksum field to 0 */
      tempPos = layer2and3Header->header.layer3ChecksumPos;
      layer2and3Header->header.txLowData[tempPos] = 0;
      layer2and3Header->header.txLowData[tempPos + 1] = 0;

      /* calculate the checksum */
      status = zl5011xPacketCalculateChecksum(layer2and3Header->header.txLowData + tempPos - ZL5011X_PKT_IPV4_CHKSUM_POS,
            ZL5011X_PKT_IPV4_HDR_LEN, &chkChange);


      if (par->fixIpv4Header == ZL5011X_TRUE)
      {
         /* disable the IPv4 dynamic fields if the header is to be fixed */
         layer2and3Header->header.layer3LengthEnable = ZL5011X_FALSE;
         layer2and3Header->header.layer3ChecksumEnable = ZL5011X_FALSE;

         /* insert the checksum into the header, inverting as required for the partial checksum */
         layer2and3Header->header.txLowData[tempPos] = (chkChange >> 8) & 0xff;
         layer2and3Header->header.txLowData[tempPos + 1] = (chkChange >> 0) & 0xff;
      }
      else
      {
         /* insert the checksum into the header, inverting as required for the partial checksum */
         layer2and3Header->header.txLowData[tempPos] = (~chkChange >> 8) & 0xff;
         layer2and3Header->header.txLowData[tempPos + 1] = (~chkChange >> 0) & 0xff;
      }
   }

   return(status);
}

/******************************************************************************

 Function:
   zl5011xUpdateUDPChecksum

 Description:
   The UDP checksum needs to be presented to the device, based on the
   length and any subsequent header fields being zero for the partial checksum.
   This function, amends the checksum based on these fields being zero.

 Inputs:
   layer4and5Header  Pointer to the zl5011xLanTxSetLayer4and5HeaderS structure.
   layer2and3Header  Pointer to the zl5011xLanTxSetLayer2and3HeaderS structure.
   par               Pointer to the zl5011xPacketTxSetHeaderS structure.

 Outputs:
    None

 Returns:
    zlStatusE

 Remarks:
   None

******************************************************************************/

zlStatusE zl5011xUpdateUDPChecksum(zl5011xLanTxSetLayer4and5HeaderS *layer4and5Header,
      zl5011xLanTxSetLayer2and3HeaderS *layer2and3Header, zl5011xPacketTxSetHeaderS *par)
{
   zlStatusE status = ZL5011X_OK;
   Uint16T chkChange, temp, ipStart;
   Uint8T tempHeader[ZL5011X_PTX_LOW_HEADER_MAX_LEN + ZL5011X_RTP_HIGH_HEADER_MAX_LEN + 16];
   Uint16T newLength = layer4and5Header->header.txHighLength + par->payloadLength - 2;

   ZL5011X_TRACE(ZL5011X_PACKET_FN_ID,
         "zl5011xUpdateUDPChecksum:",
         0, 0, 0, 0, 0, 0);

   /* if the UDP checksum is required then need to take care of the dynamic fields */
   if (par->enableUDPChecksum == ZL5011X_TRUE)
   {
      if (layer4and5Header->header.layer4LengthEnable == ZL5011X_FALSE)
      {
         /* have a checksum but no length - this means that the UDP header has been shuffled!!
            need to set the correct value for UDP in the header since the dynamic field is
            not enabled. Also need to offset the checksum calculation, since the length the
            device will use is too low */

         layer4and5Header->header.txHighData[layer4and5Header->header.layer4LengthPos] = (Uint8T)(newLength >> 8);
         layer4and5Header->header.txHighData[layer4and5Header->header.layer4LengthPos + 1] = (Uint8T)newLength;
      }

      temp = layer4and5Header->header.txHighLength;

      memcpy(tempHeader, layer4and5Header->header.txHighData, temp);

      /* if the length is an odd number of bytes, then round up to the next 16 bit word */
      if ((temp & 1) != 0)
      {
         tempHeader[temp++] = 0;
      }

      if (layer4and5Header->header.layer4LengthEnable == ZL5011X_FALSE)
      {
         /* the last 2 bytes from the PTX have been shifted into the PE block.
            Need to remove them or they will affect the checksum calculation -
            overwrite them with the length, which is needed for the pseudo header */
         tempHeader[0] = (Uint8T)(newLength >> 8);
         tempHeader[1] = (Uint8T)newLength;
      }
      else
      {
         /* zero out the length field for the calculation */
         tempHeader[layer4and5Header->header.layer4LengthPos] = 0;
         tempHeader[layer4and5Header->header.layer4LengthPos + 1] = 0;
      }

      /* zero out the checksum field for the calculation */
      tempHeader[layer4and5Header->header.layer4ChecksumPos] = 0;
      tempHeader[layer4and5Header->header.layer4ChecksumPos + 1] = 0;

      /* zero out the sequence number field for the calculation */
      if (layer4and5Header->header.layer5SequenceNumEnable == ZL5011X_TRUE)
      {
         tempHeader[layer4and5Header->header.layer5SequenceNumPos] = 0;

         if (layer4and5Header->header.layer5SequenceNum16bit == ZL5011X_TRUE)
         {
            tempHeader[layer4and5Header->header.layer5SequenceNumPos + 1] = 0;
         }
      }

      /* zero out the timestamp field for the calculation */
      if (layer4and5Header->header.layer5TimestampEnable == ZL5011X_TRUE)
      {
         tempHeader[layer4and5Header->header.layer5TimestampPos] = 0;
         tempHeader[layer4and5Header->header.layer5TimestampPos + 1] = 0;

         if (layer4and5Header->header.layer5Timestamp32bit == ZL5011X_TRUE)
         {
            tempHeader[layer4and5Header->header.layer5TimestampPos + 2] = 0;
            tempHeader[layer4and5Header->header.layer5TimestampPos + 3] = 0;
         }
      }

      /* tack the pseudo header fields onto the end of the array */
      if (par->ipVer4 == ZL5011X_TRUE)
      {
         ipStart = layer2and3Header->header.layer3LengthPos - ZL5011X_PKT_IPV4_L

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -