📄 cdc_enumerate.c
字号:
pData[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT];
pUdp->UDP_CSR[AT91C_EP_OUT] &= ~(currentReceiveBank);
if (currentReceiveBank == AT91C_UDP_RX_DATA_BK0)
currentReceiveBank = AT91C_UDP_RX_DATA_BK1;
else
currentReceiveBank = AT91C_UDP_RX_DATA_BK0;
}
}
pCdc->currentRcvBank = currentReceiveBank;
return nbBytesRcv;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_CDC_Write
//* \brief Send through endpoint 2
//*----------------------------------------------------------------------------
static uint AT91F_UDP_Write(AT91PS_CDC pCdc, const char *pData, uint length)
{
AT91PS_UDP pUdp = pCdc->pUdp;
uint cpt = 0;
// Send the first packet
cpt = MIN(length, AT91C_EP_IN_SIZE);
length -= cpt;
while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *pData++;
pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;
while (length) {
// Fill the second bank
cpt = MIN(length, AT91C_EP_IN_SIZE);
length -= cpt;
while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *pData++;
// Wait for the the first bank to be sent
while ( !(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) )
if ( !AT91F_UDP_IsConfigured(pCdc) ) return length;
pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);
pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;
}
// Wait for the end of transfer
while ( !(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) )
if ( !AT91F_UDP_IsConfigured(pCdc) ) return length;
pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP);
return length;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_USB_SendData
//* \brief Send Data through the control endpoint
//*----------------------------------------------------------------------------
unsigned int csrTab[100];
unsigned char csrIdx = 0;
static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint length)
{
uint cpt = 0;
AT91_REG csr;
do {
cpt = MIN(length, 8);
length -= cpt;
while (cpt--)
pUdp->UDP_FDR[0] = *pData++;
if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) {
pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP);
}
pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;
do {
csr = pUdp->UDP_CSR[0];
// Data IN stage has been stopped by a status OUT
if (csr & AT91C_UDP_RX_DATA_BK0) {
pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);
return;
}
} while ( !(csr & AT91C_UDP_TXCOMP) );
} while (length);
if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) {
pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP);
}
}
//*----------------------------------------------------------------------------
//* \fn AT91F_USB_SendZlp
//* \brief Send zero length packet through the control endpoint
//*----------------------------------------------------------------------------
void AT91F_USB_SendZlp(AT91PS_UDP pUdp)
{
pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY;
while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) );
pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP);
while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP);
}
//*----------------------------------------------------------------------------
//* \fn AT91F_USB_SendStall
//* \brief Stall the control endpoint
//*----------------------------------------------------------------------------
void AT91F_USB_SendStall(AT91PS_UDP pUdp)
{
pUdp->UDP_CSR[0] |= AT91C_UDP_FORCESTALL;
while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_ISOERROR) );
pUdp->UDP_CSR[0] &= ~(AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR);
while (pUdp->UDP_CSR[0] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR));
}
//*----------------------------------------------------------------------------
//* \fn AT91F_CDC_Enumerate
//* \brief This function is a callback invoked when a SETUP packet is received
//*----------------------------------------------------------------------------
static void AT91F_CDC_Enumerate(AT91PS_CDC pCdc)
{
AT91PS_UDP pUDP = pCdc->pUdp;
uchar bmRequestType, bRequest;
ushort wValue, wIndex, wLength, wStatus;
if ( !(pUDP->UDP_CSR[0] & AT91C_UDP_RXSETUP) )
return;
bmRequestType = pUDP->UDP_FDR[0];
bRequest = pUDP->UDP_FDR[0];
wValue = (pUDP->UDP_FDR[0] & 0xFF);
wValue |= (pUDP->UDP_FDR[0] << 8);
wIndex = (pUDP->UDP_FDR[0] & 0xFF);
wIndex |= (pUDP->UDP_FDR[0] << 8);
wLength = (pUDP->UDP_FDR[0] & 0xFF);
wLength |= (pUDP->UDP_FDR[0] << 8);
if (bmRequestType & 0x80) {
pUDP->UDP_CSR[0] |= AT91C_UDP_DIR;
while ( !(pUDP->UDP_CSR[0] & AT91C_UDP_DIR) );
}
pUDP->UDP_CSR[0] &= ~AT91C_UDP_RXSETUP;
while ( (pUDP->UDP_CSR[0] & AT91C_UDP_RXSETUP) );
// Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1
switch ((bRequest << 8) | bmRequestType) {
case STD_GET_DESCRIPTOR:
if (wValue == 0x100) // Return Device Descriptor
AT91F_USB_SendData(pUDP, devDescriptor, MIN(sizeof(devDescriptor), wLength));
else if (wValue == 0x200) // Return Configuration Descriptor
AT91F_USB_SendData(pUDP, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength));
else
AT91F_USB_SendStall(pUDP);
break;
case STD_SET_ADDRESS:
AT91F_USB_SendZlp(pUDP);
pUDP->UDP_FADDR = (AT91C_UDP_FEN | wValue);
pUDP->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;
break;
case STD_SET_CONFIGURATION:
pCdc->currentConfiguration = wValue;
AT91F_USB_SendZlp(pUDP);
pUDP->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN;
pUDP->UDP_CSR[1] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0;
pUDP->UDP_CSR[2] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0;
pUDP->UDP_CSR[3] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0;
break;
case STD_GET_CONFIGURATION:
AT91F_USB_SendData(pUDP, (char *) &(pCdc->currentConfiguration), sizeof(pCdc->currentConfiguration));
break;
case STD_GET_STATUS_ZERO:
wStatus = 0;
AT91F_USB_SendData(pUDP, (char *) &wStatus, sizeof(wStatus));
break;
case STD_GET_STATUS_INTERFACE:
wStatus = 0;
AT91F_USB_SendData(pUDP, (char *) &wStatus, sizeof(wStatus));
break;
case STD_GET_STATUS_ENDPOINT:
wStatus = 0;
wIndex &= 0x0F;
if ((pUDP->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= 3)) {
wStatus = (pUDP->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
AT91F_USB_SendData(pUDP, (char *) &wStatus, sizeof(wStatus));
}
else if ((pUDP->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == 0)) {
wStatus = (pUDP->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1;
AT91F_USB_SendData(pUDP, (char *) &wStatus, sizeof(wStatus));
}
else
AT91F_USB_SendStall(pUDP);
break;
case STD_SET_FEATURE_ZERO:
AT91F_USB_SendStall(pUDP);
break;
case STD_SET_FEATURE_INTERFACE:
AT91F_USB_SendZlp(pUDP);
break;
case STD_SET_FEATURE_ENDPOINT:
wIndex &= 0x0F;
if ((wValue == 0) && wIndex && (wIndex <= 3)) {
pUDP->UDP_CSR[wIndex] = 0;
AT91F_USB_SendZlp(pUDP);
}
else
AT91F_USB_SendStall(pUDP);
break;
case STD_CLEAR_FEATURE_ZERO:
AT91F_USB_SendStall(pUDP);
break;
case STD_CLEAR_FEATURE_INTERFACE:
AT91F_USB_SendZlp(pUDP);
break;
case STD_CLEAR_FEATURE_ENDPOINT:
wIndex &= 0x0F;
if ((wValue == 0) && wIndex && (wIndex <= 3)) {
if (wIndex == 1)
pUDP->UDP_CSR[1] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT);
else if (wIndex == 2)
pUDP->UDP_CSR[2] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN);
else if (wIndex == 3)
pUDP->UDP_CSR[3] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_ISO_IN);
AT91F_USB_SendZlp(pUDP);
}
else
AT91F_USB_SendStall(pUDP);
break;
// handle CDC class requests
case SET_LINE_CODING:
while ( !(pUDP->UDP_CSR[0] & AT91C_UDP_RX_DATA_BK0) );
pUDP->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);
AT91F_USB_SendZlp(pUDP);
break;
case GET_LINE_CODING:
AT91F_USB_SendData(pUDP, (char *) &line, MIN(sizeof(line), wLength));
break;
case SET_CONTROL_LINE_STATE:
pCdc->currentConnection = wValue;
AT91F_USB_SendZlp(pUDP);
break;
default:
AT91F_USB_SendStall(pUDP);
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -