Im developing a CCID compatible USB device with AT91SAM7S. I modify de CDC
source code and Igetting a problem with tranmsitting the response to a
SETUP.
Everytime I try to send the descriptor to the HOST I get an
AT91C_UDP_RX_DATA_BK0 after I fill the second 8 byte block to the FIFO. This
interrupts the transmission and the HOST does not understanding the respose. It
is amazing because the HOST (PC with WINDOWS) sends me a STD_SET_ADDRESS and
then shows that it does not recognize the device.
The relevant code is below (the DEBUG option is off):
Sorry but the identation is off i dont know why!
Thanks
//*----
//* \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;
pUDP->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0);
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:
#ifdef DEBUG
AT91F_DBGU_Printk("STD_GET_DESCRIPTOR:\n\r");
#endif
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 if (wValue == 0x300) // Return String Descriptor
AT91F_USB_SendData(pUDP, usb_strings[wIndex], MIN(sizeof(usb_strings[wIndex]),
wLength));
else
AT91F_USB_SendStall(pUDP);
break;
case STD_SET_ADDRESS:
#ifdef DEBUG
AT91F_DBGU_Printk("STD_SET_ADDRESS:\n\r");
#endif
AT91F_USB_SendZlp(pUDP);
pUDP->UDP_FADDR = (AT91C_UDP_FEN | wValue);
pUDP->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0;
break;
case STD_SET_CONFIGURATION:
#ifdef DEBUG
AT91F_DBGU_Printk("STD_SET_CONFIGURATION:\n\r");
#endif
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_ISO_IN) :
0;
break;
case STD_GET_CONFIGURATION:
#ifdef DEBUG
AT91F_DBGU_Printk("STD_GET_CONFIGURATION:\n\r");
#endif
AT91F_USB_SendData(pUDP, (char *) &(pCdc->currentConfiguration),
sizeof(pCdc->currentConfiguration));
break;
case STD_GET_STATUS_ZERO:
#ifdef DEBUG
AT91F_DBGU_Printk("STD_GET_STATUS_ZERO:\n\r");
#endif
wStatus = 0;
AT91F_USB_SendData(pUDP, (char *) &wStatus, sizeof(wStatus));
break;
case STD_GET_STATUS_INTERFACE:
#ifdef DEBUG
AT91F_DBGU_Printk("STD_GET_STATUS_INTERFACE:\n\r");
#endif
wStatus = 0;
AT91F_USB_SendData(pUDP, (char *) &wStatus, sizeof(wStatus));
break;
case STD_GET_STATUS_ENDPOINT:
#ifdef DEBUG
AT91F_DBGU_Printk("STD_GET_STATUS_ENDPOINT:\n\r");
#endif
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:
#ifdef DEBUG
AT91F_DBGU_Printk("STD_SET_FEATURE_ZERO:\n\r");
#endif
AT91F_USB_SendStall(pUDP);
break;
case STD_SET_FEATURE_INTERFACE:
#ifdef DEBUG
AT91F_DBGU_Printk("STD_SET_FEATURE_INTERFACE:\n\r");
#endif
AT91F_USB_SendZlp(pUDP);
break;
case STD_SET_FEATURE_ENDPOINT:
#ifdef DEBUG
AT91F_DBGU_Printk("STD_SET_FEATURE_ENDPOINT:\n\r");
#endif
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:
#ifdef DEBUG
AT91F_DBGU_Printk("STD_CLEAR_FEATURE_ZERO:\n\r");
#endif
AT91F_USB_SendStall(pUDP);
break;
case STD_CLEAR_FEATURE_INTERFACE:
#ifdef DEBUG
AT91F_DBGU_Printk("STD_CLEAR_FEATURE_INTERFACE:\n\r");
#endif
AT91F_USB_SendZlp(pUDP);
break;
case STD_CLEAR_FEATURE_ENDPOINT:
#ifdef DEBUG
AT91F_DBGU_Printk("STD_CLEAR_FEATURE_ENDPOINT:\n\r");
#endif
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:
#ifdef DEBUG
AT91F_DBGU_Printk("SET_LINE_CODING:\n\r");
#endif
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:
#ifdef DEBUG
AT91F_DBGU_Printk("GET_LINE_CODING:\n\r");
#endif
AT91F_USB_SendData(pUDP, (char *) &line, MIN(sizeof(line), wLength));
break;
case SET_CONTROL_LINE_STATE:
#ifdef DEBUG
AT91F_DBGU_Printk("SET_CONTROL_LINE_STATE:\n\r");
#endif
pCdc->currentConnection = wValue;
AT91F_USB_SendZlp(pUDP);
break;
default:
#ifdef DEBUG
AT91F_DBGU_Printk("INVALID CODE:\n\r");
#endif
AT91F_USB_SendStall(pUDP);
break;
}
}