我正在为.NET服务对象开发即插即用版POS。我有一台FTDI设备,上面有2个设备。一个是MSR,另一个是RFID。如果你给它一个硬件ID,快速赶上POS for .NET支持即插即用。 FTDI设备的硬件ID为QUADPORT\QUAD_SERIAL_INTERFACE
。所以在我的服务对象(SO)上,我用这个
[HardwareId("QUADPORT\\QUAD_SERIAL_INTERFACE")]
[ServiceObject(DeviceType.Msr, "FTDI Device", "MSR FTDI Device", 1, 8)]
public class FTDIDevice : Msr
{
...
}
在open方法中,我可以查询DevicePath属性,它是正确的DevicePath。作为一个快速测试,以确保它确实通过设备路径与串行端口通信,我打开了一个FileStream到这个设备路径,然后尝试打开两个虚拟COM端口,并确定其中一个有“访问被拒绝”。真棒!我接下来的测试是写入RFID设备,因为我知道大多数所有命令以及如何格式化字节数组以与RFID设备通信。实际上这是我使用的代码。
public override void Open()
{
string str = this.DevicePath;
handle_read = Kernel32.CreateExistingRWFile(str);
FS_read = new FileStream(handle_read, FileAccess.ReadWrite, 9);
Console.WriteLine("File Stream Created, Writing Open Sequence");
byte[] open = { 0xAA, 0xBB, 0x04, 0xFB, 0x00, 0x00, 0x03, 0xF8 };
FS_read.Write(open, 0, open.Length);
//byte[] receive = new byte[11];
//var something = FS_read.Read(receive, 0, receive.Length);
//Console.WriteLine(BitConverter.ToString(receive, 0, something));
//Close the FileStream and the SafeFileHandle
close();
}
private SafeFileHandle handle_read;
private FileStream FS_read;
我第一次运行这段代码时,我选择了MSR(在设备管理器和微软测试应用程序中有2个设备都具有确切的名称,所以无论如何我都在猜测)并且发送该命令没有给我回复MSR(出于显而易见的原因,它不是RFID设备)。根据MSDN站点,Read命令将阻塞,直到从我的流中读取至少一个字节。这是一个问题,因为MSR不响应RFID命令。所以基本上我的程序陷入僵局。我强行关闭程序然后再次启动它并选择了RFID并且读取方法确实返回了RFID的成功响应。
所以我的问题是如何查询Stream以查看我的设备是否有任何响应?我尝试过使用CanRead属性(总是返回true)。我已经尝试使用ReadByte来查看它是否会像文档所说的那样返回-1,但它也会挂起。我尝试使用Length属性,但它抛出一个异常,说Stream不支持搜索。感觉我没有选择,所以我在这里问。有什么建议吗?
修改
汉斯想看看我如何创造我的手柄
internal class Kernel32
{
internal static SafeFileHandle CreateExistingRWFile(string devicePath)
{
return CreateFile(devicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
}
internal const short FILE_ATTRIBUTE_NORMAL = 0x80;
internal const short INVALID_HANDLE_VALUE = -1;
internal const uint GENERIC_READ = 0x80000000;
internal const uint GENERIC_WRITE = 0x40000000;
internal const uint FILE_SHARE_READ = 0x00000001;
internal const uint FILE_SHARE_WRITE = 0x00000002;
internal const uint CREATE_NEW = 1;
internal const uint CREATE_ALWAYS = 2;
internal const uint OPEN_EXISTING = 3;
[DllImport("kernel32.dll", SetLastError = true)]
private static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool ReadFile(SafeFileHandle hFile, byte[] lpBuffer, uint nNumberOfBytesToRead, ref uint lpNumberOfBytesRead, IntPtr lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool WriteFile(SafeFileHandle hFile, byte[] lpBuffer, uint nNumberOfBytesToWrite, ref uint lpNumberOfBytesWritten, IntPtr lpOverlapped);
}
当我看到Hans提出建议时,我正在使用BeginRead,到目前为止,EndRead总是返回0:/
这是代码。
byte[] receive = new byte[11];
IAsyncResult iAR = FS_read.BeginRead(receive, 0, receive.Length, ASyncFileCallBack, receive);
byte[] wildGuess = (byte[])iAR.AsyncState;
Console.WriteLine("Guessing:{0}", BitConverter.ToString(wildGuess));
}
private void ASyncFileCallBack(IAsyncResult result)
{
byte[] buffer = (byte[])result.AsyncState;
int length = FS_read.EndRead(result);
if (length > 0)
Console.WriteLine("Response:{0}", BitConverter.ToString(buffer, 0, length));
else
Console.WriteLine("No Resposne");
}
guessing
总是只是立即吐出11 0。在控制台上显示“无响应”后不久。