USB Serial Virtual COM Port : Read not working but write works - c++

I use embedded hardware (by TI : Piccolo Control Stick xxx69) which uses FTDI usb to serial converter hardware.
On PC, I have simple VC++ application which tries to communicate to hardware over Virtual COM port (VCOM : typically COM7).
I am able to connect to port properly.
I am able to send data from application/PC to hardware and it is received correctly. (So, Tx on PC is working fine), Application first opens the connection using createfile(... ... ...) API and then uses writefile(.. ... ..) windows apis to write into the port directly.
SURPRISINGLY, I am not able to read from serial port to application. When I call readfile(... ... ...) api, it returns status as TRUE but ZERO bytes are read. I tried using API monitor software, which shows kernel api Ntreadfile(... ... ...), returns error as STATUS_TIMEOUT" [0x00000102]. It is surprising, because write works but read doesn't although data is there on line.
Data is on the line, because when I use normal hyper-terminal software, I am able to read the data correctly form controller and it is visible. [On controller side, it is all right because we can see data on hyper-terminal.
I am not windows programmer, as I deal with micro-controllers. Therefore, some help in terms to pursue this issue would be of great help.
Best Regards,
-Varun
Here is a Reference

Issue is solved. I had to add wait till InQueue > 0 (it means there is atleast 1 byte in receive buffer) or timeout (as safety exit) is over. it would be blocking call but it is OK for my application at the moment. waitComm() did not work well for me here.
sample snippet:
while(1)
{
ClearCommError((HANDLE)*h_drv, (LPDWORD)&Err, &CST);
if((CST.cbInQue >0)||(count >1000000))
break;
count++;
}

Related

Qt modbus serial port flow control handling

I'm writing a small program using QModbusDevice over the serial port (using the QModbusRtuSerialMaster class) and have some problems.
One of the problems seems to be that the flow control of the serial port is incorrect. Checking in a serial port sniffer I see that a working client sets RTS on when it sends requests, and then RTS off to receive replies. When I use QModbusRtuSerialMaster to send messages that doesn't happen.
The message is sent correctly (sometimes, subject for another question) compared to the working client. It's just the control flow that doesn't work and which causes the servers to be unable to reply.
I have set the Windows port settings for the COM-port in question to hardware flow control but it doesn't matter, the sniffer still reports no flow control.
Is there a way to get QModbusRtuSerialMaster to set the flow control as I would like? Or is there a way to manually handle the flow control (which is what the working client does)? Or is the only solution to skip the Qt modbus classes and make up my own using the serial port directly?
A short summary of what I'm doing...
First the initialization of the QModbusRtuSerialMaster object:
QModbusDevice* modbusDevice = new QModbusRtuSerialMaster(myMainWindow);
modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, "COM3");
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, QSerialPort::NoParity);
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, QSerialPort::Baud115200);
modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, QSerialPort::Data8);
modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop);
modbusDevice->setTimeout(100);
modbusDevice->setNumberOfRetries(3);
modbusDevice->connectDevice();
Then how I send a request:
auto response = modbusDevice->sendReadRequest(QModbusDataUnit(QModbusDataUnit::Coils, 0, 1), 1);
QtModbus does not implement an automatic toggling for the RTS line because it expects your hardware to do it on its own (with a dedicated line instead).
This should be the case for most RS485 converters (even cheap ones). You would only need the RTS line if you have a separate transceiver like this one with a DE/~RE input.
If you were on Linux and had some specific hardware you could try to use the RS485 mode to toggle the RTS line for you automatically. But you don't seem to be on Linux and the supported hardware is certainly very limited.
You can also toggle the line manually with port.setRequestToSend(true), see here. But note that depending on the timing needs of the device you are talking too, this software solution might not be very reliable. This particular problem has been discussed at length here. Take a look at the links on my answer too, I made some benchmarks with libmodbus that show good results.
Enabling or disabling flow control on the driver won't have any effect on this issue because this is not actually a flow control problem but a direction control one. Modbus runs on two-wire half-duplex links very often, and that means you need a way to indicate which device is allowed to talk on the bus at all times. The RTS (flow control) from an RS232 port can be used for this purpose as a software workaround.
In the end, it would be much less of a headache if you just replace your transceiver with one that supports hardware direction control. If you have a serial port with an FTDI engine you should be able to use the TXEN line for this purpose. Sometimes this hardware line is not directly routed and available on a pin but you can reroute it with MProg.
I would like to highlight that you did not mention if you are running your Modbus on RS485. I guess it's fair to assume you are, but if you have only a couple of devices next to each other you might use RS232 (even on TTL levels) and forget about direction control (you would be running full-duplex with three wires: TX, RX and GND).

How can I ignore a TCP PSH bit in Windows 7?

