Reading a Linux device with fstream - c++

I'm attempting to get feedback from some hardware that is used over USBTMC and SCPI.
I can read and write to the device using /dev/usbtmc0 in a C++ [io]fstream, alternating by reading and writing to send and receive messages. Most commands are terminated by a single newline, so it's easy to tell when the end of a response is received. The simplified code I'm using for that is:
fstream usb;
usb.open("/dev/usbtmc0", fstream::in);
if (usb.good())
{
string output;
getline(usb, output);
usb.close();
// Do things with output
}
// Additional cleanup code...
There is, however, one thing that is escaping me, and it's defined in the SCPI/IEEE specification as "*LRN?". When sent, the connected device will send back arbitrary data (actual wording from the specification) that can be used to later reprogram the device should it get into a weird state.
The issue with the response message of this LRN command is that it contains one or more newlines. It does properly terminate the entire message with a newline, but the fact that there are newlines embedded makes it really tricky to work with. Some hardware will prefix the payload with a length, but some don't.
When reading data from the hardware, there is a 5 second timeout built into the Linux usbtmc kernel driver that will block any read calls if you try to read past what's available.
Using fstream::eof doesn't seem to return anything useful. It acts much like a socket. Is there a way that I can read all data on the device without knowing about its length, termination, and while avoiding a kernel timeout?

The problem with using fstream for this is that fstream has internal buffering, there's no 1:1 correlation between device fileOps->read calls and fstream operations.
For interacting with device drivers, you really need to use the low-level open, read, write functions from unistd.h and fcntl.h.

Related

Is it possible to wrap existing TCP/OpenSSL session with `iostream`?

I use custom code to create SSL connection over native Berkeley sockets interface. I need to wrap the resulted socket with iostream to use existing algorithms written in C++ with these sockets data.
Is there any easy way to do it without need to implement stream and streambuf from scratch?
I learned boost::iostreams and boost::asio.
I didn't find any way to wrap existing OpenSSL session with boost::asio. Or may be anyone knows how to do that?
After boost:asio I concentrated my research on boost:iostreams.
boost::iostreams looks like good idea, however, its problem is that it uses read buffering. So, if we need to read just 1 byte from SSL session, it asks the TCP device to read 4 kilobytes and results in timeout. From the other hand, when I set buffer size to 0, boost::iostreams start to call write method for each byte, so when I try to write 10 bytes to stream, it calls SSL_write 10 times. TCP device itself can not use write buffering, because there are no way to forward flush method to device, so application level protocol may expect that data is sent to another peer while the data remains in output buffer.
So, we need unbuffered read and buffered flushable write; is that possible with boost::iostreams?
I found solution myself.
First of all, it is required to mark the device as flushable. Because there are not ready-made template for such device, you have to inherit device<dual_use, Ch> and override its category with multiple inheritance:
struct category : device<dual_use, Ch>::category, flushable_tag
Now when you will call flush on stream, it will forward the call to your device.
Next step is to disable stream own buffering (i. e. call open with 2nd and 3rd parameters equal to 0).
In such configuration boost will write to device each byte of data separatelly. However, you can implement buffering on device level, and flush the buffer on flush call.

C++ Stream interface in Linux

I have a program in C++ which runs a loop like this, grabbing frames from a video device, using a proprietary driver which I have no access to.
while(true) {
mybuf = getNextFrame(); // blocks
}
I would like to build some logic using other programming languages, so I was thinking of using the following interface. (I need only Linux support)
I was thinking of having a file somewhere, like:
/my/video/device
And every time I call read() on it, it would give me the current frame. Also, if I call read() again, I would like it to block until the next frame is available and return that for me. Also, if I don't call open() for awhile, I don't want the frames in-between to be buffered.
What would be the best approach?
I tried to use FUSE to implement a filesystem, but it was trying to seek inside the file, if it was a regular file, and would only read up to the size I specified for the file. I then made a character device, but it would never call my read() function, instead it would say permission denied...
I was thinking about trying CUSE, or something along the lines. Am I over complicating things? I just need to be able to work with a stream of frames which are constantly coming from my C++ loop, but I want to parse them in a different language, like Python or Go. I also do not want to mix the compilation of my C++ code with Go or python, I want the two to be completely separate. I thought having some sort of file API between the two would make things easier. What would be a good way of handling this?
I would write the program using named pipes. One thing to keep in mind is that if the recieving end disconnects in the middle of a write the server will recieve a SIGPIPE signal and unless this signal is handled or blocked the server will be terminated.

C/C++ server, communicating by stdin/stdout with clients (blocking on stdin until a number of bytes has been read)

