This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

USB CDC enumeration problem with XP

Hello,

I'm using a MAX3420E in order to comm a PCB with Atmel microcontroller, with a PC using USB. In windows vista, the PC recognizes a Serial (Virtual) Port and works right, but when I try it in Windows XP, it seems that PC doesn't recognizes the device.

It appears in the device manager as "unknown device" with VID_0000&PID_0000...

I've been searching for a similar post, and found one that had the same problem VID_0000, but the last message does't give any solution...

Any clue? Thank you very much in advance.

The descriptors I use are list below:

// DESCRIPTORS
const unsigned char DD[]=
// DEVICE Descriptor
{0x12, // bLength = 18d
0x01, // bDescriptorType = Device (1)
0x10,0x01, // bcdUSB(L/H) USB spec rev (BCD)
0x02,0x00,0x00, // bDeviceClass, bDeviceSubClass, bDeviceProtocol (descrito en Interface Descriptor)
0x40, // bMaxPacketSize0 EP0 is 64 bytes
0x6A,0x0B, // idVendor(L/H)--Maxim is 0B6A (2922 en decimal)
0x46,0x53, // idProduct(L/H)--5346 (21318 en decimal)
0x00,0x01, // bcdDevice--1234
1,2,3, // iManufacturer, iProduct, iSerialNumber
1}; // bNumConfigurations

const unsigned char CD[]=
// CONFIGURATION Descriptor
{0x09, // bLength
0x02, // bDescriptorType = Config
67,0x00, // wTotalLength(L/H) = Nº Bytes (67[0x43}) (Sin cabeceras 48[0x30]) 0x4300
0x02, // bNumInterfaces = 2
0x01, // bConfigValue
0x00, // iConfiguration
0xA0, // bmAttributes. b7=1 b6=NO self-powered b5=RWU supported (1 1 1 0 0 0 0 0)
0xFA, // MaxPower is 200 ma

// INTERFACE Descriptor
0x09, // length = 9
0x04, // type = IF
0x00, // InterFace Number = 0
0x00, // bAlternate Setting
0x01, // bNum Endpoints = 1 IN
0x02, // bInterfaceClass = 2 Communication
0x02, // bInterfaceSubClass = 2
0x01, // bInterfaceProtocol =1 (SubClass ACM=Abstract Control Mode, InterfaceProtocol=V.25ter, common AT commands)
0x00, // iInterface

// Header Functional Descriptor (marks beginning of the concatenated set of Functional Descriptors)
0x05, // bFunctionLength, Descriptor size in bytes --[18] --[48]
0x24, // bDescriptorType, CS_INTERFACE
0x00, // bDescriptorSubtype, Header Functional Descriptor
0x10,0x01, // bcdCDC, CDC specification release number in BCD format ([0x10, 0x01])

// Call Management Functional Descriptor
0x05, // bFunctionLength, Descriptor size in bytes
0x24, // bDescriptorType, CS_INTERFACE
0x01, // bDescriptorSubtype, Call Management Functional Descriptor
0x03, // bmCapabilities, Device doesn't call management itself (0->3)
0x01, // bDataInterface, Interface used for call management

// Abstract Control Management Functional Descriptor
0x04, // bDescriptorLength, Descriptor size in bytes
0x24, // bDescriptorType, CS_INTERFACE
0x02, // bDescriptorSubtype, Abstract Control Management Functional Descriptor
0x06, // bmCapabilities, Support for the GET/SET_LINE_CODING, BREAK & SET_CONTROL_LINE_STATE

// Union Functional Descriptor
0x05, // bFunctionLength, Descriptor size in bytes
0x24, // bDescriptorType, CS_INTERFACE
0x06, // bDescriptorSubtype, Union Functional Descriptor
0x00, // bMasterInterface, The controlling interface for the union (bInterfaceNumber of a Communication or Data Class interface in this configuration)
0x01, // bSlaveInterface0, The controlled interace in the union (bInterfaceNumber of an interface in this configuration)

Functional Descriptor*****************
// Endpoint Descriptor EP3-IN
0x07, // bLength
0x05, // bDescriptorType (Endpoint)
0x83, // bEndpointAddress (EP3 IN)
0x03, // bmAttributes (interrupt = 3)
0x40,0x00, // wMaxPacketSize (64[0x0040])
0x02, // bInterval, Maximum latency (0x02)

// INTERFACE Descriptor
0x09, // length = 9 --[44]
0x04, // type = IF
0x01, // InterFace Number = 1
0x00, // bAlternate Setting
0x02, // bNum Endpoints = 2 (IN&OUT)
0x0A, // bInterfaceClass = A (Data)
0x00,0x00, // bInterfaceSubClass, bInterfaceProtocol (SubClass ACM=Abstract Control Mode, InterfaceProtocol=V.25ter, common AT commands)
0x00, // iInterface

// Endpoint Descriptor EP1-OUT
0x07, // bLength
0x05, // bDescriptorType (Endpoint)
0x01, // bEndpointAddress (EP1-OUT)
0x02, // bmAttributes (bulk = 2)
0x40,0x00, // wMaxPacketSize (64[0x40])
0x00, // bInterval (0x00)

// Endpoint Descriptor EP2-IN
0x07, // bLength
0x05, // bDescriptorType (Endpoint)
0x82, // bEndpointAddress (EP2-IN)
0x02, // bmAttributes (bulk = 2)
0x40,0x00, // wMaxPacketSize (64[0x40])
0x00, // bInterval (0x00)
};

