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

📄 rndis.c

📁 基于TI DSP/BIOS的usb网卡的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
#undef  RNDIS_PM
#undef  RNDIS_WAKEUP
#undef  VERBOSE

#include "rndis.h"
#include "errno.h"
#include "stdio.h"

#include <assert.h>

//static int rndis_debug = 0;

#define RNDIS_MAX_CONFIGS    1

static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS];
static const le32 rndis_driver_version = constant_cpu_to_le32 ( 1 );
static rndis_resp_t * rndis_add_response ( int configNr, u32 length );

/* supported OIDs */
static const u32 oid_supported_list [] = 
{
    /* the general stuff */
    OID_GEN_SUPPORTED_LIST,
    OID_GEN_HARDWARE_STATUS,
    OID_GEN_MEDIA_SUPPORTED,
    OID_GEN_MEDIA_IN_USE,
    OID_GEN_MAXIMUM_FRAME_SIZE,
    OID_GEN_LINK_SPEED,
    OID_GEN_TRANSMIT_BLOCK_SIZE,
    OID_GEN_RECEIVE_BLOCK_SIZE,
    OID_GEN_VENDOR_ID,
    OID_GEN_VENDOR_DESCRIPTION,
    OID_GEN_VENDOR_DRIVER_VERSION,
    OID_GEN_CURRENT_PACKET_FILTER,
    OID_GEN_MAXIMUM_TOTAL_SIZE,
    OID_GEN_MEDIA_CONNECT_STATUS,
    OID_GEN_PHYSICAL_MEDIUM,

    /* the statistical stuff */
    OID_GEN_XMIT_OK,
    OID_GEN_RCV_OK,
    OID_GEN_XMIT_ERROR,
    OID_GEN_RCV_ERROR,
    OID_GEN_RCV_NO_BUFFER,

    /* mandatory 802.3 */
    /* the general stuff */
    OID_802_3_PERMANENT_ADDRESS,
    OID_802_3_CURRENT_ADDRESS,
    OID_802_3_MULTICAST_LIST,
    OID_802_3_MAC_OPTIONS,
    OID_802_3_MAXIMUM_LIST_SIZE,

    /* the statistical stuff */
    OID_802_3_RCV_ERROR_ALIGNMENT,
    OID_802_3_XMIT_ONE_COLLISION,
    OID_802_3_XMIT_MORE_COLLISIONS,

    #ifdef  RNDIS_PM
    /* PM and wakeup are mandatory for USB: */

    /* power management */
    OID_PNP_CAPABILITIES,
    OID_PNP_QUERY_POWER,
    OID_PNP_SET_POWER,

    #ifdef  RNDIS_WAKEUP
    /* wake up host */
    OID_PNP_ENABLE_WAKE_UP,
    OID_PNP_ADD_WAKE_UP_PATTERN,
    OID_PNP_REMOVE_WAKE_UP_PATTERN,
    #endif  /* RNDIS_WAKEUP */
    #endif  /* RNDIS_PM */
};

static u32 get_unaligned( void * data )
{
    le32 val;
    u8 * buf = data;

    val = * buf + 
        ((* ( buf + 1 )) << 8 ) + 
        ((* ( buf + 2 )) << 16 ) + 
        ((* ( buf + 3 )) << 24 );

    return le32_to_cpu( val );
}

