EmbeddedRelated.com
Forums

problem with USB CDC

Started by "Marcio Campos Lima(Net Open)" July 27, 2007
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;

}

}