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

📄 msclass.c

📁 基于ADSP-BF535 USB驱动应用程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*----------------------------------------------------------------------------------
*
* COPYRIGHT (c) 2001 by Singing Electrons, Inc. All rights reserved.
*
*
* Module Name			: C:\se\adi\hidclass\Source\HidClass.c
*
* Description			: The HID Class implementation - contains routines that implment the HID Class device
*
*
* Revision History	: At bottom of the file.
*
*---------------------------------------------------------------------------------*/

/** include files **/
#include <sys/exception.h>
#include <sys/excause.h>
#include <defBF535.h>
#include "dtype.h"
#include "usb.h"
#include "usbdriver.h"
#include "msclass.h"
#include "dprintf.h"
#include "scsi.h"

/** local definitions **/

typedef enum {
	STATE_IDLE = 0,
	STATE_WAITFOR_CBW,
	STATE_WAITFOR_DATA,
	STATE_SEND_DATA,
	STATE_EP_FOR_IN_STALLED,
	STATE_CSW_SENT
}COMMAND_STATUS_STATE;


typedef struct tagCBW{
	ULONG signature;
	ULONG tag;
	ULONG dataTransferLength;
	UCHAR flags;
	UCHAR lun;
	UCHAR wcbLength;
	UCHAR wcb[CBW_WCB_LEN];
}CBW, *PCBW;

typedef struct tagCSW{
	ULONG signature;
	ULONG tag;
	ULONG dataResidue;
	UCHAR status;
}CSW, *PCSW;

/* default settings */
#define CONTROL_PIPE_MAX_TRANSFER_LENGTH 64


#define INTERFACE_FOR_BULKONLY 0
#define ALTSETTING_FOR_BULKONLY 0

#define BULKEP_MAX_PACKET_SIZE 64
#define BULKEP_MAX_TRANSFER_SIZE 512

#define EP_FOR_IN_TRANSFERS EP1
#define EP_FOR_OUT_TRANSFERS EP2

#define MAX_LUN 0

#include "descriptors.h"



/** external functions **/

/** external data **/

/** internal functions **/

/** public data **/
bool gIsTransferActive;

/** private data **/
static PSUSPENDPROC gpOnSuspend;
static PRESUMEPROC gpOnResume;
static PRESETPROC gpOnReset;
static bool gIsDeviceConfigured = false;

COMMAND_STATUS_STATE  gCommandStatusState;
CBW gCurrentCBW;

ULONG gRemainingDataToComeIn;
ULONG gRemainingDataToShipUp;
ULONG gResidue;
void *gpDataToShipUp;

/** public functions **/

/** private functions **/
bool ProcessCBW (PCBW pCBW);
bool IsCBWMeaningful (PCBW pCBW);
void ShipDataUp (void);
bool ExtractCBW (PCBW pCBW, UCHAR *pBuffer);
void BuildCSW (UCHAR *pBuffer, ULONG tag, ULONG dataResidue, UCHAR status);

/** callback functions **/
static bool OnSetupRequest (UCHAR endpointNumber, PUSB_SETUP_DATA pSetupData, void *buffer, 
	PUINT pNumBytesToTransfer);
static bool OnGetDeviceDescriptor (void *buffer, PUINT pNumBytesToTransfer);
static bool OnGetConfigDescriptor (void *buffer, PUINT pNumBytesToTransfer);
static bool OnGetStringDescriptor (UCHAR stringIndex, USHORT langID, void *buffer, PUINT pNumBytesToTransfer);
static void OnInTransferComplete (UCHAR endpointNumber);
static bool OnOutTransferComplete (UCHAR endpointNumber, void *buffer, UINT numBytesReceived, bool wasPCAsserted);
static void OnNAKSent (UCHAR endpointNumber);
static bool OnConfigRequest (UCHAR newConfiguration, UCHAR newInterface, UCHAR newAltSetting);
static void OnSuspend (void);
static void OnResume (void);
static void OnReset (void);
static void OnSOF (void);