/* NDIS Functions */
static int  gen_ndis_query_resp ( int configNr, u32 OID, u8 * buf, 
    unsigned buf_len, rndis_resp_t * r )
{
    int         retval = - ERR_NOMEM;
    u32         length = 4; /* usually */
    le32        * outbuf;
    int         i, count;
    rndis_query_cmplt_type  * resp;

    if (! r ) return - ERR_NOMEM;
    resp = ( rndis_query_cmplt_type *) r->buf;

    if (! resp ) return - ERR_NOMEM;

    /*    if ( buf_len && rndis_debug > 1 ) 
    {
        printf( "query OID %08x value, len %d:\n", OID, buf_len );
        for ( i = 0; i < buf_len; i += 16 ) 
        {
            printf( "%03d: %08x %08x %08x %08x\n", i,
                le32_to_cpu( get_unaligned(( le32 *)& buf[i] )),
                le32_to_cpu( get_unaligned(( le32 *)& buf[i + 4] )),
                le32_to_cpu( get_unaligned(( le32 *)& buf[i + 8] )),
                le32_to_cpu( get_unaligned(( le32 *)& buf[i + 12] )));
        }
    }*/

    /* response goes here, right after the header */
    outbuf = ( le32 *) & resp[1];
    resp->InformationBufferOffset = constant_cpu_to_le32 ( 16 );

    switch ( OID ) {

        /* general oids (table 4-1) */

        /* mandatory */
    case OID_GEN_SUPPORTED_LIST:
        /*if ( rndis_debug > 1 )
            printf( "%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__ );*/
        length = sizeof ( oid_supported_list );
        count  = length / sizeof ( u32 );
        for ( i = 0; i < count; i ++)
            outbuf[i] = cpu_to_le32 ( oid_supported_list[i] );
        retval = 0;
        break;

        /* mandatory */
    case OID_GEN_HARDWARE_STATUS:
        /*if ( rndis_debug > 1 )
            printf( "%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__ );    */
        * outbuf = constant_cpu_to_le32 ( 0 );
        retval = 0;
        break;

        /* mandatory */
    case OID_GEN_MEDIA_SUPPORTED:
        /*if ( rndis_debug > 1 )
            printf( "%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__ );*/
        * outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].medium );
        retval = 0;
        break;

        /* mandatory */
    case OID_GEN_MEDIA_IN_USE:
        /*if ( rndis_debug > 1 )
            printf( "%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__ ); */
        * outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].medium );
        retval = 0;
        break;

        /* mandatory */
    case OID_GEN_MAXIMUM_FRAME_SIZE:
        /*if ( rndis_debug > 1 )
            printf( "%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__ );*/
        if ( rndis_per_dev_params [configNr].dev ) 
        {
            * outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].dev->mtu );
            retval = 0;
        }
        break;

        /* mandatory */
    case OID_GEN_LINK_SPEED:
        /*if ( rndis_debug > 1 )
            printf( "%s: OID_GEN_LINK_SPEED\n", __FUNCTION__ );*/
        if ( rndis_per_dev_params [configNr].media_state == NDIS_MEDIA_STATE_DISCONNECTED )
            * outbuf = constant_cpu_to_le32 ( 0 );
        else
            * outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].speed );
        retval = 0;
        break;

        /* mandatory */
    case OID_GEN_TRANSMIT_BLOCK_SIZE:
        /*if ( rndis_debug > 1 )
            printf( "%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__ );*/
        if ( rndis_per_dev_params [configNr].dev ) 
        {
            * outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].dev->mtu );
            retval = 0;
        }
        break;

        /* mandatory */
    case OID_GEN_RECEIVE_BLOCK_SIZE:
        /*if ( rndis_debug > 1 )
            printf( "%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__ );*/
        if ( rndis_per_dev_params [configNr].dev ) 
        {
            * outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].dev->mtu );
            retval = 0;
        }
        break;

        /* mandatory */
    case OID_GEN_VENDOR_ID:
        /*if ( rndis_debug > 1 )
            printf( "%s: OID_GEN_VENDOR_ID\n", __FUNCTION__ );*/
        * outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].vendorID );
        retval = 0;
        break;

        /* mandatory */
    case OID_GEN_VENDOR_DESCRIPTION:
        /*if ( rndis_debug > 1 )
            printf( "%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__ );*/
        length = strlen ( rndis_per_dev_params [configNr].vendorDescr );
        memcpy ( outbuf, rndis_per_dev_params [configNr].vendorDescr, length );
        retval = 0;
        break;

    case OID_GEN_VENDOR_DRIVER_VERSION:
        /*if ( rndis_debug > 1 )
            printf( "%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__ );*/
        /* Created as LE */
        * outbuf = rndis_driver_version;
        retval = 0;
        break;

        /* mandatory */
    case OID_GEN_CURRENT_PACKET_FILTER:
        /*if ( rndis_debug > 1 )
            printf( "%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__ );*/
        * outbuf = cpu_to_le32 (* rndis_per_dev_params[configNr].filter );
        retval = 0;
        break;

        /* mandatory */
    case OID_GEN_MAXIMUM_TOTAL_SIZE:
        //if ( rndis_debug > 1 )
        //  printf( "%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__ );
        * outbuf = constant_cpu_to_le32( RNDIS_MAX_TOTAL_SIZE );
        retval = 0;
        break;

        /* mandatory */
    case OID_GEN_MEDIA_CONNECT_STATUS:
        //if ( rndis_debug > 1 )
        //    printf( "%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__ );
        * outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].media_state );
        retval = 0;
        break;

    case OID_GEN_PHYSICAL_MEDIUM:
        //if ( rndis_debug > 1 )
        //  printf( "%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__ );
        * outbuf = constant_cpu_to_le32 ( 0 );
        retval = 0;
        break;

        /* The RNDIS specification is incomplete/wrong.   Some versions
     * of MS-Windows expect OIDs that aren't specified there.  Other
     * versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
     */
    case OID_GEN_MAC_OPTIONS:       /* from WinME */
        //if ( rndis_debug > 1 )
        //  printf( "%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__ );
        * outbuf = constant_cpu_to_le32(
            NDIS_MAC_OPTION_RECEIVE_SERIALIZED | 
            NDIS_MAC_OPTION_FULL_DUPLEX );
        retval = 0;
        break;

        /* statistics OIDs (table 4-2) */

        /* mandatory */
    case OID_GEN_XMIT_OK:
        //if ( rndis_debug > 1 )
        //    printf( "%s: OID_GEN_XMIT_OK\n", __FUNCTION__ );
        if ( rndis_per_dev_params [configNr].stats ) 
        {
            * outbuf = cpu_to_le32 (
                rndis_per_dev_params [configNr].stats->tx_packets -
                rndis_per_dev_params [configNr].stats->tx_errors -
                rndis_per_dev_params [configNr].stats->tx_dropped );
            retval = 0;
        }
        break;

        /* mandatory */
    case OID_GEN_RCV_OK:
        //if ( rndis_debug > 1 )
        //    printf( "%s: OID_GEN_RCV_OK\n", __FUNCTION__ );
        if ( rndis_per_dev_params [configNr].stats ) 
        {
            * outbuf = cpu_to_le32 (
                rndis_per_dev_params [configNr].stats->rx_packets -
                rndis_per_dev_params [configNr].stats->rx_errors -
                rndis_per_dev_params [configNr].stats->rx_dropped );
            retval = 0;
        }
        break;

        /* mandatory */
    case OID_GEN_XMIT_ERROR:
        //if ( rndis_debug > 1 )
        //    printf( "%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__ );
        if ( rndis_per_dev_params [configNr].stats ) 
        {
            * outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].stats->tx_errors );
            retval = 0;
        }
        break;

        /* mandatory */
    case OID_GEN_RCV_ERROR:
        //if ( rndis_debug > 1 )
        //    printf( "%s: OID_GEN_RCV_ERROR\n", __FUNCTION__ );
        if ( rndis_per_dev_params [configNr].stats ) 
        {
            * outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].stats->rx_errors );
            retval = 0;
        }
        break;

        /* mandatory */
    case OID_GEN_RCV_NO_BUFFER:
        //if ( rndis_debug > 1 )
        //  printf( "%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__ );
        if ( rndis_per_dev_params [configNr].stats ) 
        {
            * outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].stats->rx_dropped );
            retval = 0;
        }
        break;

        /* ieee802.3 OIDs (table 4-3) */

        /* mandatory */
    case OID_802_3_PERMANENT_ADDRESS:
        //if ( rndis_debug > 1 )
        //  printf( "%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__ );
        if ( rndis_per_dev_params [configNr].dev ) 
        {
            length = ETH_ALEN;
            memcpy ( outbuf, rndis_per_dev_params [configNr].host_mac, length );
            retval = 0;
        }
        break;

        /* mandatory */
    case OID_802_3_CURRENT_ADDRESS:
        //if ( rndis_debug > 1 )
        //  printf( "%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__ );
        if ( rndis_per_dev_params [configNr].dev ) 
        {
            length = ETH_ALEN;
            memcpy ( outbuf, rndis_per_dev_params [configNr].host_mac, length );
            retval = 0;
        }
        break;

        /* mandatory */
    case OID_802_3_MULTICAST_LIST:
        //if ( rndis_debug > 1 )
        //  printf( "%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__ );
        /* Multicast base address only */
        * outbuf = constant_cpu_to_le32 ( 0xE0000000 );
        retval = 0;
        break;

        /* mandatory */
    case OID_802_3_MAXIMUM_LIST_SIZE:
        //if ( rndis_debug > 1 )
        //  printf( "%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__ );
        /* Multicast base address only */
        * outbuf = constant_cpu_to_le32 ( 1 );
        retval = 0;
        break;

    case OID_802_3_MAC_OPTIONS:
        //if ( rndis_debug > 1 )
        //  printf( "%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__ );
        break;

        /* ieee802.3 statistics OIDs (table 4-4) */

        /* mandatory */
    case OID_802_3_RCV_ERROR_ALIGNMENT:
        //if ( rndis_debug > 1 )
        //  printf( "%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__ );
        if ( rndis_per_dev_params [configNr].stats ) 
        {
            * outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].stats->rx_frame_errors );
            retval = 0;
        }
        break;

        /* mandatory */
    case OID_802_3_XMIT_ONE_COLLISION:
        //if ( rndis_debug > 1 )
        //  printf( "%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__ );
        * outbuf = constant_cpu_to_le32 ( 0 );
        retval = 0;
        break;

        /* mandatory */
    case OID_802_3_XMIT_MORE_COLLISIONS:
        //if ( rndis_debug > 1 )
        //  printf( "%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__ );
        * outbuf = constant_cpu_to_le32 ( 0 );
        retval = 0;
        break;

