FileStream.Read() issues a Seek which my USB driver does notimplement.

J

Jen C.

Hi all,
I have developed a custom USB driver based on the USB printer
driver. It works great with Win32 read and write functions. The
driver communicates only through the stream interface, but Seek is not
supported, it just returns a -1.

I have not been able to get reads to work with a .NET program,
however. I am opening a FileStream, and trying to read 64 bytes into
an array of bytes.

It looks to me like .NET is asking my driver for 128 bytes, not 64,
and then tries to do a SEEK which fails, because my driver doesn't
implement Seek.

So my questions are:

1.) Why is it trying to read 128 bytes instead of 64?
2.) Can I make a change to my driver, or two my C# code to tell it to
not try to seek?
3.) Is there a better way to do this? I suppose I could p/invoke to
the Win32 functions but I'd rather not do that.

Here is the Debug log output.
4294889170 PID:3de437e TID:43ab870e 0x83ab897c: >PSO_Open(0x4e670,
0xc0000000, 0x0)
4294889170 PID:3de437e TID:43ab870e 0x83ab897c: <PSO_Open:1
4294889176 PID:3de437e TID:43ab870e 0x83ab897c: >PSO_Read(0xe14166c,
128)
4294889177 PID:3de437e TID:43ab870e 0x83ab897c: PSO_Read timeout due
in 1380 msec
4294889178 PID:3de437e TID:43ab870e 0x83ab897c: <PSO_Read:128
4294889181 PID:3de437e TID:43ab870e 0x83ab897c: PSO_Seek

Here is my code. It just tries to read 64 bytes when I click the
button.

public Form1()
{
InitializeComponent();
m_bufferIncoming = new byte[64];
}
public const string USBDRIVERNAME = "PSO1:";
public byte[] m_bufferIncoming;

FileStream m_driverFileStream;
private void button1_Click(object sender, EventArgs e)
{
try
{
m_driverFileStream = new FileStream(USBDRIVERNAME,
FileMode.Open, FileAccess.ReadWrite,
FileShare.None);
}
catch (Exception eFileException)
{
throw new USBDriverException("Could not open PSO1:
driver" +
eFileException.ToString());
}

try
{
m_driverFileStream.Read(m_bufferIncoming, 0, 64);
}
catch (Exception eRead)
{
throw new USBDriverException("Could not read PSO1: " +
eRead.ToString());
}

}

private void Form1_Closing(object sender, CancelEventArgs e)
{
m_driverFileStream.Close();
}
}
 
G

Guest

I'd alter the XXX_Seek to return TRUE but do nothing. No idea why it's
asking for 128 bytes unless it's something to do with encoding and it's
requesting characters and not bytes. XXX_Read should still work fine if it
requests 128 bytes but only 64 are available - you should populate the array
with 64 bytes and then set the dwBytesRead to 64. I would assume that the
Stream class will handle all that properly then.
 
P

Paul G. Tobey [eMVP]

1) It can ask to read *any* amount of data. If you don't have enough, you
indicate how many you *did* return. It's not up the application code or the
filesystem code to figure out how much data you should be returning, even if
there was some means of doing that for every stream driver. The number of
bytes it's asking for is how many are allocated in the buffer into which you
are supposed to write the data. I presume it's going to cache the extra 64,
if you return them, for the next read that might be coming from your
application code.

2) Probably not. It's probably setting the file pointer to the point at
which no more data was available (to the end of the file). However, either
silently allowing the seek or removing the Seek export from the driver might
do something.

