Top secrets sources NedoPC zxusbnet

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?


//#include "../my.h"
#include "../zxevo_io.h"
#include <stdio.h>
#include <Intrz80.h>
#include <string.h>
#include "SL811.H"  
#include "HAL.H"  

extern FLAGS bdata bFlags;  
PKG usbstack;  
unsigned char xdata DBUF[BUFFER_LENGTH];  
pUSBDEV xdata uDev; // Multiple USB devices attributes, Max 5 devices  

//*****************************************************************************************  
// usbXfer:  
// successful transfer = return TRUE  
// fail transfer = return FALSE  
//*****************************************************************************************  
unsigned char usbXfer(void)  
{    
    unsigned char xferLen, data0, data1,cmd;  
    unsigned char intr,result,remainder,dataX,bufLen,addr,timeout;  
    unsigned char out[8];  

    //------------------------------------------------  
    // Default setting for usb trasnfer  
    //------------------------------------------------  
    dataX=timeout=0;  
       
    data0 = EP0_Buf;                    // DATA0 buffer address  
    data1 = data0 + (unsigned char)usbstack.wPayload;   // DATA1 buffer address  
    bFlags.bits.DATA_STOP=FALSE;  
    bFlags.bits.TIMEOUT_ERR=FALSE;  

    //------------------------------------------------  
    // Define data transfer payload  
    //------------------------------------------------  
    if (usbstack.wLen >= usbstack.wPayload)          // select proper data payload  
        xferLen = usbstack.wPayload;            // limit to wPayload size    
    else                            // else take < payload len  
        xferLen = usbstack.wLen;            //    
       
    // For IN token  
    if (usbstack.pid==PID_IN)               // for current IN tokens  
        {
//              if(bFlags.bits.FULL_SPEED)
//                      cmd=sDATA0_RD;
//              else
//                      cmd=DATA0_RD;
        cmd = sDATA0_RD;            // FS/FS on Hub, sync to sof  
        }  
    // For OUT token  
    else if(usbstack.pid==PID_OUT)              // for OUT tokens  
    {      
        if(xferLen)                                 // only when there are    
                {
            SL811BufWrite(data0,usbstack.buffer,xferLen);   // data to transfer on USB  
//              if(bFlags.bits.FULL_SPEED)
//                      cmd=sDATA0_WR;
//              else
//                      cmd=DATA0_WR;
                }
                cmd = sDATA0_WR;                        // FS/FS on Hub, sync to sof  
    // implement data toggle  
        bFlags.bits.bData1 = uDev.bData1[usbstack.endpoint];  
            uDev.bData1[usbstack.endpoint] = (uDev.bData1[usbstack.endpoint] ? 0 : 1); // DataToggle  
           
        if(bFlags.bits.bData1)  
                cmd |= 0x40;                              // Set Data1 bit in command  
    }  
    //------------------------------------------------  
    // For SETUP/OUT token  
    //------------------------------------------------  
    else                                            // for current SETUP/OUT tokens  
    {      
        if(xferLen)                                 // only when there are    
        {                                       // data to transfer on USB  
            intr=usbstack.setup.wLength;              
            out[0]=usbstack.setup.bmRequest;  
            out[1]=usbstack.setup.bRequest;  
            out[2]=(unsigned char)usbstack.setup.wValue;  
            out[3]=(unsigned char)(usbstack.setup.wValue>>8);  
            out[4]=(unsigned char)usbstack.setup.wIndex;  
            out[5]=(unsigned char)(usbstack.setup.wIndex>>8);  
            out[6]=(unsigned char)usbstack.setup.wLength;  
            out[7]=(unsigned char)(usbstack.setup.wLength>>8);  
            SL811BufWrite(data0,out,xferLen);  
            usbstack.setup.wLength=intr;  
        }  
//              if(bFlags.bits.FULL_SPEED)
//                      cmd=sDATA0_WR;
//              else
//                      cmd=DATA0_WR;
                cmd = sDATA0_WR;                            // FS/FS on Hub, sync to sof  
    }  
    //------------------------------------------------  
    // For EP0's IN/OUT token data, start with DATA1  
    // Control Endpoint0's status stage.  
    // For data endpoint, IN/OUT data, start ????  
    //------------------------------------------------  
    if (usbstack.endpoint == 0 && usbstack.pid != PID_SETUP)    // for Ep0's IN/OUT token  
        cmd |= 0x40;                    // always set DATA1  
    //------------------------------------------------  
    // Arming of USB data transfer for the first pkt  
    //------------------------------------------------  
    SL811Write(EP0Status,((usbstack.endpoint&0x0F)|usbstack.pid));  // PID + EP address  
    SL811Write(EP0Counter,usbstack.usbaddr);                    // USB address  
    SL811Write(EP0Address,data0);                   // buffer address, start with "data0"  
    SL811Write(EP0XferLen,xferLen);                 // data transfer length  
    SL811Write(IntStatus,INT_CLEAR);                // clear interrupt status  
    SL811Write(EP0Control,cmd);                     // Enable ARM and USB transfer start here  
       
    //------------------------------------------------  
    // Main loop for completing a wLen data trasnfer  
    //------------------------------------------------  
    while(TRUE)  
    {      
        //---------------Wait for done interrupt------------------  
        while(TRUE)                                             // always ensure requested device is  
        {                                                       // inserted at all time, then you will  
            intr = SL811Read(IntStatus);      
                                    // wait for interrupt to be done, and    
            if((intr & USB_RESET) || (intr & INSERT_REMOVE))    // proceed to parse result from slave    
            {                                                   // device.  
                bFlags.bits.DATA_STOP = TRUE;                               // if device is removed, set DATA_STOP  
               
                return FALSE;                                   // flag true, so that main loop will    
            }                                                   // know this condition and exit gracefully  
            if(intr & USB_A_DONE)                                  
                break;                          // interrupt done !!!  
        }  
   
        SL811Write(IntStatus,INT_CLEAR); // clear interrupt status  
        result    = SL811Read(EP0Status);                       // read EP0status register  
        remainder = SL811Read(EP0Counter);                      // remainder value in last pkt xfer  
   
        //-------------------------ACK----------------------------  
        if (result & EP0_ACK)                                   // Transmission ACK  
        {      
   
            // SETUP TOKEN  
            if(usbstack.pid == PID_SETUP)                               // do nothing for SETUP/OUT token    
                break;                                          // exit while(1) immediately  
   
            // OUT TOKEN                  
            else if(usbstack.pid == PID_OUT)  
                break;  
   
            // IN TOKEN  
            else if(usbstack.pid == PID_IN)  
            {                                                   // for IN token only  
                usbstack.wLen  -= (WORD)xferLen;    // update remainding wLen value  
                cmd   ^= 0x40;              // toggle DATA0/DATA1  
                dataX++;                // point to next dataX  
   
                //------------------------------------------------    
                // If host requested for more data than the slave    
                // have, and if the slave's data len is a multiple  
                // of its endpoint payload size/last xferLen. Do    
                // not overwrite data in previous buffer.  
                //------------------------------------------------    
                if(remainder==xferLen)          // empty data detected  
                    bufLen = 0;         // do not overwriten previous data  
                else                    // reset bufLen to zero  
                    bufLen = xferLen;       // update previous buffer length  
                   
                //------------------------------------------------    
                // Arm for next data transfer when requested data    
                // length have not reach zero, i.e. wLen!=0, and  
                // last xferlen of data was completed, i.e.  
                // remainder is equal to zero, not a short pkt  
                //------------------------------------------------    
                if(!remainder && usbstack.wLen)                         // remainder==0 when last xferLen  
                {                                               // was all completed or wLen!=0  
                    addr    = (dataX & 1) ? data1:data0;        // select next address for data  
                    xferLen = (BYTE)(usbstack.wLen>=usbstack.wPayload) ? usbstack.wPayload:usbstack.wLen;    // get data length required  
                                   
                    cmd |= 0x20;                            // always sync SOF when FS, regardless    
                    SL811Write(EP0XferLen, xferLen);            // select next xfer length  
                    SL811Write(EP0Address, addr);               // data buffer addr    
                    SL811Write(IntStatus,INT_CLEAR);            // is a LS is on Hub.  
                    SL811Write(EP0Control,cmd);                 // Enable USB transfer and re-arm  
                }                  
   
                //------------------------------------------------  
                // Copy last IN token data pkt from prev transfer  
                // Check if there was data available during the  
                // last data transfer  
                //------------------------------------------------  
                if(bufLen)                                        
                {      
                    SL811BufRead(((dataX&1)?data0:data1), usbstack.buffer, bufLen);  
                    usbstack.buffer += bufLen;                                
                }  
   
                //------------------------------------------------  
                // Terminate on short packets, i.e. remainder!=0  
                // a short packet or empty data packet OR when    
                // requested data len have completed, i.e.wLen=0  
                // For a LOWSPEED device, the 1st device descp,  
                // wPayload is default to 64-byte, LS device will  
                // only send back a max of 8-byte device descp,  
                // and host detect this as a short packet, and    
                // terminate with OUT status stage  
                //------------------------------------------------  
                if(remainder || !usbstack.wLen)  
                    break;  
            }// PID IN                            
        }  
               
        //-------------------------NAK----------------------------  
        if (result & EP0_NAK)                                   // NAK Detected  
        {                                                          
            //if(usbstack.endpoint==0)                            // on ep0 during enumeration of LS device  
            //{                                                   // happen when slave is not fast enough,  
                SL811Write(IntStatus,INT_CLEAR);                // clear interrupt status, need to  
                SL811Write(EP0Control,cmd);                     // re-arm and request for last cmd, IN token  
                        result = 0;                                     // respond to NAK status only  
            //}  
            //else                                                // normal data endpoint, exit now !!! , non-zero ep  
            //    break;                                          // main loop control the interval polling  
        }  
       
        //-----------------------TIMEOUT--------------------------  
        if (result & EP0_TIMEOUT)                               // TIMEOUT Detected  
        {                                                          
            if(usbstack.endpoint==0)                                        // happens when hub enumeration  
            {  
                if(++timeout >= TIMEOUT_RETRY)  
                {      
                    timeout--;  
                    break;                                      // exit on the timeout detected    
                }  
                SL811Write(IntStatus,INT_CLEAR);                // clear interrupt status, need to  
                SL811Write(EP0Control,cmd);                     // re-arm and request for last cmd again  
            }  
            else                                                  
            {                                                   // all other data endpoint, data transfer    
                bFlags.bits.TIMEOUT_ERR = TRUE;                             // failed, set flag to terminate transfer  
                break;                                          // happens when data transfer on a device  
            }                                                   // through the hub  
        }  
   
        //-----------------------STALL----------------------------  
        if (result & EP0_STALL)                                 // STALL detected  
            return TRUE;                                        // for unsupported request.  
                                                                           
        //----------------------OVEFLOW---------------------------  
        if (result & EP0_OVERFLOW)                              // OVERFLOW detected  
            break;  
        //-----------------------ERROR----------------------------  
        //if (result & EP0_ERROR)                                 // ERROR detected  
        //    break;  
    }   // end of While(1)  
     
    if (result & EP0_ACK)   // on ACK transmission  
        return TRUE;        // return OK  
        printf("\rresult 0x%02x",result);
    return FALSE;           // fail transmission  
   
}  
//*****************************************************************************************  
// Control Endpoint 0's USB Data Xfer  
// ep0Xfer, endpoint 0 data transfer  
//*****************************************************************************************  
unsigned char ep0Xfer(void)  
{  
    usbstack.endpoint=0;  
    //----------------------------------------------------  
    // SETUP token with 8-byte request on endpoint 0  
    //----------------------------------------------------  
    usbstack.pid=PID_SETUP;  
    usbstack.wLen=8;  
    if (!usbXfer())
        {       printf("SETUP token error 0x%x \r",PID_SETUP);
                return FALSE;
        }
    usbstack.pid  = PID_IN;  
    //----------------------------------------------------  
    // IN or OUT data stage on endpoint 0      
    //----------------------------------------------------  
    usbstack.wLen=usbstack.setup.wLength;  
    if (usbstack.wLen)                                          // if there are data for transfer  
    {  
        if (usbstack.setup.bmRequest & 0x80)        // host-to-device : IN token  
        {  
            usbstack.pid  = PID_IN;    
               
            if(!usbXfer())
                {       printf("IN token endpoint 0 error 0x%x \r",usbstack.pid);
                        return FALSE;
                }
            usbstack.pid  = PID_OUT;  
        }  
        else                                            // device-to-host : OUT token  
        {
            usbstack.pid  = PID_OUT;  
                   
            if(!usbXfer())
                {       printf("OUT token endpoint 0 error 0x%x \r",usbstack.pid);
                        return FALSE;
                }
            usbstack.pid  = PID_IN;  
        }  
    }  
    DelayMs(10);  
    //----------------------------------------------------  
    // Status stage IN or OUT zero-length data packet  
    //----------------------------------------------------  
    usbstack.wLen=0;  
    if(!usbXfer())
        {       printf("IN/OUT token zero-lenght error 0x%x \r",usbstack.pid);
                return FALSE;
        }
    return TRUE;                                              
}  

