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

📄 kitleth.c

📁 三星2410的BSP开发包
💻 C
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name:   kitleth.c

Abstract:  
    This module contains the KITL Ethernet transport exported functions
Functions:


Notes: 

--*/

#include <windows.h>
#include <Kitl.h>
#include <halether.h>
#include "kitlethp.h"

static EDBG_ADDR DevAddr;

// initialize host address to be a limit-broadcast to Service port
static EDBG_ADDR HostAddr = { 0xffffffff, 0xffff, 0xffff, 0xffff, htons(EDBG_SVC_PORT) };

static UINT16 CRC (UINT16 *pwRegion1, UINT16 wLength1, UINT16 *pwRegion2, UINT16 wLength2);

BOOL KitlEtherInit (EDBG_ADDR *pAddr, DWORD dwDHCPLeaseTime)
{
    // validate the parameters
    if (!pAddr || !pAddr->dwIP || !pAddr->wPort)
        return FALSE;
    
    // keep a local copy of the addresses
    memcpy (&DevAddr, pAddr, sizeof (EDBG_ADDR));

    KITLOutputDebugString ("Calling EdbgInitDHCP\r\n");

    // initialized DHCP renew process
    return EdbgInitDHCP (pAddr, dwDHCPLeaseTime);
}

BOOL EncodeUDP (LPBYTE pbFrame, USHORT cbData, EDBG_ADDR *pSrcAddr, EDBG_ADDR *pDestAddr)
{
    EthernetFrameHeader *pFrameHeader;
    IPHeaderFormat *pIPHeader;
    UDPPseudoHeaderFormat UDPPseudoHeader;
    UDPHeaderFormat *pUDPHeader;
    LPBYTE pData = pbFrame + UDP_DATA_FRAME_OFFSET;
    static UINT16 wIndentification = 0;

    // the frame buffer MUST be WORD aligned
    if (!pbFrame || !cbData || ((DWORD) pbFrame & 3)) {
        EdbgOutputDebugString ("!EncodeUDP: frame buffer must be DWORD aligned\r\n");
        return FALSE;
    }

    // Fill in destination and source MAC addresses and the IP frame type
    pFrameHeader = (EthernetFrameHeader *) pbFrame;
    pFrameHeader->wDestMAC[0] = pDestAddr->wMAC[0];
    pFrameHeader->wDestMAC[1] = pDestAddr->wMAC[1];
    pFrameHeader->wDestMAC[2] = pDestAddr->wMAC[2];
    pFrameHeader->wSrcMAC[0] = pSrcAddr->wMAC[0];
    pFrameHeader->wSrcMAC[1] = pSrcAddr->wMAC[1];
    pFrameHeader->wSrcMAC[2] = pSrcAddr->wMAC[2];
    pFrameHeader->wFrameType = htons(IP_FRAME);

    // The field information comes from page 34 of TCP/IP Illustrated by W. Richard Stevens
    pIPHeader = (IPHeaderFormat *) (pbFrame + sizeof(EthernetFrameHeader));
    pIPHeader->bVersionLength = 0x45;   // IP Version 4, No option IP header (5 32 bit words)
    pIPHeader->bTypeOfService = 0;      // No special transport options
                                        // Total length of the IP datagram
    pIPHeader->cwTotalLength = htons(sizeof(IPHeaderFormat) + sizeof(UDPHeaderFormat) + cbData);
                                        // Unique packet identification
    pIPHeader->wIdentification = wIndentification++;
    pIPHeader->wFragment = 0;           // No fragmentation
    pIPHeader->bTimeToLive = 64;        // We can go through 64 routers
    pIPHeader->bProtocol = UDP_PROTOCOL;// Specify the UDP protocol
    pIPHeader->wCRC = 0;                // Set the CRC to 0 while it is being computed
    pIPHeader->dwSrcIP = pSrcAddr->dwIP;
    pIPHeader->dwDestIP = pDestAddr->dwIP;

    // Compute the CRC and we're done with the IP header
    pIPHeader->wCRC = CRC ((UINT16 *)pIPHeader, sizeof(IPHeaderFormat), NULL, 0);

    // The field information comes from page 145 of TCP/IP Illustrated by W. Richard Stevens
    // Construct the UDP pseudo header
    UDPPseudoHeader.dwSrcIP = pSrcAddr->dwIP;
    UDPPseudoHeader.dwDestIP = pDestAddr->dwIP;
    UDPPseudoHeader.bZero = 0;
    UDPPseudoHeader.bProtocol = UDP_PROTOCOL; // This is the code for the UDP protocol
    UDPPseudoHeader.cwTotalUDPLength = htons(sizeof(UDPHeaderFormat) + cbData);

    // Construct the real UDP header
    pUDPHeader = (UDPHeaderFormat *)((BYTE *)pIPHeader + sizeof(IPHeaderFormat));
    pUDPHeader->wSrcPort =  pSrcAddr->wPort;
    pUDPHeader->wDestPort = pDestAddr->wPort;
                                            // The total length of the UDP datagram
    pUDPHeader->cwTotalUDPLength = UDPPseudoHeader.cwTotalUDPLength;
    pUDPHeader->wCRC = 0;                   // Set the CRC to 0 while it is being computed

    // Compute the CRC for the UDP datagram.  The pad 0 will automatically be added if there are an odd number of bytes
    pUDPHeader->wCRC = CRC ((UINT16 *)(&UDPPseudoHeader), sizeof(UDPPseudoHeader), (UINT16 *)pUDPHeader, ntohs(pUDPHeader->cwTotalUDPLength));
    if (pUDPHeader->wCRC == 0)
        pUDPHeader->wCRC = ~(pUDPHeader->wCRC);

    return TRUE;
}

