Example #1
0
/**
 * For driver use only.
 *
 * @return 0 if successful
 */
uint8_t BulkOnly::ResetRecovery() {
        Notify(PSTR("\r\nResetRecovery\r\n"), 0x80);
        Notify(PSTR("-----------------\r\n"), 0x80);

        delay(6);
        Reset();
        delay(6);
        ClearEpHalt(epDataInIndex);
        delay(6);
        bLastUsbError = ClearEpHalt(epDataOutIndex);
        delay(6);
        return bLastUsbError;
}
Example #2
0
/**
 * For driver use only.
 *
 * @param error
 * @param index
 * @return
 */
uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
    uint8_t count = 3;

    bLastUsbError = error;
    //if (error)
    //ClearEpHalt(index);
    while (error && count) {
        if (error != hrSUCCESS) {
            ErrorMessage<uint8_t > (PSTR("USB Error"), error);
            ErrorMessage<uint8_t > (PSTR("Index"), index);
        }
        switch (error) {
        // case hrWRONGPID:
        case hrSUCCESS:
            return MASS_ERR_SUCCESS;
        case hrBUSY:
            // SIE is busy, just hang out and try again.
            return MASS_ERR_UNIT_BUSY;
        case hrTIMEOUT:
        case hrJERR:
            return MASS_ERR_DEVICE_DISCONNECTED;
        case hrSTALL:
            if (index == 0)
                return MASS_ERR_STALL;
            ClearEpHalt(index);
            if (index != epDataInIndex)
                return MASS_ERR_WRITE_STALL;
            return MASS_ERR_STALL;

        case hrNAK:
            if (index == 0)
                return MASS_ERR_UNIT_BUSY;
            return MASS_ERR_UNIT_BUSY;

        case hrTOGERR:
            // Handle a very super rare corner case, where toggles become de-synched.
            // I have only ran into one device that has this firmware bug, and this is
            // the only clean way to get back into sync with the buggy device firmware.
            //   --AJK
            if (bAddress && bConfNum) {
                error = pUsb->setConf(bAddress, 0, bConfNum);

                if (error)
                    break;
            }
            return MASS_ERR_SUCCESS;
        default:
            ErrorMessage<uint8_t > (PSTR("\r\nUSB"), error);
            return MASS_ERR_GENERAL_USB_ERROR;
        }
        count--;
    } // while

    return ((error && !count) ? MASS_ERR_GENERAL_USB_ERROR : MASS_ERR_SUCCESS);
}
Example #3
0
uint8_t BulkOnly::ResetRecovery()
{
	bLastUsbError = Reset();

	if (bLastUsbError) 
		return bLastUsbError;

	delay(6);

	bLastUsbError = ClearEpHalt(epDataInIndex);

	if (bLastUsbError) 
		return bLastUsbError;

	delay(6);

	bLastUsbError = ClearEpHalt(epDataOutIndex);

	delay(6);

	return bLastUsbError;
}
Example #4
0
uint8_t BulkOnly::GetMaxLUN(uint8_t *plun)
{
	uint8_t cnt = 3;

	bLastUsbError = pUsb->ctrlReq( bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, NULL ); 
	
	delay(10);
	//Serial.println(F("bLastUsbError: "));
	//Serial.println(bLastUsbError);

	if (bLastUsbError == hrSTALL)
	{
		*plun = 0;
		bLastUsbError = ClearEpHalt(epDataInIndex);
		return MASS_ERR_SUCCESS;
	}
	if (bLastUsbError == hrJERR)
		return MASS_ERR_DEVICE_DISCONNECTED;
	else if (bLastUsbError)
		return MASS_ERR_GENERAL_USB_ERROR;
	return MASS_ERR_SUCCESS;
}
Example #5
0
uint8_t BulkOnly::HandleUsbError(uint8_t index)
{
	uint8_t count = 3;

	while (bLastUsbError && count)
	{
		switch (bLastUsbError)
		{
		case hrSUCCESS:
			return MASS_ERR_SUCCESS;
		case hrJERR: 
			bLastUsbError = hrSUCCESS;
			return MASS_ERR_DEVICE_DISCONNECTED;
		case hrSTALL:
			bLastUsbError = ClearEpHalt(index);
			break;
		default:
			return MASS_ERR_GENERAL_USB_ERROR;
		}
		count --;
	} // while
	
	return MASS_ERR_SUCCESS;
}
Example #6
0
/**
 * For driver use only.
 *
 * @param pcbw
 * @param buf_size
 * @param buf
 * @param flags
 * @return
 */
uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf
#if MS_WANT_PARSER
        , uint8_t flags