// STRING descriptors. An array of string arrays

const unsigned char strDesc[][64]= {
// STRING descriptor 0--Language string
{ 0x04, // bLength
0x03, // bDescriptorType = string
0x09,0x04 // wLANGID(L/H) = English-United Sates
},
// STRING descriptor 1--Manufacturer ID
{ 34, // bLength (0x2C para 23 (incluyendo tamaño y tipo??)
0x03, // bDescriptorType = string
'x',0,
'x',0,
'x',0,
'x',0,
' ',0,
'x',0,
'x',0,
'x',0,
'x',0,
'x',0,
'x',0,
'x',0,
'x',0,
'x',0,
'x',0,
'x',0,// text in Unicode
},
// STRING descriptor 2 - Product ID
{ 8, // bLength
0x03, // bDescriptorType = string
'X',0,
'X',0,
'X',0,
},

// STRING descriptor 3 - Serial Number ID
{ 8, // bLength
0x03, // bDescriptorType = string
'X',0,
'X',0,
'X',0,
}};

const unsigned char SerialConf[]=
{ 0x00,0xE8,0x03,0x00, // dwDTFRate. Baudrate (9600hex->38400 baud)
0, // bCharFormat. 1 Stop bit
0, // bParityType: none
8, // Number of data bits: 8
};

Parents
  • Hello,

    I just copy send descriptor function and try to change tabulations...but it's not very 'readable', but if you copy the code to an empty text file, you could read it clear. I Hope this will be useful ;)

    Greetings.

    void send_descriptor(void)
    {
            static WORD sendlen,desclen;
            BYTE *pDdata=NULL;                                      // pointer to ROM Descriptor data to send
            bool send_ZLP=FALSE;                            // Zero Length packet Flag
    
            desclen = 0;                                            // check for zero as error condition (no case statements satisfied)
            switch (SUD[wValueH])                           // wValueH is descriptor type
            {
            case  GD_DEVICE:
                  /*if(SUD[wLengthL]>DD[0])*/ desclen = DD[0];   // descriptor length
                              //else desclen = SUD[wLengthL];
                  pDdata = (BYTE *) DD;
                  break;
            case  GD_CONFIGURATION:
                  if(SUD[wLengthL]>CD[2]) desclen = CD[2];       // Config descriptor includes interface, header and ep descriptors (67 Bytes [0x0043])
                              else desclen = SUD[wLengthL];
                              if(SUD[wLengthH]!=0) desclen = CD[2];         // wLengthH=1 (last byte)
                              pDdata = (BYTE *) CD;
                  break;
            case  GD_STRING:
                  desclen = strDesc[SUD[wValueL]][0];   // wValueL=string index, array[0] is the length
                  pDdata = (BYTE *) strDesc[SUD[wValueL]];       // point to first array element
                  break;
            case CS_INTERFACE:
                             if(SUD[wIndexL]==0)    // Interface Number=0. Del EndPoint 2 (interrupción), Communication
                             {
                                    /*if(SUD[wLengthL]>CD[9]) */desclen = CD[9];
                                    //else desclen = SUD[wLengthL];
                                    pDdata = (BYTE *) &CD[9];
                             }
                             else if (SUD[wIndexL]==1)      // Interface Number=1. Del EndPoint 1 (bulk), Datos
                             {
                                    /*if(SUD[wLengthL]>CD[44])*/ desclen = CD[44];
                                    //else desclen = SUD[wLengthL];
                                    pDdata = (BYTE *) &CD[44];
                             }
                                    break;
            }       // end switch on descriptor type
    //
            if (desclen!=0)                          // one of the case statements above filled in a value
            {
                    sendlen = desclen;                      // Send lower size of data
    
                    if((desclen % 64) == 0) send_ZLP=TRUE;  // Send zero length packet Flag Flag para enviar paquete de tamaño 0
                    while(desclen>0)                             // Meanwhile there are data to be sent
                    {
                            if(desclen>64) sendlen=64;   // If there are more than 64 bytes in the packet
                            else sendlen=desclen;           // If there are less than 64 bytes in the packet
                            while(!(rreg(rEPIRQ) & bmIN0BAVIRQ));// Meanwhile output buffer isn't free
                            writebytes(rEP0FIFO,sendlen,pDdata);// Write data to EP_CONTROL FIFO
                            pDdata=(pDdata+sendlen);        // Increments data pointer !! ********(VERY IMPORTANT)*******
                            if(desclen<64) wregAS(rEP0BC,sendlen);       // load EP0BC to arm the EP0-IN transfer & ACKSTAT
                            else wreg(rEP0BC,sendlen);      // load EP0BC to arm the EP0-IN transfer & ACKSTAT
                            desclen-=sendlen;                       // Substract sent data
                    }
                    if(send_ZLP)
                            wregAS(rEP0BC,0);                       // load EP0BC to arm the EP0-IN transfer & ACKSTAT
            }
            else STALL_EP0;  // none of the descriptor types match
    }
    

