⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 msclass.c

📁 基于ADSP-BF535 USB驱动应用程序
💻 C
📖 第 1 页 / 共 2 页
字号:
						case STATE_CSW_SENT:
							//Get ready to receive the next CBW

							//Setup and Arm our out endpoint
							ActivateEndpoint (EP_FOR_OUT_TRANSFERS, USBD_TYP_BULK, BULKEP_MAX_PACKET_SIZE, CBW_LENGTH);
							PrepareOUTEPForXFer (EP_FOR_OUT_TRANSFERS);
							ArmEndpoint (EP_FOR_OUT_TRANSFERS, EP_OUT);
							//Dprintf ("OnInTransferComplete: Will wait for next CBW");
							gCommandStatusState = STATE_WAITFOR_CBW;
							break;
						case STATE_SEND_DATA:
							ShipDataUp ();
							break;
					}
			}
	}



/*------------------------------------------------------------
*	OnOutTransferComplete
*
*	Parameters:  
*		endpointNumber - the endpoint on which the transfer was completed.
*		buffer - data buffer where the data was received
*		numBytesReceived - number of bytes received
*		wasPCAsserted - was the PC(packet complete) asserted when the TC interrup
*			came in. If not, this could be a possible problem???
*
*	Globals Used:
*		gIsTransferActive, gCommandStatusState, gCurrentCBW, gRemainingDataToComeIn
*
*	Description:
*		This routine is called when a transfer is completed on one of the
*		out endpoints. 
*
*	Returns:
*		true to tell the isr to recycle the dma buffer, and setup
*		things for the next transfer, false to tell the isr to
*		free up the dma buffer, and disarm the endpoint.
*
*------------------------------------------------------------*/
bool OnOutTransferComplete (UCHAR endpointNumber, void *buffer, UINT numBytesReceived, bool wasPCAsserted)
	{
		void *pCSWBuffer;
		bool validCBW = false;

		if (endpointNumber != EP_FOR_OUT_TRANSFERS)
			return(false);


		switch (gCommandStatusState)
			{
				case STATE_WAITFOR_CBW:
					//Dprintf ("Received CBW");
					if (numBytesReceived >= CBW_LENGTH)
						if (ExtractCBW (&gCurrentCBW, buffer))
							{
								validCBW = true;
								//Dprintf ("Valid CBW");
								return ProcessCBW (&gCurrentCBW);
							}

					if (!validCBW)
						{
							Dprintf ("Invalid CBW");

							//Need to prepare an error CSW
							StallEndpoint (EP_FOR_IN_TRANSFERS);

							ActivateEndpoint (EP_FOR_IN_TRANSFERS, USBD_TYP_BULK, BULKEP_MAX_PACKET_SIZE, CSW_LENGTH);
							PrepareINEPForXFer (EP_FOR_IN_TRANSFERS, &pCSWBuffer);
							BuildCSW (pCSWBuffer, gCurrentCBW.tag, 0, CSW_STATUS_COMMAND_FAILED);
							ArmEndpoint (EP_FOR_IN_TRANSFERS, EP_IN);
							gCommandStatusState = STATE_CSW_SENT;

							return (false);
						}

					break;
				case STATE_WAITFOR_DATA:
					//Dprintf1 ("More Data Received, remain: %08x", gRemainingDataToComeIn);
					SCSI_ProcessData (buffer, numBytesReceived);
					gRemainingDataToComeIn -= numBytesReceived;
					if (gRemainingDataToComeIn)
						{
							ULONG inThisPass;
							if (gRemainingDataToComeIn < BULKEP_MAX_TRANSFER_SIZE)
								{
									UnprepareEP (EP_FOR_OUT_TRANSFERS);
									ActivateEndpoint (EP_FOR_OUT_TRANSFERS, USBD_TYP_BULK, BULKEP_MAX_PACKET_SIZE, 
										gRemainingDataToComeIn);
									PrepareOUTEPForXFer (EP_FOR_OUT_TRANSFERS);
								}
							return (true);
						}
					else
						{
							gIsTransferActive = false;
							ActivateEndpoint (EP_FOR_IN_TRANSFERS, USBD_TYP_BULK, BULKEP_MAX_PACKET_SIZE, CSW_LENGTH);
							PrepareINEPForXFer (EP_FOR_IN_TRANSFERS, &pCSWBuffer);
							BuildCSW (pCSWBuffer, gCurrentCBW.tag, 0, CSW_STATUS_COMMAND_PASSED);
							ArmEndpoint (EP_FOR_IN_TRANSFERS, EP_IN);
							gCommandStatusState = STATE_CSW_SENT;
							return (false);
						}
					//break;
				default:
					return(false);
					
			}			


		return (false);
		

	}


