none
[Solved] CDC driver (SYSGEN_USB_SER) loses bulkin data @ 2kB!? RRS feed

  • Question

  • Hello all,

    We just implemented the Windows CE6 R3 CDC driver (SYSGEN_USB_SER), running on an x86 board. Device is a NXP LPC2368 running LPCUSB stack.

    It seems that the Windows CE CDC driver loses or corrupts bulkin data around the 2kB mark. It's consistent at this point, doesn't depend on time or number of packets. The same client works OK with Windows 7 CDC driver.

    So:

    - is the USB_SER driver just a sample, or an actual supported driver?

    - anyone else have this working, especially on X86?

    - help!

    Thanks :)

    Aaron

    Thursday, July 29, 2010 5:28 AM

All replies

  • Hi,

    I had similar trouble (losing data at high load) with a driver I wrote, see :
    http://groups.google.com/group/microsoft.public.windowsce.platbuilder/browse_thread/thread/3b86033f735dd9b/a9879b580aa09d95?q=cdc+driver+lose+rob

    Besides the multiple receive-listners, we also raised the prio of the receive thread.

    Not sure if the driver that comes with CE has such a thread, but I suspect it will.

    Kind regards,
    Rob
    www.robtso.nl

     

     

     

     

    Thursday, July 29, 2010 9:04 AM
  • This is actually quite a low load, one 40 byte packet every second. It lasts about 1 minute at this rate.

    We have been looking at the kernal debug and USBSER source. It seems there is indeed a 2kB FIFO involved, and when the write point reaches the end of this buffer data is discarded. It looks like the driver actually has no code to write data that overlaps the end of the buffer ...

    Friday, July 30, 2010 12:10 AM
  • So, 40 bytes a second adn 2kB FIFO - now the question is why isn't you application able to read the data out faster that the FIFO fills?

    There could be many possible reasons, including the application is blocked by other threads in the system, that the application is reading to few bytes when it calls ReadFile() and the application isn't calling ReadFile() when bytes are available.


    Bruce Eitman (eMVP)
    Senior Engineer
    Bruce.Eitman AT Eurotech DOT com
    My BLOG http://geekswithblogs.net/bruceeitman

    Eurotech Inc.
    www.Eurotech.com
    Friday, July 30, 2010 12:28 AM
    Moderator
  • Bruce,

    We read the data as it arrives, and it's all normal. There is no problem in our app.

    It's just that, after about 2kB have been read out (40 bytes at a time) from ReadFile, a chunk goes missing from the datastream we know is arriving.

    As I said above, this is obviously a problem in the USBSER driver, when a single bulkin transfer overlaps the end of the 2kB FIFO. We are debugging the driver now.

    Cheers

    Aaron

    Friday, July 30, 2010 1:34 AM
  • OK, in usbser.cpp there is some clearly untested code


    BOOL SerialDataIn::ReceiveInterruptHandler(PUCHAR pRxBuffer,ULONG *pBufflen)
    {
    ...
    if ( IsFrontArmedTransferComplete () ) {
    if (m_dwSegDataDataLen[m_dwCurIndex] == 0) { // Have't update the Transfer Status yet.
    ...
    }
    }

    // Looks like there should be an else here?
    if (m_dwSegDataOffset[m_dwCurIndex] < m_dwSegDataDataLen[m_dwCurIndex] ){ // We have Extra.
    DWORD dwCopyLen = min (dwBufferSize, m_dwSegDataDataLen[m_dwCurIndex] - m_dwSegDataOffset[m_dwCurIndex]) ;
    memcpy(pRxBuffer,m_VirtualAddress + (m_dwSegmentSize*m_dwCurIndex + m_dwSegDataOffset[m_dwCurIndex]) ,dwCopyLen);
    *pBufflen = dwCopyLen;

    // Following line is obviously wrong, should be += dwCopyLen ?
    m_dwSegDataOffset[m_dwCurIndex] += m_dwSegDataOffset[m_dwCurIndex];
    bReturn = TRUE;
    }
    if (m_dwSegDataOffset[m_dwCurIndex]>= m_dwSegDataDataLen[m_dwCurIndex] ){
    CloseFrontArmedTransfer();
    m_dwSegDataOffset[m_dwCurIndex]= m_dwSegDataDataLen[m_dwCurIndex] = 0 ;
    BOOL bResult = BulkOrIntrTransfer(USB_NO_WAIT|USB_SHORT_TRANSFER_OK,
    m_dwSegmentSize,
    m_VirtualAddress+ (m_dwCurIndex * m_dwSegmentSize),
    m_PhysicalAddress.LowPart+(m_dwCurIndex*m_dwSegmentSize),
    SERIAL_DATAIN_COOKIE+m_dwCurIndex);
    ASSERT(bResult==TRUE);
    m_dwCurIndex ++;
    if (m_dwCurIndex>=NUM_OF_IN_TRANSFER)
    m_dwCurIndex = 0;
    }
    }
    }
    Unlock();
    return bReturn;
    }

    • Edited by Aaron Lawrence Friday, July 30, 2010 4:03 AM code formatting
    • Proposed as answer by Shaihi Monday, August 2, 2010 8:47 AM
    Friday, July 30, 2010 4:00 AM
  • Testing shows this fixes the problem.

    Microsoft have confirmed this is a bug in their CDC driver.

    Monday, August 2, 2010 6:45 AM