Reply
  • Hello,

    I just copy send descriptor function and try to change tabulations...but it's not very 'readable', but if you copy the code to an empty text file, you could read it clear. I Hope this will be useful ;)

    Greetings.

    void send_descriptor(void)
    {
            static WORD sendlen,desclen;
            BYTE *pDdata=NULL;                                      // pointer to ROM Descriptor data to send
            bool send_ZLP=FALSE;                            // Zero Length packet Flag
    
            desclen = 0;                                            // check for zero as error condition (no case statements satisfied)
            switch (SUD[wValueH])                           // wValueH is descriptor type
            {
            case  GD_DEVICE:
                  /*if(SUD[wLengthL]>DD[0])*/ desclen = DD[0];   // descriptor length
                              //else desclen = SUD[wLengthL];
                  pDdata = (BYTE *) DD;
                  break;
            case  GD_CONFIGURATION:
                  if(SUD[wLengthL]>CD[2]) desclen = CD[2];       // Config descriptor includes interface, header and ep descriptors (67 Bytes [0x0043])
                              else desclen = SUD[wLengthL];
                              if(SUD[wLengthH]!=0) desclen = CD[2];         // wLengthH=1 (last byte)
                              pDdata = (BYTE *) CD;
                  break;
            case  GD_STRING:
                  desclen = strDesc[SUD[wValueL]][0];   // wValueL=string index, array[0] is the length
                  pDdata = (BYTE *) strDesc[SUD[wValueL]];       // point to first array element
                  break;
            case CS_INTERFACE:
                             if(SUD[wIndexL]==0)    // Interface Number=0. Del EndPoint 2 (interrupción), Communication
                             {
                                    /*if(SUD[wLengthL]>CD[9]) */desclen = CD[9];
                                    //else desclen = SUD[wLengthL];
                                    pDdata = (BYTE *) &CD[9];
                             }
                             else if (SUD[wIndexL]==1)      // Interface Number=1. Del EndPoint 1 (bulk), Datos
                             {
                                    /*if(SUD[wLengthL]>CD[44])*/ desclen = CD[44];
                                    //else desclen = SUD[wLengthL];
                                    pDdata = (BYTE *) &CD[44];
                             }
                                    break;
            }       // end switch on descriptor type
    //
            if (desclen!=0)                          // one of the case statements above filled in a value
            {
                    sendlen = desclen;                      // Send lower size of data
    
                    if((desclen % 64) == 0) send_ZLP=TRUE;  // Send zero length packet Flag Flag para enviar paquete de tamaño 0
                    while(desclen>0)                             // Meanwhile there are data to be sent
                    {
                            if(desclen>64) sendlen=64;   // If there are more than 64 bytes in the packet
                            else sendlen=desclen;           // If there are less than 64 bytes in the packet
                            while(!(rreg(rEPIRQ) & bmIN0BAVIRQ));// Meanwhile output buffer isn't free
                            writebytes(rEP0FIFO,sendlen,pDdata);// Write data to EP_CONTROL FIFO
                            pDdata=(pDdata+sendlen);        // Increments data pointer !! ********(VERY IMPORTANT)*******
                            if(desclen<64) wregAS(rEP0BC,sendlen);       // load EP0BC to arm the EP0-IN transfer & ACKSTAT
                            else wreg(rEP0BC,sendlen);      // load EP0BC to arm the EP0-IN transfer & ACKSTAT
                            desclen-=sendlen;                       // Substract sent data
                    }
                    if(send_ZLP)
                            wregAS(rEP0BC,0);                       // load EP0BC to arm the EP0-IN transfer & ACKSTAT
            }
            else STALL_EP0;  // none of the descriptor types match
    }
    

Children
No data