Receiving Data from the USB Host

22 Mar

Receiving Data from the USB Host
If the data-transport phase is host-to-device, firmware calls the MSDDataOut function to get data received from the host.

void MSDDataOut(void)
{
// To enable receiving data, give ownership of the endpoint’s buffer to the SIE.
mUSBBufferReady(MSD_BD_OUT);
// Service USB interrupts. (See Microchip’s Framework firmware for details.)
USBDriverService();
// Wait until the SIE has returned ownership of the endpoint buffer to the CPU,
// indicating that data was received.
while (mMSDRxIsBusy())
{
USBDriverService();
}
// Subtract the number of received bytes from dCBWDataTransferLength in the CBW.
gblCBW.dCBWDataTransferLength -= MSD_BD_OUT.Cnt;
// Subtract the number of received bytes from dCSWDataResidue in the CSW.
msd_csw.dCSWDataResidue -= MSD_BD_OUT.Cnt;
// For the next transaction, set the OUT endpoint’s count to the endpoint size.
MSD_BD_OUT.Cnt = MSD_OUT_EP_SIZE;
// Increment the OUT endpoint’s address by endpoint-size bytes
// in case there is more data to receive.
MSD_BD_OUT.ADR += MSD_OUT_EP_SIZE;
}

Sending the CSW
Firmware calls the SendCSW function after completing the command- transport and data-transport (if required) phases of a command. The function places the CSW in the IN endpoint’s buffer and transfers ownership of the buffer descriptor to the SIE.

void SendCSW(void)
{
// Wait until the CPU has ownership of the endpoint’s buffer descriptor.
while (mMSDTxIsBusy())
{
// Service USB interrupts. See Microchip’s Framework firmware for details.
USBDriverService();
}
// Set the IN endpoint’s address registers to the CSW’s address.
MSD_BD_IN.ADR = (byte*)&msd_csw;
// Set the IN endpoint’s count to the CSW’s size.
MSD_BD_IN.Cnt = MSD_CSW_SIZE;
// To enable sending the CSW, give ownership of the endpoint descriptor to the SIE.
mUSBBufferReady(MSD_BD_IN);
// Service USB interrupts.
USBDriverService();
// Prepare to receive another CBW.
// Set the OUT endpoint’s count to the size of a CBW.
MSD_BD_OUT.Cnt = sizeof(msd_cbw);
// Set the OUT endpoint’s buffer descriptor’s address to the location that will store
// the received CBW.
MSD_BD_OUT.ADR = (byte*)&msd_cbw;
// The next bulk OUT data from the host should be a CBW.
MSD_State = MSD_WAIT;
}

Managing Transfers
The ProcessIO function manages transfers on the bulk endpoints. The function implements a state machine that determines what to do depending on the value of MSD_State. The function calls the MSDCommandHandler function in Chapter 6 to decode and respond to command blocks in the CBW.

void ProcessIO(void)
{
byte i;
dword size;
// Is the bulk IN endpoint sending data to the host?
if (MSD_State == MSD_DATA_IN) {
// Has all of the data been sent?
if (gblCBW.dCBWDataTransferLength == 0)
{
// Prepare to send the CSW.
SendCSW();
}
else
{
// Prepare to send data.
MSDDataIn();
}
return;
} // End: sending data to host.

// Is the bulk OUT endpoint receiving data from the host?
if (MSD_State == MSD_DATA_OUT) {
// Has all of the data been received?
if (gblCBW.dCBWDataTransferLength == 0) {
// If dCSWDataResidue isn’t zero, the quantity of received data
// doesn’t match the quantity expected.
if ((msd_csw.bCSWStatus == 0×00) && (msd_csw.dCSWDataResidue != 0))
// Set bCSWStatus to phase error (02h).
msd_csw.bCSWStatus = 0×02;
// Prepare to send the CSW.
SendCSW();
}
return;
} // End: receiving data from the host
// If the CPU owns the OUT endpoint’s buffer descriptor,
// was the device waiting for a CBW?
if ((MSD_BD_OUT.Stat.UOWN == _UCPU) && (MSD_State == MSD_WAIT))
{
// Copy the received CBW into the gblCBW structure.
gblCBW.dCBWSignature = msd_cbw.dCBWSignature;
gblCBW.dCBWTag = msd_cbw.dCBWTag;
gblCBW.dCBWDataTransferLength = msd_cbw.dCBWDataTransferLength;
gblCBW.bCBWFlags = msd_cbw.bCBWFlags;
gblCBW.bCBWLUN = msd_cbw.bCBWLUN;
gblCBW.bCBWCBLength = msd_cbw.bCBWCBLength;
for (i = 0; i < msd_cbw.bCBWCBLength; i++)
gblCBW.CBWCB[i] = msd_cbw.CBWCB[i];

// Save the size of the CBW.
gblCBWLength = MSD_BD_OUT.Cnt;
if (IsValidCBW()) {
if (IsMeaningfulCBW()) {
// The CBW is valid and meaningful.
// Set fields in the CSW.
PrepareCSWData();
// Is the data-transport phase device to host?
if (gblCBW.bCBWFlags == 0×80)
// Prepare to send data.
MSD_State=MSD_DATA_IN;
// Is the data-transport phase host to device?
else if (gblCBW.bCBWFlags == 0×00) {
// Prepare to read received data in msd_buffer.
MSD_BD_OUT.Cnt = MSD_OUT_EP_SIZE;
MSD_BD_OUT.ADR = (byte*)&msd_buffer[0];
MSD_State = MSD_DATA_OUT;
}
// Decode and process the received command block.
MSDCommandHandler();
}
}
// To enable receiving data,
// give ownership of the endpoint’s buffer descriptor to the SIE.
mUSBBufferReady(MSD_BD_OUT);

// Service USB interrupts. (See Microchip’s Framework firmware for details.)
USBDriverService();
} // End received CBW.
}


Random Posts

No comments yet

Leave a Reply

You must be logged in to post a comment.