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

📄 rndis.c

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

    /*if ( buf_len && rndis_debug > 1 ) 
    {
        printf( "set 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] )));
        }
    }*/

    params = & rndis_per_dev_params [configNr];
    switch ( OID ) {
    case OID_GEN_CURRENT_PACKET_FILTER:
        * params->filter = ( u16 ) le32_to_cpu( get_unaligned(( le32 *)buf ));
        //if ( rndis_debug > 1 )
        //  printf( "%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n", __FUNCTION__, * params->filter );

#ifdef  RNDIS_PM
    update_linkstate:
#endif
        retval = 0;
        if (* params->filter ) 
            params->state = RNDIS_DATA_INITIALIZED;
        else
            params->state = RNDIS_INITIALIZED;            
        break;

    case OID_802_3_MULTICAST_LIST:
        /* I think we can ignore this */
        //if ( rndis_debug > 1 )
        //  printf( "%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__ );
        retval = 0;
        break;

#ifdef  RNDIS_PM
    case OID_PNP_SET_POWER:
        i = le32_to_cpu( get_unaligned(( le32 *)buf ));
        //if ( rndis_debug > 1 )
        //  printf( "%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1 );
        switch ( i ) 
        {
        case NdisDeviceStateD0:
            * params->filter = params->saved_filter;
            goto update_linkstate;
        case NdisDeviceStateD3:
        case NdisDeviceStateD2:
        case NdisDeviceStateD1:
            params->saved_filter = * params->filter;
            retval = 0;
            break;
        }
        break;
#endif  /* RNDIS_PM */

    default:
        printf( "%s: set unknown OID 0x%08X, size %d\n", __FUNCTION__, OID, buf_len );
        break;
    }
    return retval;
}

/*
 * Response Functions
 */

static int rndis_init_response ( int configNr, rndis_init_msg_type * buf )
{
    rndis_init_cmplt_type   * resp;
    rndis_resp_t            * r;

    if (! rndis_per_dev_params [configNr].dev ) return - ERR_NOTSUPP;

    r = rndis_add_response ( configNr, sizeof ( rndis_init_cmplt_type ));
    if (! r )   return - ERR_NOMEM;
    resp = ( rndis_init_cmplt_type *) r->buf;

    resp->MessageType = constant_cpu_to_le32 ( REMOTE_NDIS_INITIALIZE_CMPLT );
    resp->MessageLength = constant_cpu_to_le32 ( 52 );
    resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
    resp->Status = constant_cpu_to_le32 ( RNDIS_STATUS_SUCCESS );
    resp->MajorVersion = constant_cpu_to_le32 ( RNDIS_MAJOR_VERSION );
    resp->MinorVersion = constant_cpu_to_le32 ( RNDIS_MINOR_VERSION );
    resp->DeviceFlags = constant_cpu_to_le32 ( RNDIS_DF_CONNECTIONLESS );
    resp->Medium = constant_cpu_to_le32 ( RNDIS_MEDIUM_802_3 );
    resp->MaxPacketsPerTransfer = constant_cpu_to_le32 ( 1 );
    resp->MaxTransferSize = cpu_to_le32 (
        rndis_per_dev_params [configNr].dev->mtu
        + /*sizeof (struct ethhdr)*/ETH_HLEN
        + sizeof ( struct rndis_packet_msg_type )
        + 22 );
    resp->PacketAlignmentFactor = constant_cpu_to_le32 ( 0 );
    resp->AFListOffset = constant_cpu_to_le32 ( 0 );
    resp->AFListSize = constant_cpu_to_le32 ( 0 );

    if ( rndis_per_dev_params [configNr].ack )
        rndis_per_dev_params [configNr].ack ( rndis_per_dev_params [configNr].dev );

    return 0;
}

