By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,247 Members | 1,057 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,247 IT Pros & Developers. It's quick & easy.

USB communications using StreamReader and StreamWriter

P: n/a
I'm doing some USB communications in C# and am running into a minor
annoyance. I'm using the Windows API CreateFile function to get a
SafeFileHandle, which I then stuff into a FileStream and from there
into StreamReader and StreamWriter objects. The StreamReader is
working beautifully, but the StreamWriter isn't. If I convert the
StreamWriter.BaseStream back to a FileStream and use its
SafeFileHandle in the Windows API WriteFile function to write the data
then everything works perfectly, but that defeats the purpose of
having the StreamWriter in the first place. I want to just use the
StreamWriter.Write() function. Is there something I'm doing
incorrectly? Here's some random excerpts from my code so you can sort
of see what I'm doing. The WnAPIWrapper is just my wrapper for
getting C# friendly objects from the Windows API:

// Get the input and output streams to the USB device from the Windows
API
// Basically just gets a SafeFileHandle to the USB device and puts it
into a FileStream
StreamReader fPipeIn = new
StreamReader(WinAPIWrapper.GetFileStreamFromGuid(D eviceGuid,
@"\PIPE00"));
StreamWriter fPipeOut = new
StreamWriter(WinAPIWrapper.GetFileStreamFromGuid(D eviceGuid,
@"\PIPE01"));

// At this point I can do fPipeIn.ReadLine() and it works very well

// Create the data to send to the device
int command = 11;
byte[] data = new byte[1]{(byte)command};

// This method does NOT work. Why? fPipeOut is set to AutoFlush by
the way
fPipeOut.Write(data);

// This method, accessing the Windows API WriteFile function directly
with the FileStream.SafeFileHandle, works just fine
WinAPIWrapper.WriteToStream((FileStream)fPipeOut.B aseStream, data);

Any help is much appreciated. I don't NEED to use the StreamWriter
since I have a method that works, but it would be cleaner and nicer if
I could.

Thanks!
Stu
Jul 15 '08 #1
Share this Question
Share on Google+
3 Replies


P: n/a
st*******@gmail.com wrote:
<snip>
// Create the data to send to the device
int command = 11;
byte[] data = new byte[1]{(byte)command};

// This method does NOT work. Why? fPipeOut is set to AutoFlush by
the way
fPipeOut.Write(data);
You're actually calling the StreamWriter.Write(object) overload, because
StreamWriter has no method for writing a byte[] (it's character-oriented,
not byte-oriented).

This ends up calling .ToString() on "data", which yields "System.Byte[]"...
This is one reason not to like overloads. (The moral here is actually not to
declare an overload that takes an "object" along with more specific
overloads. Unfortunately, it's too late now.)

You'll want to call it like this instead:

fPipeOut.Write((char) 11);

or use a char[], but not a byte[].

Beware that this method simply *does not work* for bytes 127, because
these will end up encoded in UTF-8. If you want to write arbitrary bytes,
you shouldn't use StreamWriter but instead operate directly on the Stream.
You can convert (portions of) byte arrays with the Encoder classes. The same
caveat applies to using StreamReader.

--
J.
Jul 15 '08 #2

P: n/a
Thanks, that worked perfectly. Now I'm having some issues with the
StreamReader. When I send a command to the device to stop streaming,
the StreamReader hangs. I've tried ReadLine, ReadToEnd,
DiscardBufferedData. They all hang when the device stops streaming.
Anything I'm doing wrong? I would think if there is nothing to read
then ReadLine would just return a blank string... I suppose the
device could be closing its outbound USB port thus severing the
connection, would that cause the StreamReader to hang? I was hoping
it might more gracefully wait for the stream to open again.
Jul 16 '08 #3

P: n/a
On Wed, 16 Jul 2008 09:53:29 -0700, <st*******@gmail.comwrote:
Thanks, that worked perfectly. Now I'm having some issues with the
StreamReader. When I send a command to the device to stop streaming,
the StreamReader hangs. I've tried ReadLine, ReadToEnd,
DiscardBufferedData. They all hang when the device stops streaming.
Anything I'm doing wrong?
That depends. But it sounds like your USB source doesn't provide an "end
of stream" indication when it's done. That's not actually all that
surprising to me. I don't know much about USB i/o, but assuming it's like
regular serial interfaces, it just doesn't have the idea of an "end of
stream".

DiscardBufferedData() is irrelevant (has nothing at all to do with the
question). ReadToEnd() won't return until the stream ends. Even
ReadLine() won't return until a full line has been received. If no more
data is sent, there's no way for a full line to be received. So either of
those read methods will simply block indefinitely.

Ideally, the _data_ in the stream would include some kind of termination
indication. If so, then you simply need to watch for that data, and close
the stream yourself when you see it.

Otherwise, you are probably going to have to make some assumptions about
the definition of "end of stream". Most likely in the form of a timeout.
You can use a timer, restarting it each time you successfully read some
data. Once the timer finally expires (i.e. you have not received any data
after the specified amount of time), you can then assume that the device
is done sending and close the stream at that point.

Again, I'm unfamiliar with USB i/o, but I suspect that if you've got one
thread blocked on a call to ReadLine() or similar, closing the stream will
cause that call to complete with an exception, allowing you to catch the
exception and correctly detect the pseudo-"end of stream" you've created.

Finally, I'd like to suggest that you seriously consider taking Jeroen's
advice to switch to using a regular Stream. My understanding is that your
stream is not just character input, but rather also includes binary data.
If this is the case, I think you will have more reliable, more
maintainable code by handling the character data yourself with a regular
Stream than by trying to shoe-horn binary data into the character-based
StreamWriter/StreamReader classes. (Though, the "end of stream" issue as
described above will be basically the same).

Pete
Jul 16 '08 #4

This discussion thread is closed

Replies have been disabled for this discussion.