unsigned char epBulkSend(unsigned char *pBuffer,unsigned int len)  
{
    usbstack.usbaddr=0x1;  
    usbstack.endpoint=usbstack.epbulkout;  
    usbstack.pid=PID_OUT;  
    usbstack.wPayload=64;  
    usbstack.wLen=len;  
    usbstack.buffer=pBuffer;  
    while(len>0)  
    {  
        if (len > usbstack.wPayload)  
            usbstack.wLen = usbstack.wPayload;  
        else                  
            usbstack.wLen = len;
        disable_interrupt();  
        while(!usbXfer()){
                enable_interrupt();
                puts("epBulkSend ERROR");
            return FALSE;
        }
        enable_interrupt();
        len-=usbstack.wLen;  
        usbstack.buffer=usbstack.buffer+usbstack.wLen;  
    }  
    return TRUE;      
}  
   
unsigned char epBulkRcv(unsigned char *pBuffer,unsigned int len)  
{  
    usbstack.usbaddr=0x1;  
    usbstack.endpoint=usbstack.epbulkin;  
    usbstack.pid=PID_IN;  
    usbstack.wPayload=64;  
    usbstack.wLen=len;  
    usbstack.buffer=pBuffer;
    if(usbstack.wLen)  
    {    
        disable_interrupt();  
        while(!usbXfer()){
                enable_interrupt();
            return FALSE;
        }
        enable_interrupt();    
    }  
    return TRUE;  
}  
   
