添加的文件

This commit is contained in:
xu 2020-02-26 02:06:30 +08:00
parent 3362a1b47c
commit d4a9dc5bf3
2 changed files with 598 additions and 0 deletions

View File

@ -0,0 +1,512 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using System.Threading;
namespace Plane.Util
{
public class SerialPort : System.IO.Ports.SerialPort, ICommsSerial
{
static object locker = new object();
public new bool DtrEnable { get { return base.DtrEnable; } set { if (base.DtrEnable == value) return; if (ispx4(base.PortName)) return; base.DtrEnable = value; } }
public new bool RtsEnable { get { return base.RtsEnable; } set { if (base.RtsEnable == value) return; if (ispx4(base.PortName)) return; base.RtsEnable = value; } }
/*
protected override void Dispose(bool disposing)
{
try
{
try
{
Type mytype = typeof(System.IO.Ports.SerialPort);
FieldInfo field = mytype.GetField("internalSerialStream", BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
Stream stream = (Stream)field.GetValue(this);
if (stream != null)
{
try
{
stream.Dispose();
}
catch (Exception ex) { Console.WriteLine("1 " + ex.ToString()); }
stream = null;
}
}
}
catch (Exception ex) { Console.WriteLine("2 " + ex.ToString()); }
base.Dispose(disposing);
}
catch (Exception ex) { Console.WriteLine("3 " + ex.ToString()); }
}
*/
public new void Open()
{
// 500ms write timeout - win32 api default
this.WriteTimeout = 500;
if (base.IsOpen)
return;
try
{
// this causes element not found with bluetooth devices.
if (BaudRate > 115200)
{
Console.WriteLine("Doing SerialPortFixer");
SerialPortFixer.Execute(this.PortName);
Console.WriteLine("Done SerialPortFixer");
}
}
catch (Exception ex) { Console.WriteLine(ex.ToString()); }
if (PortName.StartsWith("/"))
if (!File.Exists(PortName))
throw new Exception("No such device");
try
{
base.Open();
}
catch {
try { Close(); }
catch { }
throw;
}
}
public new void Close()
{
base.Close();
}
public void toggleDTR()
{
if (ispx4(this.PortName))
{
Console.WriteLine("PX4 - no DTR");
return;
}
bool open = this.IsOpen;
Console.WriteLine("toggleDTR " + this.IsOpen);
try
{
if (!open)
this.Open();
}
catch { }
base.DtrEnable = false;
base.RtsEnable = false;
System.Threading.Thread.Sleep(50);
base.DtrEnable = true;
base.RtsEnable = true;
System.Threading.Thread.Sleep(50);
try
{
if (!open)
this.Close();
}
catch { }
Console.WriteLine("toggleDTR done " + this.IsOpen);
}
public new static string[] GetPortNames()
{
// prevent hammering
lock (locker)
{
List<string> allPorts = new List<string>();
if (Directory.Exists("/dev/"))
{
// cleanup now
GC.Collect();
// mono is failing in here on linux "too many open files"
try
{
if (Directory.Exists("/dev/serial/by-id/"))
allPorts.AddRange(Directory.GetFiles("/dev/serial/by-id/", "*"));
}
catch { }
try
{
allPorts.AddRange(Directory.GetFiles("/dev/", "ttyACM*"));
}
catch { }
try
{
allPorts.AddRange(Directory.GetFiles("/dev/", "ttyUSB*"));
}
catch { }
try
{
allPorts.AddRange(Directory.GetFiles("/dev/", "rfcomm*"));
}
catch { }
try
{
allPorts.AddRange(Directory.GetFiles("/dev/", "*usb*"));
}
catch { }
}
string[] ports = null;
try
{
ports = System.IO.Ports.SerialPort.GetPortNames()
.Select(p => p.TrimEnd())
.Select(FixBlueToothPortNameBug)
.ToArray();
}
catch { }
if (ports != null)
allPorts.AddRange(ports);
return allPorts.ToArray();
}
}
static Dictionary<string, string> comportnamecache = new Dictionary<string, string>();
public static string GetNiceName(string port)
{
// make sure we are exclusive
lock (locker)
{
portnamenice = "";
if (comportnamecache.ContainsKey(port))
{
return comportnamecache[port];
}
try
{
CallWithTimeout(new Action<string>(GetName), 1000, port);
}
catch
{
}
comportnamecache[port] = portnamenice;
return (string)portnamenice.Clone();
}
}
static string portnamenice = "";
static void GetName(string port)
{
try
{
/*
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_SerialPort"); // Win32_USBControllerDevice
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
{
foreach (ManagementObject obj2 in searcher.Get())
{
//DeviceID
if (obj2.Properties["DeviceID"].Value.ToString().ToUpper() == port.ToUpper())
{
portnamenice = obj2.Properties["Name"].Value.ToString();
return;
}
}
}
*/
}
catch { }
portnamenice = "";
}
static void CallWithTimeout(Action<string> action, int timeoutMilliseconds, string data)
{
Thread threadToKill = null;
Action wrappedAction = () =>
{
threadToKill = Thread.CurrentThread;
action(data);
};
IAsyncResult result = wrappedAction.BeginInvoke(null, null);
if (result.AsyncWaitHandle.WaitOne(timeoutMilliseconds))
{
wrappedAction.EndInvoke(result);
}
else
{
threadToKill.Abort();
throw new TimeoutException();
}
}
internal bool ispx4(string port)
{
return false;
}
// .NET bug: sometimes bluetooth ports are enumerated with bogus characters
// eg 'COM10' becomes 'COM10c' - one workaround is to remove the non numeric
// char. Annoyingly, sometimes a numeric char is added, which means this
// does not work in all cases.
// See http://connect.microsoft.com/VisualStudio/feedback/details/236183/system-io-ports-serialport-getportnames-error-with-bluetooth
private static string FixBlueToothPortNameBug(string portName)
{
if (!portName.StartsWith("COM"))
return portName;
var newPortName = "COM"; // Start over with "COM"
foreach (var portChar in portName.Substring(3).ToCharArray()) // Remove "COM", put the rest in a character array
{
if (char.IsDigit(portChar))
newPortName += portChar.ToString(); // Good character, append to portName
// else
//log.WarnFormat("Bad (Non Numeric) character in port name '{0}' - removing", portName);
}
return newPortName;
}
}
public sealed class SerialPortFixer : IDisposable
{
public static void Execute(string portName)
{
using (new SerialPortFixer(portName))
{
}
}
#region IDisposable Members
public void Dispose()
{
if (m_Handle != null)
{
m_Handle.Dispose();
m_Handle = null;
}
GC.SuppressFinalize(this);
}
#endregion
#region Implementation
private const int DcbFlagAbortOnError = 14;
private const int CommStateRetries = 10;
private SafeFileHandle m_Handle;
private SerialPortFixer(string portName)
{
const int dwFlagsAndAttributes = 0x40000000;
const int dwAccess = unchecked((int)0xC0000000); if ((portName == null) || !portName.StartsWith("COM", StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException("Invalid Serial Port", "portName");
}
SafeFileHandle hFile = NativeMethods.CreateFile(@"\\.\" + portName, dwAccess, 0, IntPtr.Zero, 3, dwFlagsAndAttributes,
IntPtr.Zero);
if (hFile.IsInvalid)
{
WinIoError();
}
try
{
int fileType = NativeMethods.GetFileType(hFile);
if ((fileType != 2) && (fileType != 0))
{
throw new ArgumentException("Invalid Serial Port", "portName");
}
m_Handle = hFile;
InitializeDcb();
}
catch
{
hFile.Dispose();
m_Handle = null;
throw;
}
}
private static class NativeMethods
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern int FormatMessage(int dwFlags, HandleRef lpSource, int dwMessageId, int dwLanguageId,
StringBuilder lpBuffer, int nSize, IntPtr arguments);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool GetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool SetCommState(SafeFileHandle hFile, ref Dcb lpDcb);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool ClearCommError(SafeFileHandle hFile, ref int lpErrors, ref Comstat lpStat);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode,
IntPtr securityAttrs, int dwCreationDisposition,
int dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern int GetFileType(SafeFileHandle hFile);
}
private void InitializeDcb()
{
Dcb dcb = new Dcb();
GetCommStateNative(ref dcb);
dcb.Flags &= ~(1u << DcbFlagAbortOnError);
SetCommStateNative(ref dcb);
}
private static string GetMessage(int errorCode)
{
StringBuilder lpBuffer = new StringBuilder(0x200);
if (
NativeMethods.FormatMessage(0x3200, new HandleRef(null, IntPtr.Zero), errorCode, 0, lpBuffer, lpBuffer.Capacity,
IntPtr.Zero) != 0)
{
return lpBuffer.ToString();
}
return "Unknown Error";
}
private static int MakeHrFromErrorCode(int errorCode)
{
return (int)(0x80070000 | (uint)errorCode);
}
private static void WinIoError()
{
int errorCode = Marshal.GetLastWin32Error();
throw new IOException(GetMessage(errorCode), MakeHrFromErrorCode(errorCode));
}
private void GetCommStateNative(ref Dcb lpDcb)
{
int commErrors = 0;
Comstat comStat = new Comstat();
for (int i = 0; i < CommStateRetries; i++)
{
if (!NativeMethods.ClearCommError(m_Handle, ref commErrors, ref comStat))
{
WinIoError();
}
if (NativeMethods.GetCommState(m_Handle, ref lpDcb))
{
break;
}
if (i == CommStateRetries - 1)
{
WinIoError();
}
}
}
private void SetCommStateNative(ref Dcb lpDcb)
{
int commErrors = 0;
Comstat comStat = new Comstat(); for (int i = 0; i < CommStateRetries; i++)
{
if (!NativeMethods.ClearCommError(m_Handle, ref commErrors, ref comStat))
{
WinIoError();
}
if (NativeMethods.SetCommState(m_Handle, ref lpDcb))
{
break;
}
if (i == CommStateRetries - 1)
{
WinIoError();
}
}
}
#region Nested type: COMSTAT
[StructLayout(LayoutKind.Sequential)]
private struct Comstat
{
public readonly uint Flags;
public readonly uint cbInQue;
public readonly uint cbOutQue;
}
#endregion
#region Nested type: DCB
/*
* https://msdn.microsoft.com/en-us/library/windows/desktop/aa363214(v=vs.85).aspx
DWORD fBinary :1;
DWORD fParity :1;
DWORD fOutxCtsFlow :1;
DWORD fOutxDsrFlow :1;
DWORD fDtrControl :2;
DWORD fDsrSensitivity :1;
DWORD fTXContinueOnXoff :1;
DWORD fOutX :1;
DWORD fInX :1;
DWORD fErrorChar :1;
DWORD fNull :1;
DWORD fRtsControl :2;
DWORD fAbortOnError :1;
DWORD fDummy2 :17;
*/
[StructLayout(LayoutKind.Sequential)]
public struct Dcb
{
public readonly uint DCBlength;
public readonly uint BaudRate;
public uint Flags;
public readonly ushort wReserved;
public readonly ushort XonLim;
public readonly ushort XoffLim;
public readonly byte ByteSize;
public readonly byte Parity;
public readonly byte StopBits;
public readonly byte XonChar;
public readonly byte XoffChar;
public readonly byte ErrorChar;
public readonly byte EofChar;
public readonly byte EvtChar;
public readonly ushort wReserved1;
}
#endregion
#endregion
}
}