BOOL KitlEtherEncodeUDP (LPBYTE pbFrame, USHORT cbData)
{
    return EncodeUDP (pbFrame, cbData, &DevAddr, &HostAddr);
}

LPBYTE KitlEtherDecodeUDP (LPBYTE pbFrame, PUSHORT pcbData)
{
    EthernetFrameHeader *pFrameHeader = (EthernetFrameHeader *) pbFrame;
    IPHeaderFormat *pIPHeader;
    UDPPseudoHeaderFormat UDPPseudoHeader;
    UDPHeaderFormat *pUDPHeader;

    // the frame buffer MUST be WORD aligned
    if (!pbFrame || !*pcbData || ((DWORD) pbFrame & 1)) {
        return NULL;
    }

    switch (ntohs(pFrameHeader->wFrameType)) {
    case ARP_FRAME:
        HandleARPPacket (&DevAddr, (LPBYTE) pbFrame);
        return NULL;        // ARP packet, KITL don't want any part of it

    case IP_FRAME:
        break;
        
    default:
        return NULL;        // not ARP, not IP, forget about it
    }

    pIPHeader = (IPHeaderFormat *) (pbFrame + sizeof(EthernetFrameHeader));

    // Make sure that it was for our IP address
    if (pIPHeader->dwDestIP != DevAddr.dwIP) {
        return NULL;        // the frame not for us
    }

    // Make sure that it is a UDP packet
    if (pIPHeader->bProtocol != UDP_PROTOCOL) {
        KITLOutputDebugString("!CheckUDP: Not UDP (proto = 0x%X)\n",pIPHeader->bProtocol);
        return NULL;
    }

    // Check the IP header checksum
    if (CRC ((UINT16 *) pIPHeader, sizeof(IPHeaderFormat), NULL, 0) != 0) {
        KITLOutputDebugString("!CheckUDP: IP header checksum failure\n");
        return NULL;
    }

    // Build the UDP Pseudo Header
    UDPPseudoHeader.dwSrcIP = pIPHeader->dwSrcIP;
    UDPPseudoHeader.dwDestIP = pIPHeader->dwDestIP;
    UDPPseudoHeader.bZero = 0;
    UDPPseudoHeader.bProtocol = UDP_PROTOCOL;         // This is the code for the UDP protocol
    UDPPseudoHeader.cwTotalUDPLength = htons(ntohs(pIPHeader->cwTotalLength) - sizeof(IPHeaderFormat));

    // Check the UDP checksum, I'm using the cwTotalUDPLength calculated from the IP header info because
    //  we know that it's not corrupted and won't give an outrageous length for the packet
    pUDPHeader = (UDPHeaderFormat *) ((BYTE *)pIPHeader + sizeof(IPHeaderFormat));
    if (CRC ((UINT16 *)(&UDPPseudoHeader), sizeof(UDPPseudoHeader), (UINT16 *)pUDPHeader, ntohs(UDPPseudoHeader.cwTotalUDPLength)) != 0) {
        KITLOutputDebugString("!CheckUDP: UDP header checksum failure\n");
        return NULL;
    }

    // update host address if it's sending to our service port
    if (htons (EDBG_SVC_PORT) == pUDPHeader->wDestPort) {
        // update host address
        if (HostAddr.dwIP == 0xffffffff) {
            EdbgOutputDebugString ("Host connected\r\n");
            HostAddr.wMAC[0] = pFrameHeader->wSrcMAC[0];
            HostAddr.wMAC[1] = pFrameHeader->wSrcMAC[1];
            HostAddr.wMAC[2] = pFrameHeader->wSrcMAC[2];
            HostAddr.dwIP = pIPHeader->dwSrcIP;
            HostAddr.wPort = pUDPHeader->wSrcPort;
            EdbgOutputDebugString ("Host IP: %s, port %d\r\n", inet_ntoa (HostAddr.dwIP), htons (HostAddr.wPort));
        }
    }

    // check if it's DHCP packet
    if (HandleDHCPPacket (&DevAddr, pUDPHeader)) {
        return NULL;        // DHCP messages, KITL don't want any part of it
    }

    // update get the data and lenght
    *pcbData = htons (pUDPHeader->cwTotalUDPLength) - sizeof(UDPHeaderFormat);
    return (LPBYTE) pUDPHeader + sizeof(UDPHeaderFormat);
}