I have a C++ program that uses Boost ASIO to communicate with a network device over a TCP socket. The program is working fine on Linux, but with Windows 7 I'm finding that the communication is not working very well. After some experimentation, I found that there's a 0.5-second delay between command and response when communicating with the device using the ASIO example telnet program, even though the response shows up in Wireshark much more quickly.
I gather that the problem is that the network device is not setting the PSH flag after it completes a chunk of data. See: http://smallvoid.com/article/winnt-tcp-push-flag.html.
I need to somehow set up my app so that it receives data from the TCP socket regardless of whether a packet has arrived with the PSH bit set. I know this must be possible because PuTTY can communicate with my device normally. I'd rather not use a registry key to get the effect, because I want to change the behavior only for this one socket, not the entire system.
What do I need to do to get Windows to ignore the PSH flag for this connection?
You could try specifying the MSG_PUSH_IMMEDIATE flag on the receiving side (https://msdn.microsoft.com/en-us/library/windows/desktop/ms741688(v=vs.85).aspx).

How to make interaction kext os x network filter with application?

I am writing network filter kernel extension for os x.
I want to call something like callbacks in kext.
For example in data_in function when I get a tcp packet I want to call this callback from user application. Application changes this packet and I inject it.
How to make this interaction between kext and user application?
First of all, you don't want to block the data_in callback - you should "swallow" the packet, send it to userspace, and when it comes back, re-inject it into the connection.
There are a few ways of exchanging data with userspace processes. The most convenient way for exchanging network packets is probably the kernel control mechanism, which essentially allows you to open a socket connection between a user program and your kext.
Apple used to offer sample source code, "tcplognke" that did something extremely similar, but it seems to have disappeared from their own site. Someone kindly appears to have saved it and is offering it for download - looks OK to me right now, but obviously be cautious about downloading stuff from random websites.

Create virtual serial port in Qt/C++

I would like to create a linux app which appears as a serial port (eg /dev/ttyTEST). This app will listen for commands sent to the port, and respond back.
Is this possible using Qt/C++ ? I haven't done kernel programming so I'm hoping this is possible in user space.
Everything depends on what the application using such device expects.
If /dev/ttyTEST is to behave like a real serial device and respond properly to all ioctl's that set its speed etc., then this can't be done from userspace. It wouldn't be too hard to implement in the kernel space, though.
If /dev/ttyTEST only needs to be a tty, then provide a pseudo tty.
If /dev/ttyTEST is merely to be something another application can write to and read from then socketpair() does it.
If you have control over the application's code, then you can have it check whether the device is a socket pair or a real character device, and ignore the failures of the serial-port-specific APIs on a socket.

Can I write Ethernet based network programs in C++?

I would like to write a program and run it on two machines, and send some data from one machine to another in an Ethernet frame.
Typically application data is at layer 7 of the OSI model, is there anything like a kernel restriction or API restriction, that would stop me from writing a program in which I can specify a destination MAC address and have some data sent to that MAC as the Ethernet payload? Then write a program to listen for incoming frames and grab the frames from a specified source MAC address, extracting the payload of data from the frame?
(So I don't want any other overhead like IP or TCP/UDP headers, I don't want to go higher than layer 2).
Can this be done in C++, or must all communication happen at the IP layer, and can this be done on Ubuntu? Extra love for pointing or providing examples! :D
My problem is obviously I'm new to network programming in c++ and as far as I know, if I want to communicate across a network I have to use a socket() call or similar, which works at an IP layer, so can I write a c++ program to work at OSI layer 2, are there APIs for this, does the Linux kernel even allow this?
As you already mentioned sockets, probably you would just like to use a raw socket. Maybe this page with C example code is of some help.
In case you are looking for an idea for a program only using Ethernet while still being useful:
Wake on LAN in it's original form is quite simple. Note however that most current implementations actually send UDP packets (exploiting that the receiver does not parse for packet headers etc. but just a string in the packet's payload).
Also the use of raw sockets is usually restricted to privileged users. You might need to either
call your program as root
or have it owned by root and setuid bit set
or set the capability for creating raw socket using setcap CAP_NET_RAW+ep /path/to/your/program-file
The last option gives more fine grained privileges (just raw sockets, not write access to your whole file system etc.) than the other two. It is still less widely known however, since it is "only" supported from kernel 2.6.24 on (which came with Ubuntu 8.04).
Yes, actually linux has a very nice feature that makes it easy to deal with layer 2 packets. You can use a TAP device, which allows your userspace program to read/write ethernet traffic through the kernel.
http://www.kernel.org/pub/linux/kernel/people/marcelo/linux-2.4/Documentation/networking/tuntap.txt
http://en.wikipedia.org/wiki/TUN/TAP