Ejemplo n.º 1
0
/* major part of this function borrowed from code shared by Richard Ibbotson    */
byte USB::outTransfer( byte addr, byte ep, unsigned int nbytes, char* data, unsigned int nak_limit )
{
    byte rcode, retry_count;
    char* data_p = data;   //local copy of the data pointer
    unsigned int bytes_tosend, nak_count;
    unsigned int bytes_left = nbytes;
    byte maxpktsize = devtable[ addr ].epinfo[ ep ].MaxPktSize;
    unsigned long timeout = millis() + USB_XFER_TIMEOUT;

    if (!maxpktsize) { //todo: move this check close to epinfo init. Make it 1< pktsize <64
        return 0xFE;
    }

    regWr( rHCTL, devtable[ addr ].epinfo[ ep ].sndToggle );    //set toggle value
    while( bytes_left ) {
        retry_count = 0;
        nak_count = 0;
        bytes_tosend = ( bytes_left >= maxpktsize ) ? maxpktsize : bytes_left;
        bytesWr( rSNDFIFO, bytes_tosend, data_p );      //filling output FIFO
        regWr( rSNDBC, bytes_tosend );                  //set number of bytes
        regWr( rHXFR, ( tokOUT | ep ));                 //dispatch packet
        while(!(regRd( rHIRQ ) & bmHXFRDNIRQ ));        //wait for the completion IRQ
        regWr( rHIRQ, bmHXFRDNIRQ );                    //clear IRQ
        rcode = ( regRd( rHRSL ) & 0x0f );
        while( rcode && ( timeout > millis())) {
            switch( rcode ) {
            case hrNAK:
                nak_count++;
                if( nak_limit && ( nak_count == USB_NAK_LIMIT )) {
                    return( rcode);                                   //return NAK
                }
                break;
            case hrTIMEOUT:
                retry_count++;
                if( retry_count == USB_RETRY_LIMIT ) {
                    return( rcode );    //return TIMEOUT
                }
                break;
            default:
                return( rcode );
            }//switch( rcode...
            /* process NAK according to Host out NAK bug */
            regWr( rSNDBC, 0 );
            regWr( rSNDFIFO, *data_p );
            regWr( rSNDBC, bytes_tosend );
            regWr( rHXFR, ( tokOUT | ep ));                 //dispatch packet
            while(!(regRd( rHIRQ ) & bmHXFRDNIRQ ));        //wait for the completion IRQ
            regWr( rHIRQ, bmHXFRDNIRQ );                    //clear IRQ
            rcode = ( regRd( rHRSL ) & 0x0f );
        }//while( rcode && ....
        bytes_left -= bytes_tosend;
        data_p += bytes_tosend;
    }//while( bytes_left...
    devtable[ addr ].epinfo[ ep ].sndToggle = ( regRd( rHRSL ) & bmSNDTOGRD ) ? bmSNDTOG1 : bmSNDTOG0;  //update toggle
    return( rcode );    //should be 0 in all cases
}
Ejemplo n.º 2
0
/* 01-0f    =   non-zero HRSLT  */
byte USB::ctrlReq( byte addr, byte ep, byte bmReqType, byte bRequest, byte wValLo, byte wValHi, unsigned int wInd, unsigned int nbytes, char* dataptr, unsigned int nak_limit )
{
    boolean direction = false;     //request direction, IN or OUT
    byte rcode;
    SETUP_PKT setup_pkt;

    regWr( rPERADDR, addr );                    //set peripheral address
    if( bmReqType & 0x80 ) {
        direction = true;                       //determine request direction
    }
    /* fill in setup packet */
    setup_pkt.ReqType_u.bmRequestType = bmReqType;
    setup_pkt.bRequest = bRequest;
    setup_pkt.wVal_u.wValueLo = wValLo;
    setup_pkt.wVal_u.wValueHi = wValHi;
    setup_pkt.wIndex = wInd;
    setup_pkt.wLength = nbytes;
    bytesWr( rSUDFIFO, 8, ( char *)&setup_pkt );    //transfer to setup packet FIFO
    rcode = dispatchPkt( tokSETUP, ep, nak_limit );            //dispatch packet
    //Serial.println("Setup packet");   //DEBUG
    if( rcode ) {                                   //return HRSLT if not zero
        Serial.print("Setup packet error: ");
        Serial.print( rcode, HEX );
        return( rcode );
    }
    //Serial.println( direction, HEX );
    if( dataptr != NULL ) {                         //data stage, if present
        rcode = ctrlData( addr, ep, nbytes, dataptr, direction );
    }
    if( rcode ) {   //return error
        Serial.print("Data packet error: ");
        Serial.print( rcode, HEX );
        return( rcode );
    }
    rcode = ctrlStatus( ep, direction );                //status stage
    return( rcode );
}
Ejemplo n.º 3
0
uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data) {
        uint8_t rcode = hrSUCCESS, retry_count;
        uint8_t *data_p = data; //local copy of the data pointer
        uint16_t bytes_tosend, nak_count;
        uint16_t bytes_left = nbytes;

        uint8_t maxpktsize = pep->maxPktSize;

        if(maxpktsize < 1 || maxpktsize > 64)
                return USB_ERROR_INVALID_MAX_PKT_SIZE;

        unsigned long timeout = millis() + USB_XFER_TIMEOUT;

        regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value

        while(bytes_left) {
                retry_count = 0;
                nak_count = 0;
                bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left;
                bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO
                regWr(rSNDBC, bytes_tosend); //set number of bytes
                regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
                while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
                regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
                rcode = (regRd(rHRSL) & 0x0f);

                while(rcode && (timeout > millis())) {
                        switch(rcode) {
                                case hrNAK:
                                        nak_count++;
                                        if(nak_limit && (nak_count == nak_limit))
                                                goto breakout;
                                        //return ( rcode);
                                        break;
                                case hrTIMEOUT:
                                        retry_count++;
                                        if(retry_count == USB_RETRY_LIMIT)
                                                goto breakout;
                                        //return ( rcode);
                                        break;
                                case hrTOGERR:
                                        // yes, we flip it wrong here so that next time it is actually correct!
                                        pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
                                        regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
                                        break;
                                default:
                                        goto breakout;
                        }//switch( rcode

                        /* process NAK according to Host out NAK bug */
                        regWr(rSNDBC, 0);
                        regWr(rSNDFIFO, *data_p);
                        regWr(rSNDBC, bytes_tosend);
                        regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
                        while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
                        regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
                        rcode = (regRd(rHRSL) & 0x0f);
                }//while( rcode && ....
                bytes_left -= bytes_tosend;
                data_p += bytes_tosend;
        }//while( bytes_left...
breakout:

        pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0;  //update toggle
        return ( rcode); //should be 0 in all cases
}
Ejemplo n.º 4
0
/* 01-0f    =   non-zero HRSLT  */
uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
        uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p) {
        bool direction = false; //request direction, IN or OUT
        uint8_t rcode;
        SETUP_PKT setup_pkt;

        EpInfo *pep = NULL;
        uint16_t nak_limit = 0;

        rcode = SetAddress(addr, ep, &pep, nak_limit);

        if(rcode)
                return rcode;

        direction = ((bmReqType & 0x80) > 0);

        /* fill in setup packet */
        setup_pkt.ReqType_u.bmRequestType = bmReqType;
        setup_pkt.bRequest = bRequest;
        setup_pkt.wVal_u.wValueLo = wValLo;
        setup_pkt.wVal_u.wValueHi = wValHi;
        setup_pkt.wIndex = wInd;
        setup_pkt.wLength = total;

        bytesWr(rSUDFIFO, 8, (uint8_t*) & setup_pkt); //transfer to setup packet FIFO

        rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet

        if(rcode) //return HRSLT if not zero
                return ( rcode);

        if(dataptr != NULL) //data stage, if present
        {
                if(direction) //IN transfer
                {
                        uint16_t left = total;

                        pep->bmRcvToggle = 1; //bmRCVTOG1;

                        while(left) {
                                // Bytes read into buffer
                                uint16_t read = nbytes;
                                //uint16_t read = (left<nbytes) ? left : nbytes;

                                rcode = InTransfer(pep, nak_limit, &read, dataptr);
                                if(rcode == hrTOGERR) {
                                        // yes, we flip it wrong here so that next time it is actually correct!
                                        pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
                                        continue;
                                }

                                if(rcode)
                                        return rcode;

                                // Invoke callback function if inTransfer completed successfully and callback function pointer is specified
                                if(!rcode && p)
                                        ((USBReadParser*)p)->Parse(read, dataptr, total - left);

                                left -= read;

                                if(read < nbytes)
                                        break;
                        }
                } else //OUT transfer
                {
                        pep->bmSndToggle = 1; //bmSNDTOG1;
                        rcode = OutTransfer(pep, nak_limit, nbytes, dataptr);
                }
                if(rcode) //return error
                        return ( rcode);
        }
        // Status stage
        return dispatchPkt((direction) ? tokOUTHS : tokINHS, ep, nak_limit); //GET if direction
}