#ifdef  RNDIS_PM
        /* power management OIDs (table 4-5) */
    case OID_PNP_CAPABILITIES:
        //if ( rndis_debug > 1 )
        //  printf( "%s: OID_PNP_CAPABILITIES\n", __FUNCTION__ );

        /* for now, no wakeup capabilities */
        length = sizeof ( struct NDIS_PNP_CAPABILITIES );
        memset( outbuf, 0, length );
        retval = 0;
        break;
    case OID_PNP_QUERY_POWER:
        //if ( rndis_debug > 1 )
        //  printf( "%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__,
        //    le32_to_cpu( get_unaligned(( le32 *)buf )) - 1 );
        /* only suspend is a real power state, and
         * it can't be entered by OID_PNP_SET_POWER...
         */
        length = 0;
        retval = 0;
        break;
#endif

    default:
        printf( "%s: query unknown OID 0x%08X\n", __FUNCTION__, OID );
        break;
    }
    if ( retval < 0 )
        length = 0;

    resp->InformationBufferLength = cpu_to_le32 ( length );
    //r->length = length + sizeof * resp;
    r->length = length + sizeof ( rndis_query_cmplt_type );    //////////////////
    resp->MessageLength = cpu_to_le32 ( r->length );
    return retval;
}

static int gen_ndis_set_resp ( u8 configNr, u32 OID, u8 * buf, 
    u32 buf_len, rndis_resp_t * r )
{
    rndis_set_cmplt_type        * resp;
    int             /*i,*/ retval = - ERR_NOTSUPP;
    struct rndis_params     * params;

    if (! r )
        return - ERR_NOMEM;
    resp = ( rndis_set_cmplt_type *) r->buf;
    if (! resp )
        return - ERR_NOMEM;

⌨️ 快捷键说明

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