/*------------------------------------------------------------
*	MSCLASS_Init
*
*	Parameters:  
*
*	Globals Used:
*		gpOnResume, gpOnReset, gUseINEP, gpTheReportDescriptor, gTheReportDescriptorSize
*		gTheDeviceDescriptor, gTheConfigDescriptor, gIsTransferActive, gIsDeviceConfigured,
*		gCommandStatusState
*
*	Description:
*		This is the main initialization routine. The client provides the vendor id, device id,
*		revision, and a bunch of pointers to routines to be calleld under various conditions.
*		This routine also calls the init routine for the SCSI device implementation code.
*
*	Returns:
*		true on success, false on failure.
*
*------------------------------------------------------------*/
bool MSCLASS_Init (uint16 vid, uint16 pid, uint16 rel, PSUSPENDPROC pOnSuspendProc, 
	PRESUMEPROC pOnResumeProc, PRESETPROC pOnResetProc)
	{

		SCSI_Init();
		//Initialize the state variables
		gIsTransferActive = false;
		gIsDeviceConfigured = false;

		gCommandStatusState = STATE_IDLE;

		/*
		gDebugNumTransfers = 0;
		gDebugTotalTransferLength = 0;
		*/

		//Save the callback addresses
		gpOnSuspend = pOnSuspendProc;
		gpOnResume = pOnResumeProc;
		gpOnReset = pOnResetProc;

		//Update the VID and PID
		memcpy (&gTheDeviceDescriptor[OFFSET_VENDOR_ID], &vid, sizeof (uint16));
		memcpy (&gTheDeviceDescriptor[OFFSET_PRODUCT_ID], &pid, sizeof (uint16));
		memcpy (&gTheDeviceDescriptor[OFFSET_RELEASE], &rel, sizeof (uint16));

		//Things to do before setting up endpoints
		if (!USBDriver_PreInit ())
			return false;

		USBDriver_SetupEndpoint (EP_FOR_IN_TRANSFERS, ALTSETTING_FOR_BULKONLY,
			INTERFACE_FOR_BULKONLY, EP_CONFIG1, EP_IN,
			EP_BULK, BULKEP_MAX_PACKET_SIZE);

		USBDriver_SetupEndpoint (EP_FOR_OUT_TRANSFERS, ALTSETTING_FOR_BULKONLY,
			INTERFACE_FOR_BULKONLY, EP_CONFIG1, EP_OUT,
			EP_BULK, BULKEP_MAX_PACKET_SIZE);

		return USBDriver_CompleteInit (OnSetupRequest, OnGetDeviceDescriptor, 
			OnGetConfigDescriptor, OnGetStringDescriptor, 
			OnInTransferComplete, OnOutTransferComplete, OnNAKSent, 
			OnSuspend, OnResume, OnReset, OnConfigRequest, OnSOF, CONTROL_PIPE_MAX_TRANSFER_LENGTH);

	}


/*------------------------------------------------------------
*	MSReset
*
*	Parameters:  
*		None
*
*	Globals Used:
*		gCommandStatusState, gRemainingDataToShipUp, gRemainingDataToComeIn
*
*	Description:
*		This is called to reset the state of the Command Status protocol, and
*		to reset the endpoints - preparing them for transfers
*
*	Returns:
*		Nothing
*
*------------------------------------------------------------*/
void MSReset (void)
	{
		//Setup and Arm our 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);

		//Disarm the IN endpoint
		DisarmEndpoint (EP_FOR_IN_TRANSFERS, EP_IN);
		UnprepareEP (EP_FOR_IN_TRANSFERS);


		Dprintf ("MSReset: Will wait for next CBW");
		gCommandStatusState = STATE_WAITFOR_CBW;
		gRemainingDataToComeIn = 0;
		gRemainingDataToShipUp = 0;

	}