/*------------------------------------------------------------
*	ProcessCBW
*
*	Parameters:  
*		pCBW - pointer to a vaild CBW
*
*	Globals Used:
*		gCurrentCBW, gRemainingDataToComeIn, gpDataToShipUp, gResidue,
*		gRemainingDataToShipUp, gCommandStatusState
*
*	Description:
*		This routine processes the Command Block Wrapper and decides
*		what is to be done next!
*
*	Returns:
*		true to receive more data, false to not receive more data.
*
*------------------------------------------------------------*/
bool ProcessCBW (PCBW pCBW)
	{
		void *pBuffer;
		void *pCSWBuffer;
		ULONG validDataLen;
		
		if (!IsCBWMeaningful(pCBW))
			{
				/*
				void *pCSWBuffer;
				//Need to prepare an error CSW
				ActivateEndpoint (EP_FOR_IN_TRANSFERS, USBD_TYP_BULK, BULKEP_MAX_PACKET_SIZE, CSW_LENGTH);
				PrepareINEPForXFer (EP_FOR_IN_TRANSFERS, &pCSWBuffer);
				BuildCSW (pCSWBuffer, gCurrentCBW.tag, 0, CSW_STATUS_COMMAND_FAILED);
				ArmEndpoint (EP_FOR_IN_TRANSFERS, EP_IN);
				gCommandStatusState = STATE_CSW_SENT;
				*/
				Dprintf1 ("Unknown SCSI Opcode: %02x", pCBW->wcb[0]);
				StallEndpoint (EP_FOR_IN_TRANSFERS);

				ActivateEndpoint (EP_FOR_IN_TRANSFERS, USBD_TYP_BULK, BULKEP_MAX_PACKET_SIZE, CSW_LENGTH);
				PrepareINEPForXFer (EP_FOR_IN_TRANSFERS, &pCSWBuffer);
				BuildCSW (pCSWBuffer, gCurrentCBW.tag, 0, CSW_STATUS_COMMAND_FAILED);
				ArmEndpoint (EP_FOR_IN_TRANSFERS, EP_IN);
				gCommandStatusState = STATE_CSW_SENT;

				return (false);
			}

		//If we're here the CBW is meaningful, let's do what the command asks us to do!

		//Dprintf1 ("SCSI Opcode: %02x", pCBW->wcb[0]);
		if (SCSI_ProcessCDB (pCBW->wcb, pCBW->wcbLength, pCBW->dataTransferLength, &pBuffer, &validDataLen))
			{
				if (pCBW->dataTransferLength == 0)
					{
						//no data involved, lets sutp the CSW
						ActivateEndpoint (EP_FOR_IN_TRANSFERS, USBD_TYP_BULK, BULKEP_MAX_PACKET_SIZE, CSW_LENGTH);
						PrepareINEPForXFer (EP_FOR_IN_TRANSFERS, &pCSWBuffer);
						BuildCSW (pCSWBuffer, gCurrentCBW.tag, 0, CSW_STATUS_COMMAND_PASSED);
						ArmEndpoint (EP_FOR_IN_TRANSFERS, EP_IN);
						gCommandStatusState = STATE_CSW_SENT;
						return (false);
					}

				//If the direction was device to host - start sending the data back
				if (pCBW->flags & CDW_FLAG_DATA_FROM_DEVICE_TO_HOST)
					{
						gIsTransferActive = true;
						gResidue = pCBW->dataTransferLength - validDataLen;
						gRemainingDataToShipUp = pCBW->dataTransferLength;
						gpDataToShipUp = pBuffer;
						ShipDataUp ();
					}
				else
					{
						gIsTransferActive = true;
						UnprepareEP (EP_FOR_OUT_TRANSFERS);
						//wait for more data
						gCommandStatusState = STATE_WAITFOR_DATA;
						gRemainingDataToComeIn = pCBW->dataTransferLength;
						ActivateEndpoint (EP_FOR_OUT_TRANSFERS, USBD_TYP_BULK, BULKEP_MAX_PACKET_SIZE, 
							(gRemainingDataToComeIn > BULKEP_MAX_TRANSFER_SIZE) ? BULKEP_MAX_TRANSFER_SIZE : gRemainingDataToComeIn);
						PrepareOUTEPForXFer (EP_FOR_OUT_TRANSFERS);
						return (true);
					}

			}
		else
			{
				//Need to prepare an error CSW
				ActivateEndpoint (EP_FOR_IN_TRANSFERS, USBD_TYP_BULK, BULKEP_MAX_PACKET_SIZE, CSW_LENGTH);
				PrepareINEPForXFer (EP_FOR_IN_TRANSFERS, &pCSWBuffer);
				BuildCSW (pCSWBuffer, gCurrentCBW.tag, 0, CSW_STATUS_COMMAND_FAILED);
				ArmEndpoint (EP_FOR_IN_TRANSFERS, EP_IN);
				gCommandStatusState = STATE_CSW_SENT;
			}
		

		return (false);
	}