3) Your application code is fine. Your driver code is broken. You could
decide that, hell, you don't care what file position the caller wants, that
doesn't mean anything to you. In that case, just return success and ignore
the parameters to the seek (or remove Seek from the exported functions of
the driver; I don't think that you are required to implement it).

Paul T.

Jen C. said:
Hi all,
I have developed a custom USB driver based on the USB printer
driver. It works great with Win32 read and write functions. The
driver communicates only through the stream interface, but Seek is not
supported, it just returns a -1.

I have not been able to get reads to work with a .NET program,
however. I am opening a FileStream, and trying to read 64 bytes into
an array of bytes.

It looks to me like .NET is asking my driver for 128 bytes, not 64,
and then tries to do a SEEK which fails, because my driver doesn't
implement Seek.

So my questions are:

1.) Why is it trying to read 128 bytes instead of 64?
2.) Can I make a change to my driver, or two my C# code to tell it to
not try to seek?
3.) Is there a better way to do this? I suppose I could p/invoke to
the Win32 functions but I'd rather not do that.

Here is the Debug log output.
4294889170 PID:3de437e TID:43ab870e 0x83ab897c: >PSO_Open(0x4e670,
0xc0000000, 0x0)
4294889170 PID:3de437e TID:43ab870e 0x83ab897c: <PSO_Open:1
4294889176 PID:3de437e TID:43ab870e 0x83ab897c: >PSO_Read(0xe14166c,
128)
4294889177 PID:3de437e TID:43ab870e 0x83ab897c: PSO_Read timeout due
in 1380 msec
4294889178 PID:3de437e TID:43ab870e 0x83ab897c: <PSO_Read:128
4294889181 PID:3de437e TID:43ab870e 0x83ab897c: PSO_Seek

Here is my code. It just tries to read 64 bytes when I click the
button.

public Form1()
{
InitializeComponent();
m_bufferIncoming = new byte[64];
}
public const string USBDRIVERNAME = "PSO1:";
public byte[] m_bufferIncoming;

FileStream m_driverFileStream;
private void button1_Click(object sender, EventArgs e)
{
try
{
m_driverFileStream = new FileStream(USBDRIVERNAME,
FileMode.Open, FileAccess.ReadWrite,
FileShare.None);
}
catch (Exception eFileException)
{
throw new USBDriverException("Could not open PSO1:
driver" +
eFileException.ToString());
}

try
{
m_driverFileStream.Read(m_bufferIncoming, 0, 64);
}
catch (Exception eRead)
{
throw new USBDriverException("Could not read PSO1: " +
eRead.ToString());
}

}

private void Form1_Closing(object sender, CancelEventArgs e)
{
m_driverFileStream.Close();
}
}
 
J

Jen C.

Thank you both for replying with helpful suggestions.

I have changed the driver SEEK code to always return success and not
do anything. That stopped my IOExceptions.

You were right Paul, that it always asks the driver for a minimum of
128 bytes and saves the rest for later.

I read 64 bytes using FileStream.Read() - and Read() returns with 64
bytes just like I asked for.
My driver gets a read request for 128 bytes, and a Seek
..

Then I read another 64 bytes using FileStream.Read(). I get the 2nd
half of the 128 bytes it read before.
This read doesn't ask the driver to do anything.


If I read another 64 bytes, it reads 128 bytes again.

It seems like all sizes greater than 128 result in (driver) reads of
the size I ask for.

OK, I think I can get this work. Thanks again for your help.

-Jenny
 
N

Norbert Unterberg

Jen said:
Thank you both for replying with helpful suggestions.

I have changed the driver SEEK code to always return success and not
do anything. That stopped my IOExceptions.

According to the docs of FileStream, it is
* a buffered stream, that means it does read-ahead
* it supports and uses seeking if the underlying file supports seeking, that
is if the file type reported by the OS is FILE_TYPE_DISK. MAybe you can cheat
the FileStream class by using a filename like @"\\.\myusbdevice"?

You were right Paul, that it always asks the driver for a minimum of
128 bytes and saves the rest for later.

You can set a different buffer size during the FileStream constuction. There are
constructors available that have an "int bufferSize" parameter.
I read 64 bytes using FileStream.Read() - and Read() returns with 64
bytes just like I asked for.
My driver gets a read request for 128 bytes, and a Seek
.

Then I read another 64 bytes using FileStream.Read(). I get the 2nd
half of the 128 bytes it read before.
This read doesn't ask the driver to do anything.

Sure, that is the effect of buffering.

Norbert
 
Top