static int rndis_query_response ( int configNr, rndis_query_msg_type * buf )
{
    rndis_query_cmplt_type * resp;
    rndis_resp_t            * r;

    //if ( rndis_debug > 1 )
    //  printf( "%s: OID = %08X\n", __FUNCTION__, cpu_to_le32( buf->OID ));

    if (! rndis_per_dev_params [configNr].dev ) return - ERR_NOTSUPP;

    r = rndis_add_response ( configNr,
        sizeof ( oid_supported_list ) + sizeof( rndis_query_cmplt_type ));
    if (! r )    return - ERR_NOMEM;
    resp = ( rndis_query_cmplt_type *) r->buf;

    resp->MessageType = constant_cpu_to_le32 ( REMOTE_NDIS_QUERY_CMPLT );
    resp->RequestID = buf->RequestID; /* Still LE in msg buffer */

    if ( gen_ndis_query_resp ( configNr, le32_to_cpu ( buf->OID ),
        le32_to_cpu( buf->InformationBufferOffset )
        + 8 + ( u8 *) buf,
        le32_to_cpu( buf->InformationBufferLength ),
        r )) 
    {
        /* OID not supported */
        resp->Status = constant_cpu_to_le32 ( RNDIS_STATUS_NOT_SUPPORTED );
        //resp->MessageLength = constant_cpu_to_le32 ( sizeof * resp );
        resp->MessageLength = constant_cpu_to_le32 ( sizeof ( rndis_query_cmplt_type ) );   /////////////
        resp->InformationBufferLength = constant_cpu_to_le32 ( 0 );
        resp->InformationBufferOffset = constant_cpu_to_le32 ( 0 );
    } 
    else
        resp->Status = constant_cpu_to_le32 ( RNDIS_STATUS_SUCCESS );

    if ( rndis_per_dev_params [configNr].ack )
        rndis_per_dev_params [configNr].ack ( rndis_per_dev_params [configNr].dev );
    return 0;
}

static int rndis_set_response ( int configNr, rndis_set_msg_type * buf )
{
    u32   BufLength, BufOffset;
    rndis_set_cmplt_type    * resp;
    rndis_resp_t        * r;

    r = rndis_add_response ( configNr, sizeof ( rndis_set_cmplt_type ));
    if (! r )    return - ERR_NOMEM;
    resp = ( rndis_set_cmplt_type *) r->buf;

    BufLength = le32_to_cpu ( buf->InformationBufferLength );
    BufOffset = le32_to_cpu ( buf->InformationBufferOffset );

    resp->MessageType = constant_cpu_to_le32 ( REMOTE_NDIS_SET_CMPLT );
    resp->MessageLength = constant_cpu_to_le32 ( 16 );
    resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
    if ( gen_ndis_set_resp ( configNr, le32_to_cpu ( buf->OID ),
        (( u8 *) buf ) + 8 + BufOffset, BufLength, r ))
        resp->Status = constant_cpu_to_le32 ( RNDIS_STATUS_NOT_SUPPORTED );
    else
        resp->Status = constant_cpu_to_le32 ( RNDIS_STATUS_SUCCESS );

    if ( rndis_per_dev_params [configNr].ack )
        rndis_per_dev_params [configNr].ack ( rndis_per_dev_params [configNr].dev );

    return 0;
}

static int rndis_reset_response ( int configNr, rndis_reset_msg_type * buf )
{
    rndis_reset_cmplt_type  * resp;
    rndis_resp_t        * r;

    r = rndis_add_response ( configNr, sizeof ( rndis_reset_cmplt_type ));
    if (! r )   return - ERR_NOMEM;
    resp = ( rndis_reset_cmplt_type *) r->buf;

    resp->MessageType = constant_cpu_to_le32 ( REMOTE_NDIS_RESET_CMPLT );
    resp->MessageLength = constant_cpu_to_le32 ( 16 );
    resp->Status = constant_cpu_to_le32 ( RNDIS_STATUS_SUCCESS );
    /* resent information */
    resp->AddressingReset = constant_cpu_to_le32 ( 1 );

    if ( rndis_per_dev_params [configNr].ack )
        rndis_per_dev_params [configNr].ack ( rndis_per_dev_params [configNr].dev );

    return 0;
}

static int rndis_keepalive_response ( int configNr, rndis_keepalive_msg_type * buf )
{
    rndis_keepalive_cmplt_type  * resp;
    rndis_resp_t            * r;

    /* host "should" check only in RNDIS_DATA_INITIALIZED state */

    r = rndis_add_response ( configNr, sizeof ( rndis_keepalive_cmplt_type ));
    if (! r )  return - ERR_NOMEM;
    resp = ( rndis_keepalive_cmplt_type *) r->buf;

    resp->MessageType = constant_cpu_to_le32 ( REMOTE_NDIS_KEEPALIVE_CMPLT );
    resp->MessageLength = constant_cpu_to_le32 ( 16 );
    resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
    resp->Status = constant_cpu_to_le32 ( RNDIS_STATUS_SUCCESS );

    if ( rndis_per_dev_params [configNr].ack )
        rndis_per_dev_params [configNr].ack ( rndis_per_dev_params [configNr].dev );

    return 0;
}

