2

我正在为 .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 。在控制台上显示“无响应”后不久。

4

0 回答 0