/*------------------------------------------------------------
*	IsCBWMeaningful
*
*	Parameters:  
*		pCBW - the CBW to check.
*
*	Globals Used:
*		None
*
*	Description:
*		Determines if the provided CBW is meaningful. It
*		depends on the SCSI implementation module to check
*		the command block.
*
*	Returns:
*		true if it is meaningful, false otherwise.
*
*------------------------------------------------------------*/
bool IsCBWMeaningful (PCBW pCBW)
	{
		if (pCBW->lun > MAX_LUN)
			return(false);
		if (pCBW->wcbLength > CBW_WCB_LEN)
			return(false);

		//Check the command opcode
		return SCSI_IsValidCommandBlock (&pCBW->wcb[0], pCBW->wcbLength);
			
	}




/*------------------------------------------------------------
*	ShipDataUp
*
*	Parameters:  
*
*	Globals Used:
*		gRemainingDataToShipUp, gpDataToShipUp
*
*	Description:
*		This routine takes care of preparing the IN endpoint
*		to send data back to the host. It uses gRemainingDataToShipUp
*		and gpDataToShipUp to decide how much data to ship up. If there
*		is no data to ship up, it fills in a CSW and sets the endpoint
*		to return the CSW.
*		
*
*	Returns:
*		Nothing.
*
*------------------------------------------------------------*/
void ShipDataUp (void)
	{
		ULONG inThisPass;
		void *pBuffer, *pCSWBuffer;

		//Dprintf1 ("ShipDataUp: %d", gRemainingDataToShipUp);

		if (gRemainingDataToShipUp)
			{
				inThisPass = (gRemainingDataToShipUp > BULKEP_MAX_TRANSFER_SIZE) ? BULKEP_MAX_TRANSFER_SIZE : gRemainingDataToShipUp;
				ActivateEndpoint (EP_FOR_IN_TRANSFERS, USBD_TYP_BULK, BULKEP_MAX_PACKET_SIZE, inThisPass);
				PrepareINEPForXFer (EP_FOR_IN_TRANSFERS, &pBuffer);
				memcpy (pBuffer, gpDataToShipUp, inThisPass);
				gpDataToShipUp = ((PUCHAR)gpDataToShipUp + inThisPass);
				gRemainingDataToShipUp -= inThisPass;
				ArmEndpoint (EP_FOR_IN_TRANSFERS, EP_IN);
				gCommandStatusState = STATE_SEND_DATA;
			}
		else
			{
				gIsTransferActive = false;
				//All data has been sent, so now send the CSW
				ActivateEndpoint (EP_FOR_IN_TRANSFERS, USBD_TYP_BULK, BULKEP_MAX_PACKET_SIZE, CSW_LENGTH);
				PrepareINEPForXFer (EP_FOR_IN_TRANSFERS, &pCSWBuffer);
				BuildCSW (pCSWBuffer, gCurrentCBW.tag, 0, CSW_STATUS_COMMAND_PASSED);
				ArmEndpoint (EP_FOR_IN_TRANSFERS, EP_IN);
				gCommandStatusState = STATE_CSW_SENT;
			}
	}



/*------------------------------------------------------------
*	OnNAKSent
*
*	Parameters:  
*		endpointNumber - endpoint where the NAK was sent.
*
*	Globals Used:
*		gPrepareReport
*
*	Description:
*		This routine is called when the device has sent a NAK in response
*		to an IN or OUT request while the DMA buffer for that endpoint
*		has been emptied. Please note that this will only be called in
*		response to an "expected" direction request - IN request for
*		endpoints setup as IN endpoints and OUT request for endpoints
*		setup as OUT endpoints. 
*
*	Returns:
*		Nothing
*
*------------------------------------------------------------*/
void OnNAKSent (UCHAR endpointNumber)
	{
	}




/*------------------------------------------------------------
*	OnSuspend
*
*	Parameters:  
*
*	Globals Used:
*		gpOnSuspend, gIsTransferActive
*
*	Description:
*		This routine will be called when USBDriver detects a
*		suspend condition. Currently, it quites the AC97 and forwards
*		the call to the client!
*
*	Returns:
*		Nothing.
*
*------------------------------------------------------------*/
void OnSuspend (void)
	{
		gIsTransferActive = false;
		if (gpOnSuspend)
			(gpOnSuspend)();
	}