/*
 * Device to Host Comunication
 */
/*static int rndis_indicate_status_msg ( int configNr, u32 status )
{
    rndis_indicate_status_msg_type  * resp;
    rndis_resp_t            * r;

    if ( rndis_per_dev_params [configNr].state == RNDIS_UNINITIALIZED )
        return - ERR_NOTSUPP;

    r = rndis_add_response ( configNr,  sizeof ( rndis_indicate_status_msg_type ));
    if (! r )    return - ERR_NOMEM;
    resp = ( rndis_indicate_status_msg_type *) r->buf;

    resp->MessageType = constant_cpu_to_le32 ( REMOTE_NDIS_INDICATE_STATUS_MSG );
    resp->MessageLength = constant_cpu_to_le32 ( 20 );
    resp->Status = cpu_to_le32 ( status );
    resp->StatusBufferLength = constant_cpu_to_le32 ( 0 );
    resp->StatusBufferOffset = constant_cpu_to_le32 ( 0 );

    if ( rndis_per_dev_params [configNr].ack )
        rndis_per_dev_params [configNr].ack ( rndis_per_dev_params [configNr].dev );
    return 0;
}*/

void rndis_set_host_mac ( int configNr, const u8 * addr )
{
    rndis_per_dev_params [configNr].host_mac = addr;
}

/*
 * Message Parser
 */
int rndis_msg_parser ( u8 configNr, u8 * buf )
{
    u32 MsgType, MsgLength;
    le32 * tmp;
    struct rndis_params     * params;

    if (! buf )  return - ERR_NOMEM;

    tmp = ( le32 *) buf;
    MsgType   = le32_to_cpu( get_unaligned( tmp ++));
    MsgLength = le32_to_cpu( get_unaligned( tmp ++));

    if ( configNr >= RNDIS_MAX_CONFIGS )
        return - ERR_NOTSUPP;
    params = & rndis_per_dev_params [configNr];

    /* For USB: responses may take up to 10 seconds */
    switch ( MsgType ) 
    {
    case REMOTE_NDIS_INITIALIZE_MSG:
        //if ( rndis_debug > 1 )
        //  printf( "%s: REMOTE_NDIS_INITIALIZE_MSG\n", __FUNCTION__ );
        params->state = RNDIS_INITIALIZED;
        return  rndis_init_response ( configNr, ( rndis_init_msg_type *) buf );

    case REMOTE_NDIS_HALT_MSG:
        //if ( rndis_debug > 1 )
        //  printf( "%s: REMOTE_NDIS_HALT_MSG\n",  __FUNCTION__ );
        params->state = RNDIS_UNINITIALIZED;
        return 0;

    case REMOTE_NDIS_QUERY_MSG:
        return rndis_query_response ( configNr, ( rndis_query_msg_type *) buf );

    case REMOTE_NDIS_SET_MSG:
        return rndis_set_response ( configNr, ( rndis_set_msg_type *) buf );

    case REMOTE_NDIS_RESET_MSG:
        //if ( rndis_debug > 1 )
        //  printf( "%s: REMOTE_NDIS_RESET_MSG\n",  __FUNCTION__ );
        return rndis_reset_response ( configNr, ( rndis_reset_msg_type *) buf );

    case REMOTE_NDIS_KEEPALIVE_MSG:
        /* For USB: host does this every 5 seconds */
        //if ( rndis_debug > 1 )
        //    printf( "%s: REMOTE_NDIS_KEEPALIVE_MSG\n",  __FUNCTION__ );
        return rndis_keepalive_response ( configNr,( rndis_keepalive_msg_type *)buf );

    default:    
        printf( "%s: unknown RNDIS message 0x%08X len %d\n",
            __FUNCTION__ , MsgType, MsgLength );
        {
            unsigned i;
            for ( i = 0; i < MsgLength; i += 16 ) 
            {
                printf( "%03d: "
                    " %02x %02x %02x %02x"
                    " %02x %02x %02x %02x"
                    " %02x %02x %02x %02x"
                    " %02x %02x %02x %02x"
                    "\n",
                    i,
                    buf[i], buf [i + 1],
                    buf[i + 2], buf[i + 3],
                    buf[i + 4], buf [i + 5],
                    buf[i + 6], buf[i + 7],
                    buf[i + 8], buf [i + 9],
                    buf[i + 10], buf[i + 11],
                    buf[i + 12], buf [i + 13],
                    buf[i + 14], buf[i + 15] );
            }
        }
        break;
    }

    return - ERR_NOTSUPP;
}

