我正在为 .NET 服务对象开发即插即用版本的 POS。我有一个 FTDI 设备,上面有 2 个设备。一种是MSR,另一种是RFID。为了快速赶上 .NET 的 POS 支持即插即用,如果你给它一个硬件 ID。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(在设备管理器和 Microsoft 测试应用程序中都有 2 个设备具有确切名称,所以我还是在猜测)并且发送该命令没有让 MSR 响应(对于明显的原因,它不是 RFID 设备)。根据 MSDN 站点,读取命令会阻塞,直到从我的流中读取至少一个字节。这是一个问题,因为 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 。在控制台上显示“无响应”后不久。