ardupilot/Tools/ArdupilotMegaPlanner/Comms/CommsSerialPort.cs

155 lines
4.9 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;
using System.IO;
using System.Linq;
using System.Management;
using ArdupilotMega.Utilities;
using System.Reflection;
namespace ArdupilotMega.Comms
{
public class SerialPort : System.IO.Ports.SerialPort,ICommsSerial
{
static bool serialportproblem = false;
protected override void Dispose(bool disposing)
{
try
{
try
{
Type mytype = typeof(System.IO.Ports.SerialPort);
FieldInfo field = mytype.GetField("internalSerialStream", BindingFlags.Instance | BindingFlags.NonPublic);
Stream stream = (Stream)field.GetValue(this);
if (stream != null)
{
stream.Dispose();
}
}
catch { }
base.Dispose(disposing);
}
catch { }
}
public new void Open()
{
// 500ms write timeout - win32 api default
this.WriteTimeout = 500;
if (base.IsOpen)
return;
base.Open();
}
public void toggleDTR()
{
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()
{
List<string> allPorts = new List<string>();
if (Directory.Exists("/dev/"))
{
if (Directory.Exists("/dev/serial/by-id/"))
allPorts.AddRange(Directory.GetFiles("/dev/serial/by-id/", "*"));
allPorts.AddRange(Directory.GetFiles("/dev/", "ttyACM*"));
allPorts.AddRange(Directory.GetFiles("/dev/", "ttyUSB*"));
allPorts.AddRange(Directory.GetFiles("/dev/", "rfcomm*"));
}
string[] ports = System.IO.Ports.SerialPort.GetPortNames()
.Select(p => p.TrimEnd())
.Select(FixBlueToothPortNameBug)
.ToArray();
allPorts.AddRange(ports);
return allPorts.ToArray();
}
internal static string GetNiceName(string port)
{
if (serialportproblem)
return "";
DateTime start = DateTime.Now;
try
{
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_SerialPort"); // Win32_USBControllerDevice
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
foreach (ManagementObject obj2 in searcher.Get())
{
//DeviceID
if (obj2.Properties["DeviceID"].Value.ToString().ToUpper() == port.ToUpper())
{
DateTime end = DateTime.Now;
if ((end - start).TotalSeconds > 5)
serialportproblem = true;
return obj2.Properties["Name"].Value.ToString();
}
}
}
catch { }
return "";
}
// .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;
}
}
}