int rndis_register ( int (* rndis_control_ack ) ( struct rndis_dev *))
{
    u8 i;

    for ( i = 0; i < RNDIS_MAX_CONFIGS; i ++) 
    {
        if (! rndis_per_dev_params [i].used ) 
        {
            rndis_per_dev_params [i].used = 1;
            rndis_per_dev_params [i].ack = rndis_control_ack;
            //printf( "%s: configNr = %d\n", __FUNCTION__, i );
            return i;
        }
    }
    printf( "failed\n" );

    return - 1;
}

int rndis_set_param_dev ( u8 configNr, struct rndis_dev * dev,
    struct net_device_stats1 * stats,
    u16 * cdc_filter )
{
    //printf( "%s:\n", __FUNCTION__ );
    if (! dev || ! stats ) return - 1;
    if ( configNr >= RNDIS_MAX_CONFIGS ) return - 1;

    rndis_per_dev_params [configNr].dev = dev;
    rndis_per_dev_params [configNr].stats = stats;
    rndis_per_dev_params [configNr].filter = cdc_filter;

    return 0;
}

int rndis_set_param_vendor ( u8 configNr, u32 vendorID, const char * vendorDescr )
{
    //printf( "%s:\n", __FUNCTION__ );
    if (! vendorDescr ) return - 1;
    if ( configNr >= RNDIS_MAX_CONFIGS ) return - 1;

    rndis_per_dev_params [configNr].vendorID = vendorID;
    rndis_per_dev_params [configNr].vendorDescr = vendorDescr;

    return 0;
}

int rndis_set_param_medium ( u8 configNr, u32 medium, u32 speed )
{
    //printf( "%s: %u %u\n", __FUNCTION__, medium, speed );
    if ( configNr >= RNDIS_MAX_CONFIGS ) return - 1;

    rndis_per_dev_params [configNr].medium = medium;
    rndis_per_dev_params [configNr].speed = speed;

    return 0;
}

void rndis_free_response ( int configNr, u8 * buf )
{
    int i;
    rndis_resp_t * r;
    for( i = 0; i < RNDIS_MSG_QUEUE_SIZE; i ++)
    {
        r = & ( rndis_per_dev_params[configNr].resp_queue[i] );
        if(( u8 *)r->buf == buf )
        {
            memset( r, 0, sizeof( rndis_resp_t ));
            break;
        }
    }
}

u8 * rndis_get_next_response ( int configNr, u32 * length )
{
    int i;
    rndis_resp_t  * r;
    for( i = 0; i < RNDIS_MSG_QUEUE_SIZE; i ++)
    {
        r = & ( rndis_per_dev_params[configNr].resp_queue[i] );
        if( r->inUse && ( r->send == 0 ) )
        {
            r->send = 1;
            * length = r->length;
            return ( u8 *)r->buf;
        }
    }
    return NULL;
}

static rndis_resp_t * rndis_add_response ( int configNr, u32 length )
{
    int i;
    rndis_resp_t    * r = 0;

    assert( length < ( RNDSI_MAX_MSGS * 4 ) );

    for( i = 0; i < RNDIS_MSG_QUEUE_SIZE; i ++)
    {   
        r = & ( rndis_per_dev_params[configNr].resp_queue[i] );
        if( r->inUse == 0 )
        {            
            r->inUse = 1;
            r->length = length;
            r->send = 0;
            break;      
        }
    }
    return r;
}

int rndis_init ( void )
{
    u8 i;
    for ( i = 0; i < RNDIS_MAX_CONFIGS; i ++) 
    {
        memset(& rndis_per_dev_params[i], 0, sizeof( rndis_params ));
        rndis_per_dev_params [i].confignr = i;
        rndis_per_dev_params [i].used = 0;
        rndis_per_dev_params [i].state = RNDIS_UNINITIALIZED;
        rndis_per_dev_params [i].media_state = NDIS_MEDIA_STATE_CONNECTED;
        //NDIS_MEDIA_STATE_DISCONNECTED;
    }
    return 0;
}

void rndis_setstate( int configNr, enum rndis_state state )
{
    rndis_per_dev_params[configNr].state = state;
}

enum rndis_state rndis_getstate( int configNr )
{
    return rndis_per_dev_params[configNr].state;
}

⌨️ 快捷键说明

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