//*****************************************************************************************  
// Set Device Address :    
//*****************************************************************************************  
unsigned char SetAddress(unsigned char addr)  
{  
    usbstack.usbaddr=0;  
    usbstack.setup.bmRequest=0;  
    usbstack.setup.bRequest=SET_ADDRESS;  
    usbstack.setup.wValue=addr;  
    usbstack.setup.wIndex=0;  
    usbstack.setup.wLength=0;  
    return ep0Xfer();  
}  

//*****************************************************************************************  
// Set Device Configuration :    
//*****************************************************************************************  
unsigned char Set_Configuration(void)  
{  
    usbstack.setup.bmRequest=0;  
    usbstack.setup.bRequest=SET_CONFIG;  
    usbstack.setup.wIndex=0;  
    usbstack.setup.wLength=0;  
    usbstack.buffer=NULL;  
    return ep0Xfer();  
}

//*****************************************************************************************  
// Get Device Descriptor : Device, Configuration, String  
//*****************************************************************************************  
unsigned char GetDesc(void)  
{    
    usbstack.setup.bmRequest=0x80;  
    usbstack.setup.bRequest=GET_DESCRIPTOR;  
    usbstack.setup.wValue=WordSwap(usbstack.setup.wValue);    
    usbstack.wPayload=uDev.wPayLoad[0];  
    return ep0Xfer();  
}  
   
