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

📄 rndisdev.c

📁 基于TI DSP/BIOS的usb网卡的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <std.h>
#include <sem.h>
#include <lck.h>
#include <csl.h>
#include <csl_irq.h>
#include <stdio.h>
#include <assert.h>

#include "rndisdev.h"
#include "Hal4D13.h"
#include "Hal4sys.h"
#include "string.h"
#include "usb_cdc.h"

#define  MANUFACTURER_STRING "Manufacturer string"
static struct rndis_dev ethdev;
static SEM_Handle semUsbIrq = NULL;

//all rndis data muster align on 4 
#pragma DATA_ALIGN(ctrltrans,4);  //4byte align 
#pragma DATA_ALIGN(intrans,4);    //4byte align 
#pragma DATA_ALIGN(outtrans,4);   //4byte align 
static struct control_trans ctrltrans;
static struct generic_trans intrans, outtrans;

int rndis_dev_index = - 1;        //rndis side selector
static Uint8 rndis_mac[6] = {0x00, 0x10, 0x07, 0x0b, 0x68, 0x58}; //host side mac
static u8 BufferTmp[MAX_PACKET_BUFFER_SIZE];
#define TX_QUEUE_SIZE    (1024 * 8)  //driver tx buffer
static u8 txQueueBuffer[TX_QUEUE_SIZE];

int usb_eth_init( struct ei_device * ei_local );
int usb_eth_send( struct ei_device * ei_local, PKT_Handle hPkt );
int usb_eth_raw_send( struct ei_device * ei_local, char * buf, unsigned int len );
int usb_eth_set_promisc( struct ei_device * ei_local );

struct ei_device usb_driver = {
    usb_eth_init,
        usb_eth_send,
        usb_eth_raw_send,
        usb_eth_set_promisc
};

static u16 dequeue_tx_msg( struct rndis_dev * dev, u8 * buf )
{
    u16 len = 0;
    struct LoopBuffCtl * queue = & dev->tx_queue;  

    if( LoopBuffDataLength( queue ))
    {
        usb_lock( dev->lock );
        LoopBuffRead( queue,( u8 *)& len, sizeof( u16 ) ); //data len
        LoopBuffRead( queue, buf, len );
        usb_unlock( dev->lock );
    }

    assert( len < USB_RNDIS_MTU );
    return len;
}

//if usb transmit busy,buffer the tcp/ip data
static int queue_tx_msg( struct rndis_dev * dev , PKT_Handle hPkt )
{
    u16 res;
    struct LoopBuffCtl * queue = & dev->tx_queue;
    res = skb_getNbProtLen( hPkt ); 
    assert( res < USB_RNDIS_MTU );

    usb_lock( dev->lock );
    if( LoopBuffFreeSpace( queue ) > ( 2 + res )) //check free space
    {
        LoopBuffWrite( queue,( u8 *)& res, sizeof( u16 ) );  //data len
        LoopBuffWrite( queue,( u8 *)skb_getNbProt( hPkt ) + 2, res ); //skp require len 2
    }
    else
        res = 0;
    usb_unlock( dev->lock );

    return res;
}

//packet buffer data into rndis packet
static u16 rndisdev_prepare_trans( struct generic_trans * trans, u8 * buf, u16 length )
{
    struct rndis_packet_msg_type * msg = ( struct rndis_packet_msg_type *)trans->dataBuffer;
    u32 msgsize = sizeof( struct rndis_packet_msg_type );

    memset( msg, 0, msgsize );
    msg->MessageType = constant_cpu_to_le32( REMOTE_NDIS_PACKET_MSG );
    msg->MessageLength = cpu_to_le32( msgsize + length );
    msg->DataOffset = cpu_to_le32( msgsize - 8 ); /*44 - 8 = 36*/
    msg->DataLength = length;   
    memcpy( trans->dataBuffer + msgsize, buf, length );
    trans->dataLength = msgsize + length;
    trans->transmitLength = 0;

    assert( length < USB_RNDIS_MTU );

    return trans->dataLength;
}

extern SEM_Handle tcpTaskSem;
static void rndisdev_on_rxpacket( struct rndis_dev * dev, u8 * buf, u16 len )
{
    u8 * data;
    PKT_Handle hPtk;
    struct net_device_stats1 * state = & dev->stats;

    if( dev->usbstate == USB_STATE_CONFIGURED )
    { //skb require len 2,get buffer from tcp/ip
        hPtk = get_skb( len + 2, ( char **)& data ); 
        if( hPtk == NULL )
        { 
            state->rx_dropped ++;
            state->rx_errors ++;        
        }
        else
        {
            memcpy( data + 2, buf, len );            //skb require len 2
            set_skb( dev->net->iface, hPtk, len );   //send the packet to tcp/ip stack
            state->tx_packets ++;
            state->tx_bytes += len; 
            SEM_post( tcpTaskSem );                  //triger tcp/ip process
        }
    }
}

extern int usb_setup( struct rndis_dev * dev );
static void rndisdev_setup( struct rndis_dev * dev )
{   
    u16 len;
    int res;   
    struct usb_ep_control * ep = & dev->ctrl_ep;   

    res = usb_setup( dev ); 
    if( res == 0 )  //no data return
        ep->status = EP_STATUS_IDLE;    
    else if( res > 0 )
    { //start data transmit
        if( ( ep->trans->DeviceRequest.bRequestType & USB_DIR_IN )
            && ( res > ep->trans->DeviceRequest.wLength ) )
            res = ep->trans->DeviceRequest.wLength;            

        len = ( res < CONTROL_PACKET_SIZE ) ?  res : CONTROL_PACKET_SIZE;       
        if( Hal4D13_WriteEndpoint( ep->index + 1, ep->trans->dataBuffer, len ) == len )
        {
            if( len == CONTROL_PACKET_SIZE )
            {           
                ep->trans->dataLength = res;        
                ep->status = EP_STATUS_IN;
                ep->trans->transmitLength  = CONTROL_PACKET_SIZE;                               
            }           
            else
                ep->status = EP_STATUS_IDLE;               
        }   
    }   
    else /*ERR_NOTSUPP*/  
        Hal4D13_SingleTransmitEP0( 0, 0 );      
}

