我正在构建一个生成DMX输出的应用程序。应用程序通过USB接口将此数据提供给硬件。由于DMX使用RS485协议,因此几乎可以使用任何RS485 USB转串口转换器。我希望我的应用程序可以通过用户编写的插件进行扩展,这些插件继承自我的基类,而不是处理应用程序和接口之间的通信。
所以这是我的问题:
应用程序启动后,当界面插入时,我无法与界面通信。我使用WqlEventQuery
和ManagementEventWatcher
类来检测usb事件(插件和输出)和加载&相应地卸载我的类。调试时我注意到驱动程序类确实看到了设备,但无法从中读取(例如序列号)。在端口可用之前我是否需要重置一些东西?
在status
之后FT_INVALID_HANDLE
设置为FT_Open
,这意味着永远不会完成通信。
FTD2xx类正常工作,除非在启动应用程序后插入接口。
SerialPort
类打开,关闭和处理一次。这是为什么?
var ports = SerialPort.GetPortNames();
SerialPort port = new SerialPort(ports[0]);
port.Open();
port.Close();
port.Dispose();
-> Following code works
<小时/> 的代码:
public abstract class Driver
{
public abstract string FullName { get; set; }
public virtual string Description { get; set; }
public abstract string[] HardwareIDs { get; set; }
public virtual int FrameRate { get; set; }
public Driver(int framerate)
{
this.FrameRate = framerate;
}
public abstract void Start();
public abstract void Stop();
public abstract void SetDMXValue(int channel, byte value);
}
FTD2xx驱动程序类
public class FTD2XX : Driver
{
public override string FullName
{
get { return "FTD2XX Usb-Interface"; }
set {}
}
public override string Description
{
get { return "Driver for the FTD2xx usb-to-dmx interface"; }
set {}
}
public override string[] HardwareIDs
{
get { return new string[] { @"USB\VID_0403&PID_6001" }; }
set {}
}
public byte[] buffer { get; private set; }
public uint handle;
public bool done = false;
public int bytesWritten = 0;
public FT_STATUS status;
public const byte BITS_8 = 8;
public const byte STOP_BITS_2 = 2;
public const byte PARITY_NONE = 0;
public const UInt16 FLOW_NONE = 0;
public const byte PURGE_RX = 1;
public const byte PURGE_TX = 2;
Thread workThread;
// DLL IMPORT'S LEFT OUT FOR SIZE //
public FTD2XX(int frameRate) : base(frameRate)
{
this.buffer = new byte[255];
}
public override void Start()
{
handle = 0;
status = FT_Open(0, ref handle);
workThread = new Thread(new ThreadStart(writeData));
workThread.Start();
}
public override void SetDMXValue(int channel, byte value)
{
if (buffer != null)
{
buffer[channel] = value;
}
}
public void writeData()
{
while (!done)
{
InitOpenDMX();
FT_SetBreakOn(handle);
FT_SetBreakOff(handle);
bytesWritten = write(handle, buffer, buffer.Length);
Thread.Sleep(FrameRate);
}
}
public int write(uint handle, byte[] data, int length)
{
IntPtr ptr = Marshal.AllocHGlobal((int)length);
Marshal.Copy(data, 0, ptr, (int)length);
uint bytesWritten = 0;
status = FT_Write(handle, ptr, (uint)length, ref bytesWritten);
return (int)bytesWritten;
}
public void InitOpenDMX()
{
status = FT_ResetDevice(handle);
status = FT_SetDivisor(handle, (char)12); // set baud rate
status = FT_SetDataCharacteristics(handle, BITS_8, STOP_BITS_2, PARITY_NONE);
status = FT_SetFlowControl(handle, (char)FLOW_NONE, 0, 0);
status = FT_ClrRts(handle);
status = FT_Purge(handle, PURGE_TX);
status = FT_Purge(handle, PURGE_RX);
}
public override void Stop()
{
this.done = true;
this.workThread.Abort();
this.workThread = null;
status = FT_ResetDevice(handle);
status = FT_Close(handle);
}
/// <summary>
/// Enumaration containing the varios return status for the DLL functions.
/// </summary>
public enum FT_STATUS
{
FT_OK = 0,
FT_INVALID_HANDLE,
FT_DEVICE_NOT_FOUND,
FT_DEVICE_NOT_OPENED,
FT_IO_ERROR,
FT_INSUFFICIENT_RESOURCES,
FT_INVALID_PARAMETER,
FT_INVALID_BAUD_RATE,
FT_DEVICE_NOT_OPENED_FOR_ERASE,
FT_DEVICE_NOT_OPENED_FOR_WRITE,
FT_FAILED_TO_WRITE_DEVICE,
FT_EEPROM_READ_FAILED,
FT_EEPROM_WRITE_FAILED,
FT_EEPROM_ERASE_FAILED,
FT_EEPROM_NOT_PRESENT,
FT_EEPROM_NOT_PROGRAMMED,
FT_INVALID_ARGS,
FT_OTHER_ERROR
};
}
}
USB事件处理程序
private void DeviceInsertedEvent(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
foreach(Driver driver in this.drivers)
{
if (driver.HardwareIDs.Any(hID => (instance.Properties["DeviceID"].Value as string).StartsWith(hID)))
{
driver.Start();
if (this.OnDriverLoaded != null)
this.OnDriverLoaded(this, new PluginLoadUnloadEventArgs(driver));
break;
}
}
}
Unplug基本相同,但使用了.Stop()
和OnDriverUnload()
启动后检测任何兼容的USB设备(如果是这样,代码可以正常工作)
ManagementObjectCollection collection;
using (var searcher = new ManagementObjectSearcher(@"Select * From Win32_USBHub"))
collection = searcher.Get();
foreach (var device in collection)
{
foreach (Driver driver in this.drivers)
{
if (driver.HardwareIDs.Any(hID => (device.GetPropertyValue("DeviceID") as string).StartsWith(hID)))
{
driver.Start();
if (this.OnDriverLoaded != null)
this.OnDriverLoaded(this, new PluginLoadUnloadEventArgs(driver));
goto End;
}
}
}
End:
return;