UCHAR KitlEtherGetFrameHdrSize (void)
{
    return UDP_DATA_FRAME_OFFSET;
}

// This routine will calculation the complemented 16-bit 1's complement sum required to compute
//  network CRCs.  The CRC can be calculated over two different memory regions.  If only one
//  region is desired, then the other's length can be set to 0.  Also, if an odd number of bytes
//  are specified, the routine will add a 0 to the end of the data before doing the CRC and will
//  include that 0 in the calculation.
static UINT16 CRC (UINT16 *pwRegion1, UINT16 wLength1, UINT16 *pwRegion2, UINT16 wLength2)
{

    DWORD dwSum, dwCarryOut;
    UINT16 wCRC;
    UINT16 i;

    // There is no need to swap for network ordering during calculation because of the end around
    //  carry used in 1's complement addition
    dwSum = 0;
    if (wLength1 & 1) {
        *((BYTE *)pwRegion1 + wLength1) = 0;
        wLength1++;
    }
    wLength1 >>= 1;
    for (i = 0; i < wLength1; i++)
        dwSum += *pwRegion1++;

    if (wLength2 & 1) {
        *((BYTE *)pwRegion2 + wLength2) = 0;
        wLength2++;
    }
    wLength2 >>= 1;
    for (i = 0; i < wLength2; i++)
        dwSum += *pwRegion2++;

    // Now, we have to add back in all the carry out's from the lower 16 bits
    //  because this is 1's complement
    while (dwSum & 0xFFFF0000UL) {
        dwCarryOut = dwSum >> 16;
        dwSum &= 0x0000FFFFUL;
        dwSum += dwCarryOut;
    }

    wCRC = (UINT16)dwSum;

    // There is no need to flip for network byte order because we did all the sums backwards
    //  already.
    wCRC = ~wCRC;

    return wCRC;

}


BOOL EdbgSendUDP(
                 BYTE *pFrameBuffer,    // @parm [IN] - Formatting buffer (must be at least 42 + cwLength bytes)
                 EDBG_ADDR *pDestAddr,  // @parm [IN] - Address of destination
                 USHORT wSrcPort,       // @parm [IN] - Source UDP port number
                 BYTE *pData,           // @parm [IN] - User data buffer
                 UINT16 cwLength )      // @parm [IN] - # of bytes of data in user buffer
{
    EDBG_ADDR srcAddr;

    // construct source address
    memcpy (&srcAddr, &DevAddr, sizeof (EDBG_ADDR));
    srcAddr.wPort = htons (wSrcPort);

    // Copy user data if necessary
    if ((pData - pFrameBuffer) != UDP_DATA_FRAME_OFFSET)
        memcpy (pFrameBuffer + UDP_DATA_FRAME_OFFSET, pData, cwLength);

    // UDP encoding
    if (!EncodeUDP (pFrameBuffer, cwLength, &srcAddr, pDestAddr)) {
        return FALSE;
    }

    return KitlSendRawData (pFrameBuffer, (USHORT) (cwLength + UDP_DATA_FRAME_OFFSET));
}

BOOL KitlEthGetInfo (DWORD dwCode, LPVOID lpData, LPDWORD pcbData)
{
    if (!lpData || !pcbData || ((DWORD)lpData & 3) || (sizeof(DWORD) != *pcbData)) {
        return FALSE;
    }
    switch (dwCode) {
    case KGI_HOSTADDR:
        *(LPDWORD)lpData = HostAddr.dwIP;
        break;

    case KGI_DEVADDR:
        *(LPDWORD)lpData = DevAddr.dwIP;
        break;

    case KGI_BAUDRATE:
        *(LPDWORD)lpData = 10*1024*1024;    // 10MB per second
        break;

    case KGI_PORT:
        *(LPDWORD)lpData = htons (HostAddr.wPort);
        break;

    default:
        return FALSE;
    }
    return TRUE;
}

⌨️ 快捷键说明

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