USB communications using StreamReader and StreamWriter

S

stumorgan

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(DeviceGuid,
@"\PIPE00"));
StreamWriter fPipeOut = new
StreamWriter(WinAPIWrapper.GetFileStreamFromGuid(DeviceGuid,
@"\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.BaseStream, 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
 
J

Jeroen Mostert

// 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.
 
S

stumorgan

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top