/* CDC and RNDIS support the same host-chosen outgoing packet filters. */
#define DEFAULT_FILTER  (USB_CDC_PACKET_TYPE_BROADCAST \
            |USB_CDC_PACKET_TYPE_ALL_MULTICAST \
            |USB_CDC_PACKET_TYPE_PROMISCUOUS \
            |USB_CDC_PACKET_TYPE_DIRECTED)

static void ep_ctl_out_handle( struct rndis_dev * dev )
{   
    struct usb_ep_control * ep = & dev->ctrl_ep;
    struct control_trans * trans = ep->trans;
    struct usb_ctrlrequest * ctrl = ( struct usb_ctrlrequest *)(&( trans->DeviceRequest ));
    u8 epstatus, len, dirin;

    epstatus = Hal4D13_GetEndpointStatusWInteruptClear( ep->index );   

    if( epstatus & D13REG_EPSTS_SETUP )
    {   
        len = Hal4D13_ReadEndpointWOClearBuffer( ep->index, ( u8 *)ctrl, CONTROL_PACKET_SIZE );     
        Hal4D13_AcknowledgeSETUP(); 
        Hal4D13_ClearBuffer( ep->index );       
        trans->dataLength = ctrl->wLength;
        ep->trans->transmitLength = len - sizeof( struct usb_ctrlrequest ); 
        dirin = ctrl->bRequestType & USB_DIR_IN;
        if( dirin || ( (! dirin ) && ctrl->wLength == 0 ) )  
        {
            ep->status = EP_STATUS_IDLE;
            rndisdev_setup( dev );      //complete setup packet received            
        }
        else
            ep->status = EP_STATUS_OUT; 
    }
    else if( ep->status == EP_STATUS_OUT )
    {
        len = Hal4D13_ReadEndpoint( ep->index, trans->dataBuffer + trans->transmitLength, CONTROL_PACKET_SIZE );
        trans->transmitLength += len;
        if( len < CONTROL_PACKET_SIZE )
        {
            ep->status = EP_STATUS_IDLE;
            rndisdev_setup( dev );     //complete setup packet received             
        }
    }  
    else
        ep->status = EP_STATUS_IDLE;
}

static void ep_ctl_in_handle( struct rndis_dev * dev )
{
    struct usb_ep_control * ep = & dev->ctrl_ep;
    struct control_trans * trans = ep->trans;
    u8 len;

    Hal4D13_GetEndpointStatusWInteruptClear( ep->index + 1 );   
    if( ep->status == EP_STATUS_IN )
    { //data in sending
        len = trans->dataLength - trans->transmitLength;
        if( len > CONTROL_PACKET_SIZE )
            len = CONTROL_PACKET_SIZE;
        if( Hal4D13_WriteEndpoint( ep->index + 1,
            trans->dataBuffer + trans->transmitLength,
            len ) == len )
        {
            trans->transmitLength += len;
            if( len < CONTROL_PACKET_SIZE )//transmit over
                ep->status = EP_STATUS_IDLE; 
        }
    }
    else
        ep->status = EP_STATUS_IDLE;
}

static void ep_in_handle( struct rndis_dev * dev )
{
    struct usb_ep_general * ep = & ( dev->in_ep );
    struct generic_trans * trans = ep->trans;
    u16 len, bufs, ep_last;

    ep_last = Hal4D13_GetEndpointStatusWInteruptClear( ep->index );
    if(( ep_last & ( D13REG_EPSTS_DBF0 | D13REG_EPSTS_DBF1 )) == 0x00 )
        bufs = 2;
    else
        bufs = 1;
    while( bufs )
    {
        if( ep->status == EP_STATUS_IN )
        { //data in processing
            len = trans->dataLength - trans->transmitLength;
            if( len > BULK_PACKET_SIZE )
                len = BULK_PACKET_SIZE ;
            if( Hal4D13_WriteEndpoint( ep->index, trans->dataBuffer + 
                trans->transmitLength, len ) == len )
            {            
                trans->transmitLength += len;
                if( len < BULK_PACKET_SIZE )
                { //packet transmit over   
                    dev->stats.rx_packets ++;
                    dev->stats.rx_bytes += trans->transmitLength;

                    /*//start new packet transmit
                    len = dequeue_tx_msg( dev , BufferTmp );        
                    if( len )
                        rndisdev_prepare_trans( trans, BufferTmp, len ); 
                    else
                        ep->status = EP_STATUS_IDLE;            
                    */
                    ep->status = EP_STATUS_IDLE;
                }       
            }   
        }
        else
            ep->status = EP_STATUS_IDLE;

        if( ep->status == EP_STATUS_IDLE )
        {
            len = dequeue_tx_msg( dev , BufferTmp );        
            if( len )
            {
                rndisdev_prepare_trans( trans, BufferTmp, len ); 
                ep->status = EP_STATUS_IN;                
            }            
        }

        bufs --;
    }
}

static void ep_out_handle( struct rndis_dev * dev )
{

⌨️ 快捷键说明

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