📄 udp.c
字号:
for (bEndpoint = 0; bEndpoint < pUsb->dNumEndpoints; bEndpoint++) {
pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
// Reset endpoint transfer descriptor
pEndpoint->pData = 0;
pEndpoint->dBytesRemaining = 0;
pEndpoint->dBytesTransferred = 0;
pEndpoint->dBytesBuffered = 0;
pEndpoint->fCallback = 0;
pEndpoint->pArgument = 0;
// Configure endpoint characteristics
pEndpoint->dFlag = AT91C_UDP_RX_DATA_BK0;
pEndpoint->dState = endpointStateDisabled;
}
}
//------------------------------------------------------------------------------
// \brief Disable all endpoints (except control endpoint 0), aborting current
// transfers if necessary.
// \param pUsb Pointer to a S_usb instance
//------------------------------------------------------------------------------
static void UDP_DisableEndpoints(const S_usb *pUsb)
{
S_usb_endpoint *pEndpoint;
unsigned char bEndpoint;
// For each endpoint, if it is enabled, disable it and invoke the callback
// Control endpoint 0 is not disabled
for (bEndpoint = 1; bEndpoint < pUsb->dNumEndpoints; bEndpoint++) {
pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
UDP_EndOfTransfer(pEndpoint, USB_STATUS_RESET);
pEndpoint->dState = endpointStateDisabled;
}
}
//------------------------------------------------------------------------------
// \brief Endpoint interrupt handler.
//
// Handle IN/OUT transfers, received SETUP packets and STALLing
// \param pUsb Pointer to a S_usb instance
// \param bEndpoint Index of endpoint
// \see S_usb
//------------------------------------------------------------------------------
static void UDP_EndpointHandler(const S_usb *pUsb, unsigned char bEndpoint)
{
S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
AT91PS_UDP pInterface = UDP_GetDriverInterface(pUsb);
unsigned int dStatus = pInterface->UDP_CSR[bEndpoint];
TRACE_DEBUG_L("Ept%d ", bEndpoint);
// Handle interrupts
// IN packet sent
if (ISSET(dStatus, AT91C_UDP_TXCOMP)) {
TRACE_DEBUG_L("Wr ");
// Check that endpoint was in Write state
if (pEndpoint->dState == endpointStateWrite) {
// End of transfer ?
if ((pEndpoint->dBytesBuffered < pEndpoint->wMaxPacketSize)
||
(!ISCLEARED(dStatus, AT91C_UDP_EPTYPE)
&& (pEndpoint->dBytesRemaining == 0)
&& (pEndpoint->dBytesBuffered == pEndpoint->wMaxPacketSize))) {
TRACE_DEBUG_L("%d ", pEndpoint->dBytesBuffered);
pEndpoint->dBytesTransferred += pEndpoint->dBytesBuffered;
pEndpoint->dBytesBuffered = 0;
// Disable interrupt if this is not a control endpoint
if (!ISCLEARED(dStatus, AT91C_UDP_EPTYPE)) {
SET(pInterface->UDP_IDR, 1 << bEndpoint);
}
UDP_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
}
else {
// Transfer remaining data
TRACE_DEBUG_L("%d ", pEndpoint->wMaxPacketSize);
pEndpoint->dBytesTransferred += pEndpoint->wMaxPacketSize;
pEndpoint->dBytesBuffered -= pEndpoint->wMaxPacketSize;
// Send next packet
if (pEndpoint->dNumFIFO == 1) {
// No double buffering
UDP_WritePayload(pUsb, bEndpoint);
UDP_SETEPFLAGS(pUsb, bEndpoint, AT91C_UDP_TXPKTRDY);
}
else {
// Double buffering
UDP_SETEPFLAGS(pUsb, bEndpoint, AT91C_UDP_TXPKTRDY);
UDP_WritePayload(pUsb, bEndpoint);
}
}
}
// Acknowledge interrupt
UDP_CLEAREPFLAGS(pUsb, bEndpoint, AT91C_UDP_TXCOMP);
}
// OUT packet received
if (ISSET(dStatus, AT91C_UDP_RX_DATA_BK0)
|| ISSET(dStatus, AT91C_UDP_RX_DATA_BK1)) {
TRACE_DEBUG_L("Rd ");
// Check that the endpoint is in Read state
if (pEndpoint->dState != endpointStateRead) {
// Endpoint is NOT in Read state
if (ISCLEARED(dStatus, AT91C_UDP_EPTYPE)
&& ISCLEARED(dStatus, 0xFFFF0000)) {
// Control endpoint, 0 bytes received
// Acknowledge the data and finish the current transfer
TRACE_DEBUG_L("Ack ");
UDP_ClearRXFlag(pUsb, bEndpoint);
UDP_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
}
else if (ISSET(dStatus, AT91C_UDP_FORCESTALL)) {
// Non-control endpoint
// Discard stalled data
TRACE_DEBUG_L("Disc ");
UDP_ClearRXFlag(pUsb, bEndpoint);
}
else {
// Non-control endpoint
// Nak data
TRACE_DEBUG_L("Nak ");
SET(pInterface->UDP_IDR, 1 << bEndpoint);
}
}
else {
// Endpoint is in Read state
// Retrieve data and store it into the current transfer buffer
unsigned short wPacketSize = (unsigned short) (dStatus >> 16);
TRACE_DEBUG_L("%d ", wPacketSize);
UDP_GetPayload(pUsb, bEndpoint, wPacketSize);
UDP_ClearRXFlag(pUsb, bEndpoint);
if ((pEndpoint->dBytesRemaining == 0)
|| (wPacketSize < pEndpoint->wMaxPacketSize)) {
// Disable interrupt if this is not a control endpoint
if (!ISCLEARED(dStatus, AT91C_UDP_EPTYPE)) {
SET(pInterface->UDP_IDR, 1 << bEndpoint);
}
UDP_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
}
}
}
// SETUP packet received
if (ISSET(dStatus, AT91C_UDP_RXSETUP)) {
TRACE_DEBUG_L("Stp ");
// If a transfer was pending, complete it
// Handle the case where during the status phase of a control write
// transfer, the host receives the device ZLP and ack it, but the ack
// is not received by the device
if ((pEndpoint->dState == endpointStateWrite)
|| (pEndpoint->dState == endpointStateRead)) {
UDP_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
}
// Copy the setup packet in S_usb
UDP_GetSetup(pUsb);
// Set the DIR bit before clearing RXSETUP in Control IN sequence
if (USB_GetSetup(pUsb)->bmRequestType & 0x80) {
UDP_SETEPFLAGS(pUsb, bEndpoint, AT91C_UDP_DIR);
}
UDP_CLEAREPFLAGS(pUsb, bEndpoint, AT91C_UDP_RXSETUP);
// Forward the request to the upper layer
USB_NewRequestCallback(pUsb);
}
// STALL sent
if (ISSET(dStatus, AT91C_UDP_STALLSENT)) {
TRACE_WARNING("Sta ");
// Acknowledge the stall flag
UDP_CLEAREPFLAGS(pUsb, bEndpoint, AT91C_UDP_STALLSENT);
// If the endpoint is not halted, clear the stall condition
if (pEndpoint->dState != endpointStateHalted) {
UDP_CLEAREPFLAGS(pUsb, bEndpoint, AT91C_UDP_FORCESTALL);
}
}
}
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// \brief Configure an endpoint with the provided endpoint descriptor
// \param pUsb Pointer to a S_usb instance
// \param pEpDesc Pointer to the endpoint descriptor
// \return true if the endpoint is now configured, false otherwise
// \see S_usb_endpoint_descriptor
// \see S_usb
//------------------------------------------------------------------------------
bool UDP_ConfigureEndpoint(const S_usb *pUsb,
const S_usb_endpoint_descriptor *pEpDesc)
{
AT91PS_UDP pInterface = UDP_GetDriverInterface(pUsb);
S_usb_endpoint *pEndpoint;
unsigned char bEndpoint;
unsigned char bType;
bool isINEndpoint;
unsigned int dFlags;
// NULL descriptor -> Control endpoint 0
if (pEpDesc == 0) {
bEndpoint = 0;
bType = ENDPOINT_TYPE_CONTROL;
isINEndpoint = false;
}
else {
bEndpoint = (unsigned char) (pEpDesc->bEndpointAddress & 0x7);
bType = (unsigned char) (pEpDesc->bmAttributes & 0x3);
if (ISSET(pEpDesc->bEndpointAddress, 1 << 7)) {
isINEndpoint = true;
}
else {
isINEndpoint = false;
}
}
// Get pointer on endpoint
pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
if (pEndpoint == 0) {
return false;
}
// Configure wMaxPacketSize
if (pEpDesc != 0) {
pEndpoint->wMaxPacketSize = pEpDesc->wMaxPacketSize;
}
else {
pEndpoint->wMaxPacketSize = USB_ENDPOINT0_MAXPACKETSIZE;
}
// Abort the current transfer is the endpoint was configured and in
// Write or Read state
if ((pEndpoint->dState == endpointStateRead)
|| (pEndpoint->dState == endpointStateWrite)) {
UDP_EndOfTransfer(pEndpoint, USB_STATUS_RESET);
}
// Enter IDLE state
pEndpoint->dState = endpointStateIdle;
// Reset Endpoint Fifos
SET(pInterface->UDP_RSTEP, 1 << bEndpoint);
CLEAR(pInterface->UDP_RSTEP, 1 << bEndpoint);
// Configure endpoint
dFlags = AT91C_UDP_EPEDS;
SET(dFlags, bType << UDP_EPTYPE_INDEX);
if (isINEndpoint) {
SET(dFlags, 1 << UDP_EPDIR_INDEX);
}
if (bType == ENDPOINT_TYPE_CONTROL) {
SET(pInterface->UDP_IER, 1 << bEndpoint);
}
TRACE_DEBUG_L("CfgEpt%d ", bEndpoint);
UDP_SETEPFLAGS(pUsb, bEndpoint, dFlags);
return true;
}
//------------------------------------------------------------------------------
// \brief UDP interrupt handler
//
// Manages device resume, suspend, end of bus reset. Forwards endpoint
// interrupts to the appropriate handler.
// \param pUsb Pointer to a S_usb instance
//------------------------------------------------------------------------------
void UDP_Handler(const S_usb *pUsb)
{
AT91PS_UDP pInterface = UDP_GetDriverInterface(pUsb);
unsigned int dStatus;
unsigned char bEndpoint;
if ( (!ISSET(USB_GetState(pUsb), USB_STATE_SUSPENDED))
&& (ISSET(USB_GetState(pUsb), USB_STATE_POWERED))){
LED_TOGGLE(LED_USB);
}
TRACE_DEBUG_L("Hlr ");
// Get interrupts status
dStatus = pInterface->UDP_ISR & pInterface->UDP_IMR & ISR_MASK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -