gpt4 book ai didi

c++ - 使用 Windows USB 虚拟 Com 端口识别断开连接事件

转载 作者:可可西里 更新时间:2023-11-01 09:29:11 24 4
gpt4 key购买 nike

我正在开发一个使用虚拟串行端口设备驱动程序与 USB 设备通信的应用程序。我们遇到过这样一种情况,如果在串口句柄打开时设备被拔掉(或死机),那么在串口句柄关闭后重新连接的唯一方法是拔掉设备,然后再插回。

如果我能够足够快地检测到故障,则有潜在的解决方法。问题在于,在这些条件下,以下函数调用不会报告错误:

根据我的经验,当设备被拔掉时唯一返回错误的函数是 WriteFile 。可以理解,我真的不想为了测试端口连接是否仍然有效而编写无意义的数据。

我的问题是是否有一些方法可以用来确定端口连接是否仍然有效。

如果对我正在做的事情有任何疑问,下面的代码片段显示了我的端口轮询线程正在做什么:

// set up the communications timeouts
COMMTIMEOUTS timeouts;
if (!GetCommTimeouts(port_handle, &timeouts))
throw OsException(my_strings[strid_get_comm_timeouts_failed].c_str());

timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
timeouts.ReadTotalTimeoutConstant = 10;
timeouts.WriteTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 10000;
if(!SetCommTimeouts(port_handle, &timeouts))
throw OsException(my_strings[strid_set_comm_timeouts_failed].c_str());

on_open();

// we need to set a base for the carrier detect signal. This will be used to determine
// when the signal "changes" while the loop executes
bool carrier_detect_set = false;
uint4 modem_status = 0;

if(!GetCommModemStatus(port_handle, &modem_status))
throw OsException(my_strings[strid_get_modem_status_failed].c_str());
if(modem_status & MS_RLSD_ON)
carrier_detect_set = true;

// we are now ready to enter the main service loop for this thread.
OVERLAPPED io_control;
memset(&io_control, 0, sizeof(io_control));
while(!should_close)
{
// we need to check to see if any comm errors have occurred
uint4 comm_errors = 0;
if(!ClearCommError(port_handle, &comm_errors, 0))
throw OsException(my_strings[strid_clear_comm_errors_failed].c_str());
if(comm_errors != 0)
on_comm_errors(comm_errors);

// we also need to determine if the carrier detect line has changed
modem_status = 0;
if(!GetCommModemStatus(port_handle, &modem_status))
throw OsException(my_strings[strid_get_modem_status_failed].c_str());
if(carrier_detect_set && (modem_status & MS_RLSD_ON) == 0)
on_carrier_detect_change(false);
else if(!carrier_detect_set && (modem_status & MS_RLSD_ON) != 0)
on_carrier_detect_change(true);

// we will now execute any command that might be waiting
command_handle command;
commands_protector.lock();
while(!commands.empty())
{
command = commands.front();
commands.pop_front();
commands_protector.unlock();
command->execute(this, port_handle, false);
commands_protector.lock();
}
commands_protector.unlock();

// now we will try to write anything that is pending in the write queue
fill_write_buffer(tx_queue);
while(!tx_queue.empty() && !should_close)
{
uint4 bytes_avail = tx_queue.copy(tx_buff, sizeof(tx_buff));
uint4 bytes_written = 0;

rcd = WriteFile(port_handle, tx_buff, bytes_avail, &bytes_written, &io_control);
if(!rcd || bytes_written == 0)
throw Csi::OsException(my_strings[strid_write_failed].c_str());
if(rcd)
{
SetLastError(0);
if(bytes_written)
{
tx_queue.pop(bytes_written);
on_low_level_write(tx_buff, bytes_written);
}
if(bytes_written < bytes_avail)
throw OsException(my_strings[strid_write_timed_out].c_str());
}
}

// we will now poll to see if there is any data available to be written
uint4 bytes_read = 0;

rcd = ReadFile(port_handle, rx_buff, sizeof(rx_buff), &bytes_read, &io_control);
if(rcd && bytes_read)
on_low_level_read(rx_buff, bytes_read);
else if(!rcd)
throw OsException(my_strings[strid_read_failed].c_str());
}

我在使用重叠 I/O 时也遇到了同样的问题。

最佳答案

我可以通过添加以下代码来检测端口故障:

while(!should_close)
{
// we will attempt to get and then set the comm state each time the loop repeats.
// This will hopefully allow use to verify that the port is still valid.
if(tx_queue.empty())
{
DCB dcb;
init_dcb(&dcb);
if(!GetCommState(port_handle, &dcb))
throw OsException(my_strings[strid_get_modem_status_failed].c_str());
if(!SetCommState(port_handle, &dcb))
throw OsException(my_strings[strid_get_modem_status_failed].c_str());
}

我担心在每个轮询循环中执行此测试的开销。我可能会尝试将其与 RegisterDeviceNotification 结合使用正如 MSalters 所建议的那样。

红利阅读

关于c++ - 使用 Windows USB 虚拟 Com 端口识别断开连接事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20713207/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com