This is a question about inter process communication via stdin/stdout.
The problem is I have a COM library, which I wasn't able to use with any Java-COM bridge (one particular function always causes core dump). But I was able to use it from a C++ program.
So I decided to make a wrapper server program in C++ to make those calls for me, and communicate with it from Java via stdin/stdout, but I'm facing a problem here.
I've decided to use protobufs for communicating messages, the main problem is reading input on the C++ side. I need a method, that will block until a certain amount of bytes is written to stdin for it to read.
The idea was to use google's protobufs, and set up communication like this:
C program starts an infinite loop, blocking on STDIN input, waiting to get 4 bytes in, which would be the length of the incoming message.
Then it blocks to get the whole message (raw byte count is known)
Parse the message with protobuf
Do work
Write output to stdout (probably in the same manner, prepending the message with the number of bytes incoming)
Java clinet reads this using DataStream or something like this and deciphers using protobufs as well
Setting up this two way communication turned out to be quite a lot harder, than I would have thought, thanks to my lack of knowledge of C++ and Windows programming (I compile it using MSVS2013 Community, and there are so many windows specific marcos/typedefs from all this COM code).
Is there some 3rd party lib, that can make creation of such a simple server, well, actually, simple?
PS: can be C, can be C++, I just need it to run on Windows.
A relatively simple message handling loop might look like this.
However you should really check the return value of both of the reads and handle errors there.
void read_and_process_message(void) {
while(true) {
long nMessageBytes;
read(stdin, &nMessageBytes, sizeof(long));
//Convert from network byte-order to local byte order
nMessageBytes = ntohl(nMessageBytes);
char * buffer = malloc(nMessageBytes);
read(stdin, buffer, nMessageBytes);
// Do something with your buffer and write to stdout.
}
}

In C/C++ I want to write to the same pipe multiple times

I have a program that creates pipes between two processes. One process constantly monitors the output of the other and when specific output is encountered it gives input through the other pipe with the write() function. The problem I am having, though is that the contents of the pipe don't go through to the other process's stdin stream until I close() the pipe. I want this program to infinitely loop and react every time it encounters the output it is looking for. Is there any way to send the input to the other process without closing the pipe?
I have searched a bit and found that named pipes can be reopened after closing them, but I wanted to find out if there was another option since I have already written the code to use unnamed pipes and I haven't yet learned to use named pipes.
Take a look at using fflush.
How are you reading the other end? Are you expecting complete strings? You aren't sending terminating NULs in the snippet you posted. Perhaps sending strlen(string)+1 bytes will fix it. Without seeing the code it's hard to tell.
Use fsync. http://pubs.opengroup.org/onlinepubs/007908799/xsh/fsync.html
From http://www.delorie.com/gnu/docs/glibc/libc_239.html:
Once write returns, the data is enqueued to be written and can be read back right away, but it is not necessarily written out to permanent storage immediately. You can use fsync when you need to be sure your data has been permanently stored before continuing. (It is more efficient for the system to batch up consecutive writes and do them all at once when convenient. Normally they will always be written to disk within a minute or less.) Modern systems provide another function fdatasync which guarantees integrity only for the file data and is therefore faster. You can use the O_FSYNC open mode to make write always store the data to disk before returning.

WinApi get number of available bytes from a USB port?

Is there a way to check the number of bytes available from a USB device (printer in our case)?
We're using CreateFile and ReadFile and WriteFile for IO communications with our USB device, which works. But We can't figure out how much data is available without actually doing a read. We can't use GetFileSize, as even the documentation says you can't use it for a :
"nonseeking device such as a pipe or a communications device"...
So that doesn't work. Any suggestions? Are we doing our USB I/O incorrectly? Is there a better way to Read/Write to USB?
You first need to open up the port in asynchronous mode. To do that, pass the flag FILE_FLAG_OVERLAPPED to CreateFile. Then, when you call ReadFile, pass in a pointer to an OVERLAPPED structure. This does an asynchronous read and immediately returns ERROR_IO_PENDING without blocking (or, if the OS already has the data buffered, you might get lucky and get a successful read -- be prepared to handle that case).
Once the asynchronous I/O has started, you can then periodically check if it has completed with GetOverlappedResult.
This allows you to answer the question "are X bytes of data available?" for a particular value of X (the one passed to ReadFile). 95% of the time, that's good enough, since you're looking for data in a particular format. The other 5% of the time, you'll need to add another layer of abstraction top, where you keep doing asynchronous reads and store the data in a buffer.
Note that asynchronous I/O is very tricky to get right, and there's a lot of edge cases to consider. Carefully read all of the documentation for these functions to make sure your code is correct.
Can you use C#? If so you can access the USB port using System.IO.SerialPort class, and then set up a DataReceived event handler for incoming data. There is a BytesToRead property that tells you how much data is waiting to be read.
All of this must be available in native code, if I can find it I'll edit this.
EDIT: the best I can find for native is ReadPrinter - I don't see how to check if data is there, this will block if it's not.