Example #1
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 #2
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;
}