/*------------------------------------------------------------
*	OnSetupRequest
*
*	Parameters:  
*		endpointNumber - the endpoint on which this request was received
*		pSetupData - points to a structure cantaining the SETUP DATA(0)
*		buffer - points to a buffer where the setup data is available, or should be placed.
*		pNumBytesToTransfer - points to a location where the number of bytes
*			to be sent back should be stored.
*	Globals Used:
*		None
*
*	Description:
*		This routine is called by the USB driver to handle a special setup request, 
*		that is not a GET DEVICE, GET CONFIG, or GET STRING descriptor
*		
*		Based on the request type, this routine reads/writes to the buffer
*		provided.
*
*	Returns:
*		true to succeed the request, false to stall the request
*
*------------------------------------------------------------*/
bool OnSetupRequest (UCHAR endpointNumber, PUSB_SETUP_DATA pSetupData, void *buffer, 
	PUINT pNumBytesToTransfer)
	{
		bool retVal = false; //stall
		bool validRequest = false;

		//Need to handle the class specific requests
		if (endpointNumber == EP0)
			{
				if ((USB_CONTROL_REQUEST_GET_TYPE (pSetupData->bmRequestType) == USB_CONTROL_REQUEST_TYPE_CLASS) &&
					(USB_CONTROL_REQUEST_GET_RECIPIENT (pSetupData->bmRequestType) == USB_CONTROL_REQUEST_TYPE_INTERFACE) &&
					(LOBYTE (pSetupData->wIndex) == INTERFACE_FOR_BULKONLY))
					{
						if ((USB_CONTROL_REQUEST_GET_DIRECTION(pSetupData->bmRequestType) == USB_CONTROL_REQUEST_TYPE_OUT)  &&
							(pSetupData->bRequest == USBMS_REQUEST_RESET) && (pSetupData->wValue == 0) && (pSetupData->wLength == 0))
							{
								validRequest = true;
								retVal = true;
								MSReset ();
							}
						else if ((USB_CONTROL_REQUEST_GET_DIRECTION(pSetupData->bmRequestType) == USB_CONTROL_REQUEST_TYPE_IN)  &&
							(pSetupData->bRequest == USBMS_REQUEST_GET_MAX_LUN) && (pSetupData->wValue == 0) && (pSetupData->wLength == 1))
							{
								validRequest = true;
								*(PUCHAR)buffer = MAX_LUN;
								*pNumBytesToTransfer = 1;
								retVal = true;
							}
					}
			}

		
		if (!validRequest)
			{
				Dprintf1 ("Unknown setup request: %02x", pSetupData->bmRequestType);
				Dprintf3 ("Dir = %02x, Type = %02x, Rec = %02x", USB_CONTROL_REQUEST_GET_DIRECTION (pSetupData->bmRequestType),
					USB_CONTROL_REQUEST_GET_TYPE (pSetupData->bmRequestType),
					USB_CONTROL_REQUEST_GET_RECIPIENT (pSetupData->bmRequestType));
				Dprintf1 ("bRequest = %02x", pSetupData->bRequest);
			}
			

		return (retVal);
	}




/*------------------------------------------------------------
*	OnGetDeviceDescriptor
*
*	Parameters:  
*		buffer - location (DMA buffer) where the descriptor data is to
*			be put.
*		pNumBytesToTransfer - points to a location where the original wLength
*			is stored. This routine should update this location to indicate
*			the actual number of bytes transferred to the buffer.
*
*	Globals Used:
*		gTheDeviceDescriptor
*
*	Description:
*		This routine is in response to a GET DEVICE DESCRIPTOR
*		setup request. This routine fills in the required data
*
*	Returns:
*		true - always!
*
*------------------------------------------------------------*/
bool OnGetDeviceDescriptor (void *buffer, PUINT pNumBytesToTransfer)
	{
		if (*pNumBytesToTransfer < sizeof (gTheDeviceDescriptor))
			memcpy (buffer, &gTheDeviceDescriptor, *pNumBytesToTransfer);
		else
			{
				memcpy (buffer, &gTheDeviceDescriptor, sizeof (gTheDeviceDescriptor));
				*pNumBytesToTransfer = sizeof (gTheDeviceDescriptor);
			}

		return(true);
	}



/*------------------------------------------------------------
*	OnGetConfigDescriptor
*
*	Parameters:  
*		buffer - location (DMA buffer) where the descriptor data is to
*			be put.
*		pNumBytesToTransfer - points to a location where the original wLength
*			is stored. This routine should update this location to indicate
*			the actual number of bytes transferred to the buffer.
*
*	Globals Used:
*		gTheConfigDescriptor
*
*	Description:
*		This routine is in response to a GET CONFIG DESCRIPTOR
*		setup request. This routine fills in the required data
*
*	Returns:
*		true - always!
*
*------------------------------------------------------------*/
bool OnGetConfigDescriptor (void *buffer, PUINT pNumBytesToTransfer)
	{

		if (*pNumBytesToTransfer < sizeof(gTheConfigDescriptor))
			memcpy (buffer, &gTheConfigDescriptor, *pNumBytesToTransfer);
		else
			{
				memcpy (buffer, &gTheConfigDescriptor, sizeof (gTheConfigDescriptor));
				*pNumBytesToTransfer = sizeof (gTheConfigDescriptor);
			}

		return (true);
	}