#endif
        ) {

#if MS_WANT_PARSER
        uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength;
        printf("Transfersize %i\r\n", bytes);
        delay(1000);

        bool callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK;
#else
        uint16_t bytes = buf_size;
#endif
        bool write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN;
        uint8_t ret = 0;
        uint8_t usberr;
        CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles.
        SetCurLUN(pcbw->bmCBWLUN);
        ErrorMessage<uint32_t > (PSTR("CBW.dCBWTag"), pcbw->dCBWTag);

        while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1);

        ret = HandleUsbError(usberr, epDataOutIndex);
        //ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex);
        if(ret) {
                ErrorMessage<uint8_t > (PSTR("============================ CBW"), ret);
        } else {
                if(bytes) {
                        if(!write) {
#if MS_WANT_PARSER
                                if(callback) {
                                        uint8_t rbuf[bytes];
                                        while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1);
                                        if(usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0);
                                } else {
#endif
                                        while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
#if MS_WANT_PARSER

                                }
#endif
                                ret = HandleUsbError(usberr, epDataInIndex);
                        } else {
                                while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
                                ret = HandleUsbError(usberr, epDataOutIndex);
                        }
                        if(ret) {
                                ErrorMessage<uint8_t > (PSTR("============================ DAT"), ret);
                        }
                }
        }

        {
                bytes = sizeof (CommandStatusWrapper);
                int tries = 2;
                while(tries--) {
                        while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1);
                        if(!usberr) break;
                        ClearEpHalt(epDataInIndex);
                        if(tries) ResetRecovery();
                }
                if(!ret) {
                        Notify(PSTR("CBW:\t\tOK\r\n"), 0x80);
                        Notify(PSTR("Data Stage:\tOK\r\n"), 0x80);
                } else {
                        // Throw away csw, IT IS NOT OF ANY USE.
                        ResetRecovery();
                        return ret;
                }
                ret = HandleUsbError(usberr, epDataInIndex);
                if(ret) {
                        ErrorMessage<uint8_t > (PSTR("============================ CSW"), ret);
                }
                if(usberr == hrSUCCESS) {
                        if(IsValidCSW(&csw, pcbw)) {
                                //ErrorMessage<uint32_t > (PSTR("CSW.dCBWTag"), csw.dCSWTag);
                                //ErrorMessage<uint8_t > (PSTR("bCSWStatus"), csw.bCSWStatus);
                                //ErrorMessage<uint32_t > (PSTR("dCSWDataResidue"), csw.dCSWDataResidue);
                                Notify(PSTR("CSW:\t\tOK\r\n\r\n"), 0x80);
                                return csw.bCSWStatus;
                        } else {
                                // NOTE! Sometimes this is caused by the reported residue being wrong.
                                // Get a different device. It isn't compliant, and should have never passed Q&A.
                                // I own one... 05e3:0701 Genesys Logic, Inc. USB 2.0 IDE Adapter.
                                // Other devices that exhibit this behavior exist in the wild too.
                                // Be sure to check quirks in the Linux source code before reporting a bug. --xxxajk
                                Notify(PSTR("Invalid CSW\r\n"), 0x80);
                                ResetRecovery();
                                //return MASS_ERR_SUCCESS;
                                return MASS_ERR_INVALID_CSW;
                        }
                }
        }
        return ret;
}
Example #7
0
uint8_t BulkOnly::Transaction(CommandBlockWrapper *cbw, uint16_t size, void *buf, uint8_t flags)
{
	uint16_t read;
	{
		bLastUsbError = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof(CommandBlockWrapper), (uint8_t*)cbw);

		uint8_t ret = HandleUsbError(epDataOutIndex);

		if (ret)
		{
			ErrorMessage<uint8_t>(PSTR("CBW"), ret);
			return ret;
		}
	}

	if (size && buf)
	{
		read = size;

		if (cbw->bmCBWFlags & MASS_CMD_DIR_IN)
		{
			if ((flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK)
			{
				const uint8_t	bufSize = 64;
				uint16_t		total	= size;
				uint16_t		count	= 0;
				uint8_t			rbuf[bufSize];

				read = bufSize;

				while(count < total && 
					((bLastUsbError = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, (uint8_t*)rbuf)) == hrSUCCESS)
					)
				{
					((USBReadParser*)buf)->Parse(read, rbuf, count);

					count += read;
					read = bufSize;
				}

				if (bLastUsbError == hrSTALL)
					bLastUsbError = ClearEpHalt(epDataInIndex);

				if (bLastUsbError)
				{
					ErrorMessage<uint8_t>(PSTR("RDR"), bLastUsbError);
					return MASS_ERR_GENERAL_USB_ERROR;
				}
			} // if ((flags & 1) == 1)
			else
				bLastUsbError = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, (uint8_t*)buf);
		} // if (cbw->bmCBWFlags & MASS_CMD_DIR_IN)

		else if (cbw->bmCBWFlags & MASS_CMD_DIR_OUT)
			bLastUsbError = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, read, (uint8_t*)buf);
	}

	uint8_t ret = HandleUsbError((cbw->bmCBWFlags & MASS_CMD_DIR_IN) ? epDataInIndex : epDataOutIndex);

	if (ret)
	{
		ErrorMessage<uint8_t>(PSTR("RSP"), ret);
		return MASS_ERR_GENERAL_USB_ERROR;
	}
	{
		CommandStatusWrapper	csw;
		read = sizeof(CommandStatusWrapper);

		bLastUsbError = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, (uint8_t*)&csw);

		uint8_t ret = HandleUsbError(epDataInIndex);

		if (ret)
		{
			ErrorMessage<uint8_t>(PSTR("CSW"), ret);
			return ret;
		}
		//if (csw.bCSWStatus == MASS_ERR_PHASE_ERROR)
		//	bLastUsbError = ResetRecovery();

		return csw.bCSWStatus;
	}
	//return MASS_ERR_SUCCESS;
}