windowsserial-portusbcreatefile

SetupComm, SetCommState, SetCommTimeouts fail with USB device


i am opening a USB device:

enter image description here

for communication using CreateFile:

HANDLE hUsb = CreateFile("\\.\LCLD9",
      GENERIC_READ | GENERIC_WRITE, 
      0, 
      null, 
      OPEN_EXISTING, 
      FILE_FLAG_OVERLAPPED, 
      0);

The call succeeds (i.e. hUsb is not equal to INVALID_HANDLE_VALUE). But then it comes time to do what we do with every serial port:

Each of these calls returns a GetLastError() code of 1. E.g.:

SetupComm(hUsb, 1024, 1024);

Why are operations to configure the serial device failing when using a "USB" serial device, but work when using a "virtual COM port"? Do USB devices not support such baud rates, buffers, flow control, and timeouts?

If this is a limitation/feature of Universal Serial devices, how can i detect that a handle refers to a "Universal Serial Device", rather than a "COMM Port"? For example, the user is the one who specifies which port to use:


Other serial functions that fail when talking to Universal Serial Bus serial device:

Which begs the larger question, how do you communicate with a USB device once it's been opened with CreateFile?


Solution

  • Turns out that i don't have to do anything with Comm, because it's not a COM port. The reason my WriteFile was failing was because i was attempting to write to \\.\LCLD9 rather than \\.\LCLD9\.

    The trailing backslash is critical; even though CreateFile returns success both ways.

    void WriteToDisplay(String s)
    {
       //Open the display
       var hLineDisplay = CreateFile("\\.\LCLD9\", GENERIC_WRITE, 0, nil, OPEN_EXISTING, 0, 0);
    
       //Write the command
       DWORD bytesWritten;
       WriteFile(hLineDisplay, s, s.Length, ref bytesWritten, nil);
    
       FileClose(hLineDisplay);
    }
    

    Anyone using Logic Controls LD9000 USB Line Display, the above is how you write to the display.

    After reverse engineering their .NET Line Display driver i will also mention that the name of the port you use, e.g.:

    can be inferred from the full devicePath returned using the Windows Setup APIs. For example, my pole display's full device path is:

    \\?\USB#VID_0FA8&PID_A090#6&DF2EE03&0&1#{A5DCBF10-6530-11D2-901F-00C04FB951ED}
                     \______/
                        |
                    ProductID
    

    The rule is to check the device path for Product IDs. In my case PID_A090 means it will be available as file \\.\LCLD9\. Other product IDs and their associated file paths:

    Contains  DeviceName (trailing backslash is not optional)
    ========  ===============================================
    PID_A030  \\.\LCPD3\
    PID_A060  \\.\LCPD6\
    PID_A090  \\.\LCLD9\
    

    Note: Any code is released into the public domain. No attribution required.