/*------------------------------------------------------------
*	OnGetStringDescriptor
*
*	Parameters:  
*		wValue - the string to be retrieved
*		buffer - location (DMA buffer) where the descriptor data is to
*			be put.
*		pNumBytesToTransfer - points to a location where the original wLength
*			is stored. This routine should update this location to indicate
*			the actual number of bytes transferred to the buffer.
*
*	Globals Used:
*		Not Yet!
*
*	Description:
*		This routine is in response to a GET STRING DESCRIPTOR
*		setup request. This routine fills in the required data
*
*	Returns:
*		true - always!
*
*------------------------------------------------------------*/
bool OnGetStringDescriptor (UCHAR stringIndex, USHORT langID, void *buffer, PUINT pNumBytesToTransfer)
	{
		bool retVal = false;
		UINT neededSpace = 0;
		UINT maxBytesToTransfer = 0;
		UINT outIndex = 0, charIndex = 0;

		if (stringIndex == 0)
			{
				//Need to return a langid array here!
				if (*pNumBytesToTransfer < sizeof (gTheLangIDArray))
					memcpy (buffer, &gTheLangIDArray, *pNumBytesToTransfer);
				else
					{
						memcpy (buffer, &gTheLangIDArray, sizeof (gTheLangIDArray));
						*pNumBytesToTransfer = sizeof (gTheLangIDArray);
					}
				retVal = true;
			}
		else if ((stringIndex < TOTAL_STRING_DESCRIPTORS) && (stringIndex > 0))
			{
				//Convert this to a zero based index
				stringIndex--;
				neededSpace = (strlen (gTheStringDescriptors[stringIndex]) + 1) * 2;
				if (neededSpace > *pNumBytesToTransfer)
					maxBytesToTransfer = *pNumBytesToTransfer;
				else
					maxBytesToTransfer = *pNumBytesToTransfer = neededSpace;

				//Transfer as many as we can
				((char *)buffer)[outIndex++] = neededSpace;
				((char *)buffer)[outIndex++] = USB_STRING_DESCRIPTOR;
				while ((outIndex + 1) < maxBytesToTransfer)
					{
						((char *)buffer)[outIndex++] = gTheStringDescriptors[stringIndex][charIndex++];
						((char *)buffer)[outIndex++] = 0;
					}


				retVal = true;
			}

		//Don't have any strings yet!
		return(retVal);
	}




/*------------------------------------------------------------
*	OnConfigRequest
*
*	Parameters:  
*		newConfiguration - the new configuration after Config request.
*		newInterface - the new interface after Config(Set Interface) request.
*		newAltSetting - the new alt setting after Config(Set Interface) request
*
*	Globals Used:
*		gIsDeviceConfigured
*
*	Description:
*		This routien is called in response to a configuration change - i.e.
*		after receiving a Set Config or a Set Interface request.
*
*	Returns:
*		true - always
*
*------------------------------------------------------------*/
bool OnConfigRequest (UCHAR newConfiguration, UCHAR newInterface, UCHAR newAltSetting)
	{
		//Dprintf3 ("Audio Dev Config Request: %02x, %02x, %02x!", (UINT)newConfiguration, (UINT)newInterface, (UINT)newAltSetting);
		if ((newConfiguration == EP_CONFIG1) && (newInterface == INTERFACE_FOR_BULKONLY) &&
			(newAltSetting == ALTSETTING_FOR_BULKONLY))
			{
				if (!gIsDeviceConfigured)
					{
						//Looks like we're in, setup our endpoints
						Dprintf ("Mass Storage Device Configured!");
						MSReset ();
						gIsDeviceConfigured = true;
					}
			}
		else
			{
				//Disarm the endpoints
				DisarmEndpoint (EP_FOR_IN_TRANSFERS, EP_IN);
				UnprepareEP (EP_FOR_IN_TRANSFERS);
				DisarmEndpoint (EP_FOR_OUT_TRANSFERS, EP_OUT);
				UnprepareEP (EP_FOR_OUT_TRANSFERS);
				gIsDeviceConfigured = false;
			}
			
		return true;
	}



/*------------------------------------------------------------
*	OnInTransferComplete
*
*	Parameters:  
*		endpointNumber - the endpoint on which the transfer was completed.
*
*	Globals Used:
*		gCommandStatusState
*
*	Description:
*		This routine is called when a IN transfer is completed on one of the
*		endpoints. 
*
*	Returns:
*		Nothing
*
*------------------------------------------------------------*/
void OnInTransferComplete (UCHAR endpointNumber)
	{
		if (endpointNumber == EP_FOR_IN_TRANSFERS)
			{
				//Disarm the IN endpoint
				//DisarmEndpoint (EP_FOR_IN_TRANSFERS, EP_IN);
				//UnprepareEP (EP_FOR_IN_TRANSFERS);

				//Dprintf1 ("InTransferComplete: %02x", gCommandStatusState);
				switch (gCommandStatusState)
					{

⌨️ 快捷键说明

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