SetupComm, SetCommState, SetCommTimeouts fail with USB device

泄露秘密 提交于 2020-01-15 15:30:08

问题


i am opening a USB device:

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:

  • SetupComm (set receive and transit buffer sizes)
  • SetCommState (set flow-control, baud rate, etc)
  • SetCommTimeouts (set timeouts)

Each of these calls with 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 "Universial Serial Device", rather than a "COMM Port"? For example, the user is the one who specifies which port to use:

  • \.\COM5
  • \.\LCLD9

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

  • GetCommModemStatus (with error code 1)
  • ReadFile (with error code 6)
  • PurgeComm (with error code 6)
  • WriteFile (with error code 6)

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


回答1:


No, USB devices do not use these things. If your device is an actual USB-to-RS232 (or other slow serial), then you should be opening the COM port it associated with. Let the drivers handle the work of sending that data.

USB communication is not like COM ports. You can think of it more as an external PCI bus than a simple send-whatever-data-you-want line.




回答2:


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.:

  • \\.\LCLD9\
  • \\.\LCPD6\
  • \\.\LCPD3\

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.



来源:https://stackoverflow.com/questions/20551935/setupcomm-setcommstate-setcommtimeouts-fail-with-usb-device

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!