/*------------------------------------------------------------
*	OnResume
*
*	Parameters:  
*
*	Globals Used:
*		gpOnResume, gIsDeviceConfigured
*
*	Description:
*		This routine will be called when the USBDriver detects that
*		the bus is out of suspend. Currently, it simply forwards
*		the call to the client!
*
*	Returns:
*		Nothing.
*
*------------------------------------------------------------*/
void OnResume (void)
	{
		gIsDeviceConfigured = false;
		MSReset ();
		if (gpOnResume)
			(gpOnResume) ();
	}


/*------------------------------------------------------------
*	OnSOF
*
*	Parameters:  None.
*
*	Globals Used:
*
*	Description:
*		This routine will be called when the USBDriver receives an SOF
*		interrupt. It is mainly used to see if the transfers have timed out.
*
*	Returns:
*		Nothing.
*
*------------------------------------------------------------*/
void OnSOF (void)
	{

	}


/*------------------------------------------------------------
*	OnReset
*
*	Parameters:  
*
*	Globals Used:
*		gpOnReset, gIsDeviceConfigured, gIsTransferActive
*
*	Description:
*		This routine will be called when the USBDriver detects reset
*		signalling on the bus. Currently, it quiets the codec and forwards
*		the call to the client!
*
*	Returns:
*		Nothing.
*
*------------------------------------------------------------*/
void OnReset (void)
	{
		gIsDeviceConfigured = false;
		gIsTransferActive = false;
		MSReset ();
		if (gpOnReset)
			(gpOnReset)();
	}



/*------------------------------------------------------------
*	ExtractCBW
*
*	Parameters:  
*		pCBW - pointer to a CBW to fill.
*		pBuffer - pointer to a buffer that contains data for the CBW.
*
*	Globals Used:
*		None
*
*	Description:
*		Extracts fields for the CBW from a data buffer.
*
*	Returns:
*		true if the signature matches, false otherwise.
*
*------------------------------------------------------------*/
bool ExtractCBW (PCBW pCBW, UCHAR *pBuffer)
	{
		pCBW->signature = *(PULONG)pBuffer;
		pCBW->tag = *(PULONG)(pBuffer+CBW_TAG_OFFSET);
		pCBW->dataTransferLength = *(PULONG)(pBuffer+CBW_DATA_TRANSFER_LENGTH_OFFSET);
		pCBW->flags = *(PUCHAR)(pBuffer+CBW_FLAGS_OFFSET);
		pCBW->lun = *(PUCHAR)(pBuffer+CBW_LUN_OFFSET);
		pCBW->wcbLength = *(PUCHAR)(pBuffer+CBW_WCBLENGTH_OFFSET);
		memcpy (&pCBW->wcb[0], pBuffer+CBW_WCB_OFFSET, CBW_WCB_LEN);
		return (pCBW->signature == CBW_SIGNATURE);
	}



/*------------------------------------------------------------
*	BuildCSW
*
*	Parameters:  
*		pBuffer - points to a buffer where the CSW must be built.
*		tag - tag for the CSW
*		dataResidue - for the CSW
*		status - for the CSW
*
*	Globals Used:
*		None
*
*	Description:
*		Builds a CBW (buffer) from provided parameters.
*
*	Returns:
*		Nothing.
*
*------------------------------------------------------------*/
void BuildCSW (UCHAR *pBuffer, ULONG tag, ULONG dataResidue, UCHAR status)
	{
		*(PULONG)pBuffer = CSW_SIGNATURE;
		*(PULONG)(pBuffer + CSW_TAG_OFFSET) = tag;
		*(PULONG)(pBuffer + CSW_DATA_RESIDUE_OFFSET) = dataResidue;
		*(pBuffer + CSW_STATUS_OFFSET) = status;
	}


/*----------------------------------------------------------------------------------
* $Log: MSClass.c,v $
* Revision 1.4  2003/03/03 22:36:43  Devendra
* - Added documentation.
* - Some code cleanup.
*
* Revision 1.3  2003/03/03 21:38:44  Devendra
* - Changed the bulk transfer mechainsm to make it more efficient by using transfer lengths that are the same size as the disk block sizes.
*
* Revision 1.2  2003/03/03 21:26:41  Devendra
* - BugFix: Writes were not working correctly.
* - Changed to using the SDRAM for disk data storage.
* - Increased the disk capacity to 16MB.
* - Added disk init. routine to make it look like a FAT formatted 16MB disk.
*
* Revision 1.1  2003/03/03 18:13:45  Devendra
* First Rev, the device enumerates as Mass Storage Class
*
*
*---------------------------------------------------------------------------------*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -