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

📄 at91_svc_usbctl.c

📁 AT91RM9200 BSP with dual ethernet port
💻 C
字号:
/**----------------------------------------------------------------------------*/
/**      ATMEL Microcontroller Software Support  -  ROUSSET  -*/
/**----------------------------------------------------------------------------*/
/** The software is delivered "AS IS" without warranty or condition of any*/
/** kind, either express, implied or statutory. This includes without*/
/** limitation any warranty or condition with respect to merchantability or*/
/** fitness for any particular purpose, or against the infringements of*/
/** intellectual property rights of others.*/
/**----------------------------------------------------------------------------*/
/** File Name           : AT91_SVC_USBCTL.c*/
/** Object              : DMA service USB device control enpoint*/
/***/
/** 1.0 Jul 30 2002 	: ODi Creation*/
/**----------------------------------------------------------------------------*/
#include "AT91_SVC_USBCTL.h"


/**----------------------------------------------------------------------------*/
/** \fn    AT91F_SVC_USBCTL_Open*/
/** \brief Open USBCTL service.*/
/**----------------------------------------------------------------------------*/
AT91PS_SVC_USBCTL AT91F_SVC_USBCTL_Open(
	AT91PS_SVC_USBCTL pSvcUdp,  /* \arg Pointer to an USBCTL service previously allocated*/
	AT91PS_UDP pUdp)            /* \arg Pointer to UDP registers*/
{
	pSvcUdp->Handler = AT91F_SVC_USBCTL_Handler;
	pSvcUdp->Read    = AT91F_SVC_USBCTL_Read;
	pSvcUdp->Write   = AT91F_SVC_USBCTL_Write;

	pSvcUdp->DisptachSetup = (AT91PF_SVC_USBCTL_DispatchSetup) 0;
	pSvcUdp->RWComplete    = (AT91PF_SVC_USBCTL_RWComplete) 0;

	pSvcUdp->pBuffer = (char *) 0;
	pSvcUdp->bufferSize = 0;
	pSvcUdp->eot = 0;

	pSvcUdp->pUdp = pUdp;


	return pSvcUdp;
}

/**----------------------------------------------------------------------------*/
/** \fn    AT91F_SVC_USBCTL_DataIn*/
/** \brief*/
/**----------------------------------------------------------------------------*/
static void AT91F_SVC_USBCTL_DataIn(
	AT91PS_SVC_USBCTL pSvcUdp,     /* \arg Pointer to an USBCTL service*/
	AT91PS_UDP pUdp)               /* \arg Pointer to UDP registers*/
{
	char *pBuffer;

	/* If bufferSize == 0 Send a Zero length packet*/
	if (pSvcUdp->bufferSize == 0)
		AT91F_UDP_EpEndOfWr(pUdp, 0);

	/* else initialize DPR*/
	else {
		pBuffer = pSvcUdp->pBuffer;
		if (pSvcUdp->bufferSize >= 8) {
			AT91F_UDP_EpWrite(pUdp, 0, *pBuffer++);
			AT91F_UDP_EpWrite(pUdp, 0, *pBuffer++);
			AT91F_UDP_EpWrite(pUdp, 0, *pBuffer++);
			AT91F_UDP_EpWrite(pUdp, 0, *pBuffer++);
			AT91F_UDP_EpWrite(pUdp, 0, *pBuffer++);
			AT91F_UDP_EpWrite(pUdp, 0, *pBuffer++);
			AT91F_UDP_EpWrite(pUdp, 0, *pBuffer++);
			AT91F_UDP_EpWrite(pUdp, 0, *pBuffer++);
			pSvcUdp->bufferSize -= 8;
		}
		else while (pSvcUdp->bufferSize--)
			AT91F_UDP_EpWrite(pUdp, 0, *pBuffer++);
		pSvcUdp->pBuffer = pBuffer;
		AT91F_UDP_EpEndOfWr(pUdp, 0);
	}
	pSvcUdp->eot = !(pSvcUdp->bufferSize);
}

/**----------------------------------------------------------------------------*/
/** \fn    AT91F_SVC_USBCTL_DataOut*/
/** \brief*/
/**----------------------------------------------------------------------------*/
__inline char AT91F_SVC_USBCTL_DataOut(
	AT91PS_SVC_USBCTL pSvcUdp,     /* \arg Pointer to an USBCTL service*/
	AT91PS_UDP pUdp,               /* \arg Pointer to UDP registers*/
	unsigned int epCsr)            /* \arg Value of the UDP_CSR[0] register*/
{
	unsigned int bytesReceived;
	char eor; /* Detect end of Receive*/

	/* Copy bytes received to the client buffer*/
	bytesReceived = (epCsr & AT91C_UDP_RXBYTECNT) >> 16;
	if (bytesReceived > pSvcUdp->bufferSize)
		bytesReceived = pSvcUdp->bufferSize;
	pSvcUdp->bufferSize -= bytesReceived;
	/* Check the end of a Control OUT sequence: An incomplete packet stops the Data OUT sequence*/
	eor = (bytesReceived < 8);

	while (bytesReceived--)
		*(pSvcUdp->pBuffer)++ = AT91F_UDP_EpRead(pUdp, 0);
	AT91F_UDP_EpClear(pUdp, 0, (AT91C_UDP_RX_DATA_BK0));

	return eor;
}

/**----------------------------------------------------------------------------*/
/** \fn    AT91F_SVC_USBCTL_Handler*/
/** \brief*/
/**----------------------------------------------------------------------------*/
void AT91F_SVC_USBCTL_Handler(
	AT91PS_SVC_USBCTL pSvcUdp)     /* \arg Pointer to an USBCTL service*/
{
	AT91PS_UDP   pUdp = pSvcUdp->pUdp; /* Pointer to UDP registers*/
	unsigned int epCsr =  AT91F_UDP_EpStatus(pUdp, 0);

	/* Test if a SETUP packet has been received*/
	if (epCsr & AT91C_UDP_RXSETUP) {
		/* Copy the setup packet*/
		pSvcUdp->pSetup[0] = AT91F_UDP_EpRead(pUdp, 0);
		pSvcUdp->pSetup[1] = AT91F_UDP_EpRead(pUdp, 0);
		pSvcUdp->pSetup[2] = AT91F_UDP_EpRead(pUdp, 0);
		pSvcUdp->pSetup[3] = AT91F_UDP_EpRead(pUdp, 0);
		pSvcUdp->pSetup[4] = AT91F_UDP_EpRead(pUdp, 0);
		pSvcUdp->pSetup[5] = AT91F_UDP_EpRead(pUdp, 0);
		pSvcUdp->pSetup[6] = AT91F_UDP_EpRead(pUdp, 0);
		pSvcUdp->pSetup[7] = AT91F_UDP_EpRead(pUdp, 0);
		/* Set the DIR bit before clearing RXSETUP in Control IN sequence*/
		if (pSvcUdp->pSetup[0] & 0x80)
			AT91F_UDP_EpSet(pUdp, 0, AT91C_UDP_DIR);
		/* Clear RXSETUP*/
		AT91F_UDP_EpClear(pUdp, 0, AT91C_UDP_RXSETUP);
		/* Notify the dispatcher*/
		if (pSvcUdp->DisptachSetup)
			pSvcUdp->DisptachSetup(pSvcUdp);
	}

	/* Test if the previous DATA IN packet is achieved*/
	else if (epCsr & AT91C_UDP_TXCOMP) {
		AT91F_UDP_EpClear(pUdp, 0, AT91C_UDP_TXCOMP);
		/* test end of transmission*/
		if (pSvcUdp->eot && pSvcUdp->RWComplete)
			pSvcUdp->RWComplete(pSvcUdp);
		/* else start new packet transfer*/
		else
			AT91F_SVC_USBCTL_DataIn(pSvcUdp, pUdp);
	}

	/* test if any DATA OUT packet occured*/
	else if (epCsr & AT91C_UDP_RX_DATA_BK0) {
		/* Test if this DATA OUT aborts a CONTROL IN sequence*/
		if (!(pSvcUdp->eot) && pSvcUdp->RWComplete)
			pSvcUdp->RWComplete(pSvcUdp);
		if (AT91F_SVC_USBCTL_DataOut(pSvcUdp, pUdp, epCsr) && pSvcUdp->RWComplete)
			pSvcUdp->RWComplete(pSvcUdp);
	}

	/* Test if a STALL has been acknowledged...*/
	else if (epCsr & AT91C_UDP_ISOERROR) { /* !!!!! Should be: AT91C_UDP_STALLSENT) {*/
		AT91F_UDP_EpClear(pUdp, 0, (AT91C_UDP_ISOERROR | AT91C_UDP_FORCESTALL));
	}

}


/**----------------------------------------------------------------------------*/
/** \fn    AT91F_SVC_USBCTL_Write*/
/** \brief*/
/**----------------------------------------------------------------------------*/
void AT91F_SVC_USBCTL_Write(
	AT91PS_SVC_USBCTL pSvcUdp,     /* \arg Pointer to an USBCTL service*/
	const char *pBuffer,                 /* \arg Pointer to the client buffer to send*/
	unsigned int bufferSize,       /* \arg Client buffer size*/
	AT91PF_SVC_USBCTL_RWComplete Callback) /* \arg Callback to invoke when buffer is Sent*/
{
	pSvcUdp->bufferSize  = bufferSize;
	pSvcUdp->pBuffer     = (char *)pBuffer;
	pSvcUdp->RWComplete  = Callback;

	AT91F_SVC_USBCTL_DataIn(pSvcUdp, pSvcUdp->pUdp);
}

/**----------------------------------------------------------------------------*/
/** \fn    AT91F_SVC_USBCTL_Read*/
/** \brief*/
/**----------------------------------------------------------------------------*/
void AT91F_SVC_USBCTL_Read(
	AT91PS_SVC_USBCTL pSvcUdp,     /* \arg Pointer to an USBCTL service*/
	char *pBuffer,                 /* \arg Pointer to the client buffer to fill*/
	unsigned int bufferSize,       /* \arg Client buffer size*/
	AT91PF_SVC_USBCTL_RWComplete Callback) /* \arg Callback to invoke when buffer is Full*/
{
	if ((bufferSize == 0) && (Callback)) {
		Callback(pSvcUdp);
		return;
	}
	pSvcUdp->bufferSize = bufferSize;
	pSvcUdp->pBuffer    = pBuffer;
	pSvcUdp->RWComplete = Callback;
}

⌨️ 快捷键说明

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