//*****************************************************************************************  
// USB Device Enumeration Process  
// Support 1 confguration and interface #0 and alternate setting #0 only  
// Support up to 1 control endpoint + 4 data endpoint only  
//*****************************************************************************************  
unsigned char EnumUsbDev(BYTE usbaddr)  
{
    unsigned char i;                                    // always reset USB transfer address    
    unsigned char uAddr = 0;                            // for enumeration to Address #0  
    unsigned char epLen;

    //------------------------------------------------  
    // Reset only Slave device attached directly  
    //------------------------------------------------  
    uDev.wPayLoad[0] = 64;  // default 64-byte payload of Endpoint 0, address #0  
    if(usbaddr == 1)        // bus reset for the device attached to SL811HS only  
        USBReset();     // that will always have the USB address = 0x01 (for a hub)  
//        DelayMs(25);

    //------------------------------------------------  
    // Get USB Device Descriptors on EP0 & Addr 0  
    // with default 64-byte payload  
    //------------------------------------------------  

    usbstack.usbaddr=uAddr;  
    usbstack.setup.wValue=DEVICE;  
    usbstack.setup.wIndex=0;  
    usbstack.setup.wLength=18;  
    usbstack.buffer=DBUF;  

    if (!GetDesc())         // and determine the wPayload size  
        return FALSE;                               // get correct wPayload of Endpoint 0  
    uDev.wPayLoad[0]=DBUF[7];   // on current non-zero USB address  
    //------------------------------------------------  
    // Set Slave USB Device Address  
    //------------------------------------------------
        printf("Set Slave USB Device Address 0x%x  \r",usbaddr);
    if (!SetAddress(usbaddr))                       // set to specific USB address  
        return FALSE;                               //  
    uAddr = usbaddr;                                // transfer using this new address  

    //------------------------------------------------  
    // Get USB Device Descriptors on EP0 & Addr X  
    //------------------------------------------------  

    usbstack.usbaddr=uAddr;    
    usbstack.setup.wLength=DBUF[0];    
    usbstack.setup.wValue=DEVICE;  
    usbstack.setup.wIndex=0;      
    usbstack.buffer=DBUF;      
    if (!GetDesc())        
        return FALSE;                               // For this current device:  
    uDev.iMfg  = DBUF[14];
    uDev.iPdt  = DBUF[15];
        uDev.wVID=DBUF[8]+(DBUF[9]<<8);
        uDev.wPID=DBUF[10]+(DBUF[11]<<8);
        printf("VID 0x%x, PID 0x%x MNFG 0x%x PROD 0x%x \r",uDev.wVID,uDev.wPID,uDev.iMfg,uDev.iPdt);

    //------------------------------------------------  
    // Get Slave USB Configuration Descriptors  
    //------------------------------------------------  

    usbstack.usbaddr=uAddr;  
    usbstack.setup.wValue=CONFIGURATION;  
    usbstack.setup.wIndex=0;  
    usbstack.setup.wLength=64;  
    usbstack.buffer=DBUF;      
    if (!GetDesc())
        return FALSE;      

    uDev.bClass     = DBUF[9+5];    // update to class type  
    uDev.bNumOfEPs = (DBUF[9+4] <= MAX_EP) ? DBUF[9+4] : MAX_EP;  
    if(uDev.bClass==8) //mass storage device  
        bFlags.bits.bMassDevice=TRUE;  
    //------------------------------------------------  
    // Set configuration (except for HUB device)  
    //------------------------------------------------  
    usbstack.usbaddr=uAddr;  
    usbstack.setup.wValue=DEVICE;  
                                        // enumerating a FS/LS non-hub device  
        if (!Set_Configuration())       // connected directly to SL811HS  
                return FALSE;  

    //------------------------------------------------  
    // For each slave endpoints, get its attributes  
    // Excluding endpoint0, only data endpoints  
    //------------------------------------------------  

    epLen = 0;  
    for (i=1; i<=uDev.bNumOfEPs; i++)                // For each data endpoint  
    {
        uDev.bEPAddr[i]     = DBUF[9 + 9 + epLen+2];    // Ep address and direction                
        uDev.bAttr[i]       = DBUF[9 + 9 + epLen+3];    // Attribute of Endpoint              
        uDev.wPayLoad[i]    = LSwapINT16(DBUF[9 + 9 + epLen+4],DBUF[9 + 9 + epLen+5]);  // Payload of Endpoint  
        uDev.bInterval[i]   = DBUF[9 + 9 + epLen+6];    // Polling interval  
        uDev.bData1[i] = 0;                     // init data toggle  
        printf("EndPoint 0x%x, attr = 0x%x, \npkt_size = 0x%x, interval = 0x%x \r",uDev.bEPAddr[i],uDev.bAttr[i],uDev.wPayLoad[i],uDev.bInterval[i]);
        epLen += 7;  
        //////////////////////////////  
        if(uDev.bAttr[i]==0x2)     //bulk transfer  
        {
            if(uDev.bEPAddr[i]&0x80)
                usbstack.epbulkin=uDev.bEPAddr[i];
            else  
                usbstack.epbulkout=uDev.bEPAddr[i];
        }
        //////////////////////////////  
    }
        printf("epbulkin = 0x%x epbulkout = 0x%x \r",usbstack.epbulkin,usbstack.epbulkout);
    return TRUE;  
}