View File

@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
namespace Plane.Util
{
/// <summary>
/// 为PasswordBox控件的Password增加绑定功能
/// </summary>
public static class PasswordBoxHelper
{
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.RegisterAttached("Password",
typeof(string), typeof(PasswordBoxHelper),
new FrameworkPropertyMetadata(string.Empty, OnPasswordPropertyChanged));
public static readonly DependencyProperty AttachProperty =
DependencyProperty.RegisterAttached("Attach",
typeof(bool), typeof(PasswordBoxHelper), new PropertyMetadata(false, Attach));
private static readonly DependencyProperty IsUpdatingProperty =
DependencyProperty.RegisterAttached("IsUpdating", typeof(bool),
typeof(PasswordBoxHelper));
public static void SetAttach(DependencyObject dp, bool value)
{
dp.SetValue(AttachProperty, value);
}
public static bool GetAttach(DependencyObject dp)
{
return (bool)dp.GetValue(AttachProperty);
}
public static string GetPassword(DependencyObject dp)
{
return (string)dp.GetValue(PasswordProperty);
}
public static void SetPassword(DependencyObject dp, string value)
{
dp.SetValue(PasswordProperty, value);
}
private static bool GetIsUpdating(DependencyObject dp)
{
return (bool)dp.GetValue(IsUpdatingProperty);
}
private static void SetIsUpdating(DependencyObject dp, bool value)
{
dp.SetValue(IsUpdatingProperty, value);
}
private static void OnPasswordPropertyChanged(DependencyObject sender,
DependencyPropertyChangedEventArgs e)
{
PasswordBox passwordBox = sender as PasswordBox;
passwordBox.PasswordChanged -= PasswordChanged;
if (!(bool)GetIsUpdating(passwordBox))
{
passwordBox.Password = (string)e.NewValue;
}
passwordBox.PasswordChanged += PasswordChanged;
}
private static void Attach(DependencyObject sender,
DependencyPropertyChangedEventArgs e)
{
PasswordBox passwordBox = sender as PasswordBox;
if (passwordBox == null)
return;
if ((bool)e.OldValue)
{
passwordBox.PasswordChanged -= PasswordChanged;
}
if ((bool)e.NewValue)
{
passwordBox.PasswordChanged += PasswordChanged;
}
}
private static void PasswordChanged(object sender, RoutedEventArgs e)
{
PasswordBox passwordBox = sender as PasswordBox;
SetIsUpdating(passwordBox, true);
SetPassword(passwordBox, passwordBox.Password);
SetIsUpdating(passwordBox, false);
}
}
}