Initial commit
This commit is contained in:
commit
849cb8865a
30
.gitignore
vendored
Executable file
30
.gitignore
vendored
Executable file
@ -0,0 +1,30 @@
|
||||
|
||||
#ignore thumbnails created by windows
|
||||
Thumbs.db
|
||||
#Ignore files build by Visual Studio
|
||||
*.obj
|
||||
*.exe
|
||||
*.pdb
|
||||
*.user
|
||||
*.aps
|
||||
*.pch
|
||||
*.vspscc
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ncb
|
||||
*.suo
|
||||
*.tlb
|
||||
*.tlh
|
||||
*.bak
|
||||
*.cache
|
||||
*.ilk
|
||||
*.log
|
||||
[Bb]in
|
||||
[Dd]ebug*/
|
||||
*.lib
|
||||
*.sbr
|
||||
obj/
|
||||
[Rr]elease*/
|
||||
_ReSharper*/
|
||||
[Tt]est[Rr]esult*
|
||||
*.testsettings
|
63
PInvokeSerialPort.Sample/PInvokeSerialPort.Sample.csproj
Executable file
63
PInvokeSerialPort.Sample/PInvokeSerialPort.Sample.csproj
Executable file
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{76FAB402-7515-4A9B-8605-4FEC0736C78A}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>PInvokeSerialPort.Sample</RootNamespace>
|
||||
<AssemblyName>PInvokeSerialPort.Sample</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\PInvokeSerialPort\PInvokeSerialPort.csproj">
|
||||
<Project>{AEC711A5-AA9B-4127-A82C-C4D8FDA9741A}</Project>
|
||||
<Name>PInvokeSerialPort</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
19
PInvokeSerialPort.Sample/Program.cs
Executable file
19
PInvokeSerialPort.Sample/Program.cs
Executable file
@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using PInvokeSerialPort;
|
||||
|
||||
namespace PInvokeSerialPort.Sample
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
var serialPort = new SerialPort("com1", 14400);
|
||||
serialPort.DataReceived += x => Console.Write((char)x);
|
||||
serialPort.Open();
|
||||
while (true)
|
||||
{
|
||||
serialPort.Write(Console.ReadKey().KeyChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
36
PInvokeSerialPort.Sample/Properties/AssemblyInfo.cs
Executable file
36
PInvokeSerialPort.Sample/Properties/AssemblyInfo.cs
Executable file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("PInvokeSerialPort.Sample")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("PInvokeSerialPort.Sample")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2012")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("9628528d-5e4d-4071-aad1-b1f85f3d45d5")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
66
PInvokeSerialPort.Test/PInvokeSerialPort.Test.csproj
Executable file
66
PInvokeSerialPort.Test/PInvokeSerialPort.Test.csproj
Executable file
@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>
|
||||
</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{928609B4-70AB-4D93-A43E-4BE75C279066}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>PInvokeSerialPort.Test</RootNamespace>
|
||||
<AssemblyName>PInvokeSerialPort.Test</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
|
||||
<Visible>False</Visible>
|
||||
</CodeAnalysisDependentAssemblyPaths>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="PInvokeSerialPortTest.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\PInvokeSerialPort\PInvokeSerialPort.csproj">
|
||||
<Project>{AEC711A5-AA9B-4127-A82C-C4D8FDA9741A}</Project>
|
||||
<Name>PInvokeSerialPort</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
84
PInvokeSerialPort.Test/PInvokeSerialPortTest.cs
Executable file
84
PInvokeSerialPort.Test/PInvokeSerialPortTest.cs
Executable file
@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Threading;
|
||||
|
||||
namespace PInvokeSerialPort.Test
|
||||
{
|
||||
/// <summary>
|
||||
/// Test class.
|
||||
/// Attention: Run it just in test debug.
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class PInvokeSerialPortTest
|
||||
{
|
||||
dynamic _sender;
|
||||
dynamic _reciever;
|
||||
StringBuilder _stringBuilder;
|
||||
|
||||
public void OpenWriteDoWaitClose(Action action)
|
||||
{
|
||||
const string testSting = "test";
|
||||
_stringBuilder = new StringBuilder();
|
||||
_sender.Open();
|
||||
_reciever.Open();
|
||||
|
||||
action();
|
||||
|
||||
_sender.Write(testSting);
|
||||
Thread.Sleep(100);
|
||||
Assert.AreEqual(testSting, _stringBuilder.ToString());
|
||||
|
||||
_sender.Close();
|
||||
_reciever.Close();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OverallTest1()
|
||||
{
|
||||
_sender = new SerialPort("com1");
|
||||
_reciever = new SerialPort("com2");
|
||||
OpenWriteDoWaitClose(() =>
|
||||
{
|
||||
((SerialPort)_reciever).DataReceived += x => _stringBuilder.Append((char)x);
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OverallTest2()
|
||||
{
|
||||
_sender = new System.IO.Ports.SerialPort("com1");
|
||||
|
||||
_reciever = new SerialPort("com2");
|
||||
|
||||
OpenWriteDoWaitClose(() =>
|
||||
{
|
||||
((SerialPort)(object)_reciever).DataReceived += x => _stringBuilder.Append((char)x);
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OverallTest3()
|
||||
{
|
||||
_sender = new SerialPort("com1");
|
||||
_reciever = new System.IO.Ports.SerialPort("com2");
|
||||
|
||||
OpenWriteDoWaitClose(() =>
|
||||
{
|
||||
((System.IO.Ports.SerialPort)_reciever).DataReceived += (x, y) => _stringBuilder.Append(_reciever.ReadExisting());
|
||||
});
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void OverallTest4() // this is not really a PInvokeSerialTest :D
|
||||
{
|
||||
_sender = new System.IO.Ports.SerialPort("com1");
|
||||
_reciever = new System.IO.Ports.SerialPort("com2");
|
||||
|
||||
OpenWriteDoWaitClose(() =>
|
||||
{
|
||||
((System.IO.Ports.SerialPort)_reciever).DataReceived += (x, y) => _stringBuilder.Append(_reciever.ReadExisting());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
35
PInvokeSerialPort.Test/Properties/AssemblyInfo.cs
Executable file
35
PInvokeSerialPort.Test/Properties/AssemblyInfo.cs
Executable file
@ -0,0 +1,35 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("PInvokeSerialPort.Test")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("PInvokeSerialPort.Test")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2012")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("7e55b1ff-e888-4433-ab65-c9b32bb8125f")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
64
PInvokeSerialPort.sln
Executable file
64
PInvokeSerialPort.sln
Executable file
@ -0,0 +1,64 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual Studio 2010
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PInvokeSerialPort", "PInvokeSerialPort\PInvokeSerialPort.csproj", "{AEC711A5-AA9B-4127-A82C-C4D8FDA9741A}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{99052083-B245-462F-8778-4C94662ABABE}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Local.testsettings = Local.testsettings
|
||||
PInvokeSerialPort.vsmdi = PInvokeSerialPort.vsmdi
|
||||
TraceAndTestImpact.testsettings = TraceAndTestImpact.testsettings
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PInvokeSerialPort.Test", "PInvokeSerialPort.Test\PInvokeSerialPort.Test.csproj", "{928609B4-70AB-4D93-A43E-4BE75C279066}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PInvokeSerialPort.Sample", "PInvokeSerialPort.Sample\PInvokeSerialPort.Sample.csproj", "{76FAB402-7515-4A9B-8605-4FEC0736C78A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(TestCaseManagementSettings) = postSolution
|
||||
CategoryFile = PInvokeSerialPort.vsmdi
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|Mixed Platforms = Debug|Mixed Platforms
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|Mixed Platforms = Release|Mixed Platforms
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{AEC711A5-AA9B-4127-A82C-C4D8FDA9741A}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{AEC711A5-AA9B-4127-A82C-C4D8FDA9741A}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
|
||||
{AEC711A5-AA9B-4127-A82C-C4D8FDA9741A}.Debug|Mixed Platforms.Build.0 = Debug|x86
|
||||
{AEC711A5-AA9B-4127-A82C-C4D8FDA9741A}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{AEC711A5-AA9B-4127-A82C-C4D8FDA9741A}.Debug|x86.Build.0 = Debug|x86
|
||||
{AEC711A5-AA9B-4127-A82C-C4D8FDA9741A}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{AEC711A5-AA9B-4127-A82C-C4D8FDA9741A}.Release|Mixed Platforms.ActiveCfg = Release|x86
|
||||
{AEC711A5-AA9B-4127-A82C-C4D8FDA9741A}.Release|Mixed Platforms.Build.0 = Release|x86
|
||||
{AEC711A5-AA9B-4127-A82C-C4D8FDA9741A}.Release|x86.ActiveCfg = Release|x86
|
||||
{AEC711A5-AA9B-4127-A82C-C4D8FDA9741A}.Release|x86.Build.0 = Release|x86
|
||||
{928609B4-70AB-4D93-A43E-4BE75C279066}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{928609B4-70AB-4D93-A43E-4BE75C279066}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{928609B4-70AB-4D93-A43E-4BE75C279066}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||
{928609B4-70AB-4D93-A43E-4BE75C279066}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||
{928609B4-70AB-4D93-A43E-4BE75C279066}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{928609B4-70AB-4D93-A43E-4BE75C279066}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{928609B4-70AB-4D93-A43E-4BE75C279066}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{928609B4-70AB-4D93-A43E-4BE75C279066}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||
{928609B4-70AB-4D93-A43E-4BE75C279066}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||
{928609B4-70AB-4D93-A43E-4BE75C279066}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{76FAB402-7515-4A9B-8605-4FEC0736C78A}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{76FAB402-7515-4A9B-8605-4FEC0736C78A}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
|
||||
{76FAB402-7515-4A9B-8605-4FEC0736C78A}.Debug|Mixed Platforms.Build.0 = Debug|x86
|
||||
{76FAB402-7515-4A9B-8605-4FEC0736C78A}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{76FAB402-7515-4A9B-8605-4FEC0736C78A}.Debug|x86.Build.0 = Debug|x86
|
||||
{76FAB402-7515-4A9B-8605-4FEC0736C78A}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{76FAB402-7515-4A9B-8605-4FEC0736C78A}.Release|Mixed Platforms.ActiveCfg = Release|x86
|
||||
{76FAB402-7515-4A9B-8605-4FEC0736C78A}.Release|Mixed Platforms.Build.0 = Release|x86
|
||||
{76FAB402-7515-4A9B-8605-4FEC0736C78A}.Release|x86.ActiveCfg = Release|x86
|
||||
{76FAB402-7515-4A9B-8605-4FEC0736C78A}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
6
PInvokeSerialPort.vsmdi
Executable file
6
PInvokeSerialPort.vsmdi
Executable file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<TestLists xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
|
||||
<TestList name="Lists of Tests" id="8c43106b-9dc1-4907-a29f-aa66a61bf5b6">
|
||||
<RunConfiguration id="0631e4df-13f5-4c4c-974b-95bba187fbb2" name="Local" storage="local.testsettings" type="Microsoft.VisualStudio.TestTools.Common.TestRunConfiguration, Microsoft.VisualStudio.QualityTools.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
</TestList>
|
||||
</TestLists>
|
13
PInvokeSerialPort/ASCII.cs
Executable file
13
PInvokeSerialPort/ASCII.cs
Executable file
@ -0,0 +1,13 @@
|
||||
namespace PInvokeSerialPort
|
||||
{
|
||||
/// <summary>
|
||||
/// Byte type with enumeration constants for ASCII control codes.
|
||||
/// </summary>
|
||||
public enum ASCII : byte
|
||||
{
|
||||
NULL = 0x00, SOH = 0x01, STH = 0x02, ETX = 0x03, EOT = 0x04, ENQ = 0x05, ACK = 0x06, BELL = 0x07,
|
||||
BS = 0x08, HT = 0x09, LF = 0x0A, VT = 0x0B, FF = 0x0C, CR = 0x0D, SO = 0x0E, SI = 0x0F, DC1 = 0x11,
|
||||
DC2 = 0x12, DC3 = 0x13, DC4 = 0x14, NAK = 0x15, SYN = 0x16, ETB = 0x17, CAN = 0x18, EM = 0x19,
|
||||
SUB = 0x1A, ESC = 0x1B, FS = 0x1C, GS = 0x1D, RS = 0x1E, US = 0x1F, SP = 0x20, DEL = 0x7F
|
||||
}
|
||||
}
|
22
PInvokeSerialPort/CommPortException.cs
Executable file
22
PInvokeSerialPort/CommPortException.cs
Executable file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
|
||||
namespace PInvokeSerialPort
|
||||
{
|
||||
/// <summary>
|
||||
/// Exception used for all errors.
|
||||
/// </summary>
|
||||
public class CommPortException : ApplicationException
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor for raising direct exceptions
|
||||
/// </summary>
|
||||
/// <param name="desc">Description of error</param>
|
||||
public CommPortException(string desc) : base(desc) { }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for re-raising exceptions from receive thread
|
||||
/// </summary>
|
||||
/// <param name="e">Inner exception raised on receive thread</param>
|
||||
public CommPortException(Exception e) : base("Receive Thread Exception", e) { }
|
||||
}
|
||||
}
|
25
PInvokeSerialPort/Handshake.cs
Executable file
25
PInvokeSerialPort/Handshake.cs
Executable file
@ -0,0 +1,25 @@
|
||||
namespace PInvokeSerialPort
|
||||
{
|
||||
/// <summary>
|
||||
/// Standard handshake methods
|
||||
/// </summary>
|
||||
public enum Handshake
|
||||
{
|
||||
/// <summary>
|
||||
/// No handshaking
|
||||
/// </summary>
|
||||
None,
|
||||
/// <summary>
|
||||
/// Software handshaking using Xon / Xoff
|
||||
/// </summary>
|
||||
XonXoff,
|
||||
/// <summary>
|
||||
/// Hardware handshaking using CTS / RTS
|
||||
/// </summary>
|
||||
CtsRts,
|
||||
/// <summary>
|
||||
/// Hardware handshaking using DSR / DTR
|
||||
/// </summary>
|
||||
DsrDtr
|
||||
}
|
||||
}
|
25
PInvokeSerialPort/HsOutput.cs
Executable file
25
PInvokeSerialPort/HsOutput.cs
Executable file
@ -0,0 +1,25 @@
|
||||
namespace PInvokeSerialPort
|
||||
{
|
||||
/// <summary>
|
||||
/// Uses for RTS or DTR pins
|
||||
/// </summary>
|
||||
public enum HsOutput
|
||||
{
|
||||
/// <summary>
|
||||
/// Pin is asserted when this station is able to receive data.
|
||||
/// </summary>
|
||||
Handshake = 2,
|
||||
/// <summary>
|
||||
/// Pin is asserted when this station is transmitting data (RTS on NT, 2000 or XP only).
|
||||
/// </summary>
|
||||
Gate = 3,
|
||||
/// <summary>
|
||||
/// Pin is asserted when this station is online (port is open).
|
||||
/// </summary>
|
||||
Online = 1,
|
||||
/// <summary>
|
||||
/// Pin is never asserted.
|
||||
/// </summary>
|
||||
None = 0
|
||||
};
|
||||
}
|
29
PInvokeSerialPort/ModemStatus.cs
Executable file
29
PInvokeSerialPort/ModemStatus.cs
Executable file
@ -0,0 +1,29 @@
|
||||
using PInvokeSerialPort.Win32PInvoke;
|
||||
|
||||
namespace PInvokeSerialPort
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the status of the modem control input signals.
|
||||
/// </summary>
|
||||
public struct ModemStatus
|
||||
{
|
||||
private readonly uint _status;
|
||||
internal ModemStatus(uint val) { _status = val; }
|
||||
/// <summary>
|
||||
/// Condition of the Clear To Send signal.
|
||||
/// </summary>
|
||||
public bool Cts { get { return ((_status & Win32Com.MS_CTS_ON) != 0); } }
|
||||
/// <summary>
|
||||
/// Condition of the Data Set Ready signal.
|
||||
/// </summary>
|
||||
public bool Dsr { get { return ((_status & Win32Com.MS_DSR_ON) != 0); } }
|
||||
/// <summary>
|
||||
/// Condition of the Receive Line Status Detection signal.
|
||||
/// </summary>
|
||||
public bool Rlsd { get { return ((_status & Win32Com.MS_RLSD_ON) != 0); } }
|
||||
/// <summary>
|
||||
/// Condition of the Ring Detection signal.
|
||||
/// </summary>
|
||||
public bool Ring { get { return ((_status & Win32Com.MS_RING_ON) != 0); } }
|
||||
}
|
||||
}
|
74
PInvokeSerialPort/PInvokeSerialPort.csproj
Executable file
74
PInvokeSerialPort/PInvokeSerialPort.csproj
Executable file
@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{AEC711A5-AA9B-4127-A82C-C4D8FDA9741A}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>PInvokeSerialPort</RootNamespace>
|
||||
<AssemblyName>PInvokeSerialPort</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ASCII.cs" />
|
||||
<Compile Include="SerialPort.cs" />
|
||||
<Compile Include="CommPortException.cs" />
|
||||
<Compile Include="ModemStatus.cs" />
|
||||
<Compile Include="QueueStatus.cs" />
|
||||
<Compile Include="Win32PInvoke\COMMPROP.cs" />
|
||||
<Compile Include="Win32PInvoke\COMMTIMEOUTS.cs" />
|
||||
<Compile Include="Win32PInvoke\COMSTAT.cs" />
|
||||
<Compile Include="Win32PInvoke\DCB.cs" />
|
||||
<Compile Include="Handshake.cs" />
|
||||
<Compile Include="HsOutput.cs" />
|
||||
<Compile Include="Win32PInvoke\OVERLAPPED.cs" />
|
||||
<Compile Include="Parity.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="StopBits.cs" />
|
||||
<Compile Include="Win32PInvoke\Win32Com.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
29
PInvokeSerialPort/Parity.cs
Executable file
29
PInvokeSerialPort/Parity.cs
Executable file
@ -0,0 +1,29 @@
|
||||
namespace PInvokeSerialPort
|
||||
{
|
||||
/// <summary>
|
||||
/// Parity settings
|
||||
/// </summary>
|
||||
public enum Parity
|
||||
{
|
||||
/// <summary>
|
||||
/// Characters do not have a parity bit.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
/// <summary>
|
||||
/// If there are an odd number of 1s in the data bits, the parity bit is 1.
|
||||
/// </summary>
|
||||
Odd = 1,
|
||||
/// <summary>
|
||||
/// If there are an even number of 1s in the data bits, the parity bit is 1.
|
||||
/// </summary>
|
||||
Even = 2,
|
||||
/// <summary>
|
||||
/// The parity bit is always 1.
|
||||
/// </summary>
|
||||
Mark = 3,
|
||||
/// <summary>
|
||||
/// The parity bit is always 0.
|
||||
/// </summary>
|
||||
Space = 4
|
||||
};
|
||||
}
|
36
PInvokeSerialPort/Properties/AssemblyInfo.cs
Executable file
36
PInvokeSerialPort/Properties/AssemblyInfo.cs
Executable file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("PInvokeSerialPort")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("PInvokeSerialPort")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2012")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("a9b6ec41-2cde-4cdb-bd80-3dc730bcd820")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
134
PInvokeSerialPort/QueueStatus.cs
Executable file
134
PInvokeSerialPort/QueueStatus.cs
Executable file
@ -0,0 +1,134 @@
|
||||
using System.Text;
|
||||
using PInvokeSerialPort.Win32PInvoke;
|
||||
|
||||
namespace PInvokeSerialPort
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the current condition of the port queues.
|
||||
/// </summary>
|
||||
public struct QueueStatus
|
||||
{
|
||||
private uint status;
|
||||
private uint inQueue;
|
||||
private uint outQueue;
|
||||
private uint inQueueSize;
|
||||
private uint outQueueSize;
|
||||
|
||||
internal QueueStatus(uint stat, uint inQ, uint outQ, uint inQs, uint outQs)
|
||||
{ status = stat; inQueue = inQ; outQueue = outQ; inQueueSize = inQs; outQueueSize = outQs; }
|
||||
/// <summary>
|
||||
/// Output is blocked by CTS handshaking.
|
||||
/// </summary>
|
||||
public bool ctsHold { get { return ((status & COMSTAT.fCtsHold) != 0); } }
|
||||
/// <summary>
|
||||
/// Output is blocked by DRS handshaking.
|
||||
/// </summary>
|
||||
public bool dsrHold { get { return ((status & COMSTAT.fDsrHold) != 0); } }
|
||||
/// <summary>
|
||||
/// Output is blocked by RLSD handshaking.
|
||||
/// </summary>
|
||||
public bool rlsdHold { get { return ((status & COMSTAT.fRlsdHold) != 0); } }
|
||||
/// <summary>
|
||||
/// Output is blocked because software handshaking is enabled and XOFF was received.
|
||||
/// </summary>
|
||||
public bool xoffHold { get { return ((status & COMSTAT.fXoffHold) != 0); } }
|
||||
/// <summary>
|
||||
/// Output was blocked because XOFF was sent and this station is not yet ready to receive.
|
||||
/// </summary>
|
||||
public bool xoffSent { get { return ((status & COMSTAT.fXoffSent) != 0); } }
|
||||
|
||||
/// <summary>
|
||||
/// There is a character waiting for transmission in the immediate buffer.
|
||||
/// </summary>
|
||||
public bool immediateWaiting { get { return ((status & COMSTAT.fTxim) != 0); } }
|
||||
|
||||
/// <summary>
|
||||
/// Number of bytes waiting in the input queue.
|
||||
/// </summary>
|
||||
public long InQueue { get { return inQueue; } }
|
||||
/// <summary>
|
||||
/// Number of bytes waiting for transmission.
|
||||
/// </summary>
|
||||
public long OutQueue { get { return outQueue; } }
|
||||
/// <summary>
|
||||
/// Total size of input queue (0 means information unavailable)
|
||||
/// </summary>
|
||||
public long InQueueSize { get { return inQueueSize; } }
|
||||
/// <summary>
|
||||
/// Total size of output queue (0 means information unavailable)
|
||||
/// </summary>
|
||||
public long OutQueueSize { get { return outQueueSize; } }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var m = new StringBuilder("The reception queue is ", 60);
|
||||
if (inQueueSize == 0)
|
||||
{
|
||||
m.Append("of unknown size and ");
|
||||
}
|
||||
else
|
||||
{
|
||||
m.Append(inQueueSize.ToString() + " bytes long and ");
|
||||
}
|
||||
if (inQueue == 0)
|
||||
{
|
||||
m.Append("is empty.");
|
||||
}
|
||||
else if (inQueue == 1)
|
||||
{
|
||||
m.Append("contains 1 byte.");
|
||||
}
|
||||
else
|
||||
{
|
||||
m.Append("contains ");
|
||||
m.Append(inQueue.ToString());
|
||||
m.Append(" bytes.");
|
||||
}
|
||||
m.Append(" The transmission queue is ");
|
||||
if (outQueueSize == 0)
|
||||
{
|
||||
m.Append("of unknown size and ");
|
||||
}
|
||||
else
|
||||
{
|
||||
m.Append(outQueueSize.ToString() + " bytes long and ");
|
||||
}
|
||||
if (outQueue == 0)
|
||||
{
|
||||
m.Append("is empty");
|
||||
}
|
||||
else if (outQueue == 1)
|
||||
{
|
||||
m.Append("contains 1 byte. It is ");
|
||||
}
|
||||
else
|
||||
{
|
||||
m.Append("contains ");
|
||||
m.Append(outQueue.ToString());
|
||||
m.Append(" bytes. It is ");
|
||||
}
|
||||
if (outQueue > 0)
|
||||
{
|
||||
if (ctsHold || dsrHold || rlsdHold || xoffHold || xoffSent)
|
||||
{
|
||||
m.Append("holding on");
|
||||
if (ctsHold) m.Append(" CTS");
|
||||
if (dsrHold) m.Append(" DSR");
|
||||
if (rlsdHold) m.Append(" RLSD");
|
||||
if (xoffHold) m.Append(" Rx XOff");
|
||||
if (xoffSent) m.Append(" Tx XOff");
|
||||
}
|
||||
else
|
||||
{
|
||||
m.Append("pumping data");
|
||||
}
|
||||
}
|
||||
m.Append(". The immediate buffer is ");
|
||||
if (immediateWaiting)
|
||||
m.Append("full.");
|
||||
else
|
||||
m.Append("empty.");
|
||||
return m.ToString();
|
||||
}
|
||||
}
|
||||
}
|
740
PInvokeSerialPort/SerialPort.cs
Executable file
740
PInvokeSerialPort/SerialPort.cs
Executable file
@ -0,0 +1,740 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using PInvokeSerialPort.Win32PInvoke;
|
||||
|
||||
namespace PInvokeSerialPort
|
||||
{
|
||||
/// <summary>
|
||||
/// PInvokeSerialPort main class.
|
||||
/// Borrowed from http://msdn.microsoft.com/en-us/magazine/cc301786.aspx ;)
|
||||
/// </summary>
|
||||
public class SerialPort : IDisposable
|
||||
{
|
||||
private IntPtr _hPort;
|
||||
private IntPtr _ptrUwo = IntPtr.Zero;
|
||||
private Thread _rxThread;
|
||||
private bool _online;
|
||||
private bool _auto;
|
||||
private bool _checkSends = true;
|
||||
private Exception _rxException;
|
||||
private bool _rxExceptionReported;
|
||||
private int _writeCount;
|
||||
private readonly ManualResetEvent _writeEvent = new ManualResetEvent(false);
|
||||
private int _stateRts = 2;
|
||||
private int _stateDtr = 2;
|
||||
private int _stateBrk = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Class contructor
|
||||
/// </summary>
|
||||
public SerialPort(string portName)
|
||||
{
|
||||
PortName = portName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class contructor
|
||||
/// </summary>
|
||||
public SerialPort(string portName, int baudRate)
|
||||
{
|
||||
PortName = portName;
|
||||
BaudRate = baudRate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the com port and configures it with the required settings
|
||||
/// </summary>
|
||||
/// <returns>false if the port could not be opened</returns>
|
||||
public bool Open()
|
||||
{
|
||||
var portDcb = new DCB();
|
||||
var commTimeouts = new COMMTIMEOUTS();
|
||||
var wo = new OVERLAPPED();
|
||||
|
||||
if (_online) return false;
|
||||
|
||||
_hPort = Win32Com.CreateFile(PortName, Win32Com.GENERIC_READ | Win32Com.GENERIC_WRITE, 0, IntPtr.Zero,
|
||||
Win32Com.OPEN_EXISTING, Win32Com.FILE_FLAG_OVERLAPPED, IntPtr.Zero);
|
||||
if (_hPort == (IntPtr)Win32Com.INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (Marshal.GetLastWin32Error() == Win32Com.ERROR_ACCESS_DENIED)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
throw new CommPortException("Port Open Failure");
|
||||
}
|
||||
|
||||
_online = true;
|
||||
|
||||
commTimeouts.ReadIntervalTimeout = 0;
|
||||
commTimeouts.ReadTotalTimeoutConstant = 0;
|
||||
commTimeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
commTimeouts.WriteTotalTimeoutConstant = SendTimeoutConstant;
|
||||
commTimeouts.WriteTotalTimeoutMultiplier = SendTimeoutMultiplier;
|
||||
portDcb.Init(((Parity == Parity.Odd) || (Parity == Parity.Even)), TxFlowCts, TxFlowDsr,
|
||||
(int)UseDtr, RxGateDsr, !TxWhenRxXoff, TxFlowX, RxFlowX, (int)UseRts);
|
||||
portDcb.BaudRate = BaudRate;
|
||||
portDcb.ByteSize = (byte)DataBits;
|
||||
portDcb.Parity = (byte)Parity;
|
||||
portDcb.StopBits = (byte)StopBits;
|
||||
portDcb.XoffChar = (byte)XoffChar;
|
||||
portDcb.XonChar = (byte)XonChar;
|
||||
portDcb.XoffLim = (short)RxHighWater;
|
||||
portDcb.XonLim = (short)RxLowWater;
|
||||
if ((RxQueue != 0) || (TxQueue != 0))
|
||||
if (!Win32Com.SetupComm(_hPort, (uint)RxQueue, (uint)TxQueue)) ThrowException("Bad queue settings");
|
||||
if (!Win32Com.SetCommState(_hPort, ref portDcb)) ThrowException("Bad com settings");
|
||||
if (!Win32Com.SetCommTimeouts(_hPort, ref commTimeouts)) ThrowException("Bad timeout settings");
|
||||
|
||||
_stateBrk = 0;
|
||||
if (UseDtr == HsOutput.None) _stateDtr = 0;
|
||||
if (UseDtr == HsOutput.Online) _stateDtr = 1;
|
||||
if (UseRts == HsOutput.None) _stateRts = 0;
|
||||
if (UseRts == HsOutput.Online) _stateRts = 1;
|
||||
|
||||
_checkSends = CheckAllSends;
|
||||
wo.Offset = 0;
|
||||
wo.OffsetHigh = 0;
|
||||
wo.hEvent = _checkSends ? _writeEvent.Handle : IntPtr.Zero;
|
||||
_ptrUwo = Marshal.AllocHGlobal(Marshal.SizeOf(wo));
|
||||
Marshal.StructureToPtr(wo, _ptrUwo, true);
|
||||
_writeCount = 0;
|
||||
|
||||
_rxException = null;
|
||||
_rxExceptionReported = false;
|
||||
_rxThread = new Thread(ReceiveThread)
|
||||
{
|
||||
Name = "CommBaseRx",
|
||||
Priority = ThreadPriority.AboveNormal
|
||||
};
|
||||
_rxThread.Start();
|
||||
Thread.Sleep(1); //Give rx thread time to start. By documentation, 0 should work, but it does not!
|
||||
|
||||
_auto = false;
|
||||
if (AfterOpen())
|
||||
{
|
||||
_auto = AutoReopen;
|
||||
return true;
|
||||
}
|
||||
Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes the com port.
|
||||
/// </summary>
|
||||
public void Close()
|
||||
{
|
||||
if (_online)
|
||||
{
|
||||
_auto = false;
|
||||
BeforeClose(false);
|
||||
InternalClose();
|
||||
_rxException = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void InternalClose()
|
||||
{
|
||||
Win32Com.CancelIo(_hPort);
|
||||
if (_rxThread != null)
|
||||
{
|
||||
_rxThread.Abort();
|
||||
_rxThread = null;
|
||||
}
|
||||
Win32Com.CloseHandle(_hPort);
|
||||
if (_ptrUwo != IntPtr.Zero) Marshal.FreeHGlobal(_ptrUwo);
|
||||
_stateRts = 2;
|
||||
_stateDtr = 2;
|
||||
_stateBrk = 2;
|
||||
_online = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For IDisposable
|
||||
/// </summary>
|
||||
public void Dispose() { Close(); }
|
||||
|
||||
/// <summary>
|
||||
/// Destructor (just in case)
|
||||
/// </summary>
|
||||
~SerialPort() { Close(); }
|
||||
|
||||
/// <summary>
|
||||
/// True if online.
|
||||
/// </summary>
|
||||
public bool Online { get { return _online && CheckOnline(); } }
|
||||
|
||||
/// <summary>
|
||||
/// Block until all bytes in the queue have been transmitted.
|
||||
/// </summary>
|
||||
public void Flush()
|
||||
{
|
||||
CheckOnline();
|
||||
CheckResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this to throw exceptions in derived classes. Correctly handles threading issues
|
||||
/// and closes the port if necessary.
|
||||
/// </summary>
|
||||
/// <param name="reason">Description of fault</param>
|
||||
protected void ThrowException(string reason)
|
||||
{
|
||||
if (Thread.CurrentThread == _rxThread)
|
||||
{
|
||||
throw new CommPortException(reason);
|
||||
}
|
||||
if (_online)
|
||||
{
|
||||
BeforeClose(true);
|
||||
InternalClose();
|
||||
}
|
||||
if (_rxException == null)
|
||||
{
|
||||
throw new CommPortException(reason);
|
||||
}
|
||||
throw new CommPortException(_rxException);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queues bytes for transmission.
|
||||
/// </summary>
|
||||
/// <param name="toSend">Array of bytes to be sent</param>
|
||||
public void Write(byte[] toSend)
|
||||
{
|
||||
uint sent;
|
||||
CheckOnline();
|
||||
CheckResult();
|
||||
_writeCount = toSend.GetLength(0);
|
||||
if (Win32Com.WriteFile(_hPort, toSend, (uint)_writeCount, out sent, _ptrUwo))
|
||||
{
|
||||
_writeCount -= (int)sent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Marshal.GetLastWin32Error() != Win32Com.ERROR_IO_PENDING) ThrowException("Unexpected failure");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queues string for transmission.
|
||||
/// </summary>
|
||||
/// <param name="toSend">Array of bytes to be sent</param>
|
||||
public void Write(string toSend)
|
||||
{
|
||||
Write(new ASCIIEncoding().GetBytes(toSend));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queues a single byte for transmission.
|
||||
/// </summary>
|
||||
/// <param name="toSend">Byte to be sent</param>
|
||||
public void Write(byte toSend)
|
||||
{
|
||||
var b = new byte[1];
|
||||
b[0] = toSend;
|
||||
Write(b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queues a single char for transmission.
|
||||
/// </summary>
|
||||
/// <param name="toSend">Byte to be sent</param>
|
||||
public void Write(char toSend)
|
||||
{
|
||||
Write(toSend.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Queues string with a new line ("\r\n") for transmission.
|
||||
/// </summary>
|
||||
/// <param name="toSend">Array of bytes to be sent</param>
|
||||
public void WriteLine(string toSend)
|
||||
{
|
||||
Write(new ASCIIEncoding().GetBytes(toSend + Environment.NewLine));
|
||||
}
|
||||
|
||||
private void CheckResult()
|
||||
{
|
||||
if (_writeCount <= 0) return;
|
||||
uint sent;
|
||||
if (Win32Com.GetOverlappedResult(_hPort, _ptrUwo, out sent, _checkSends))
|
||||
{
|
||||
_writeCount -= (int)sent;
|
||||
if (_writeCount != 0) ThrowException("Send Timeout");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Marshal.GetLastWin32Error() != Win32Com.ERROR_IO_PENDING) ThrowException("Unexpected failure");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a protocol byte immediately ahead of any queued bytes.
|
||||
/// </summary>
|
||||
/// <param name="tosend">Byte to send</param>
|
||||
/// <returns>False if an immediate byte is already scheduled and not yet sent</returns>
|
||||
public void SendImmediate(byte tosend)
|
||||
{
|
||||
CheckOnline();
|
||||
if (!Win32Com.TransmitCommChar(_hPort, tosend)) ThrowException("Transmission failure");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delay processing.
|
||||
/// </summary>
|
||||
/// <param name="milliseconds">Milliseconds to delay by</param>
|
||||
protected void Sleep(int milliseconds)
|
||||
{
|
||||
Thread.Sleep(milliseconds);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the status of the modem control input signals.
|
||||
/// </summary>
|
||||
/// <returns>Modem status object</returns>
|
||||
protected ModemStatus GetModemStatus()
|
||||
{
|
||||
uint f;
|
||||
|
||||
CheckOnline();
|
||||
if (!Win32Com.GetCommModemStatus(_hPort, out f)) ThrowException("Unexpected failure");
|
||||
return new ModemStatus(f);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the status of the queues
|
||||
/// </summary>
|
||||
/// <returns>Queue status object</returns>
|
||||
protected QueueStatus GetQueueStatus()
|
||||
{
|
||||
COMSTAT cs;
|
||||
COMMPROP cp;
|
||||
uint er;
|
||||
|
||||
CheckOnline();
|
||||
if (!Win32Com.ClearCommError(_hPort, out er, out cs)) ThrowException("Unexpected failure");
|
||||
if (!Win32Com.GetCommProperties(_hPort, out cp)) ThrowException("Unexpected failure");
|
||||
return new QueueStatus(cs.Flags, cs.cbInQue, cs.cbOutQue, cp.dwCurrentRxQueue, cp.dwCurrentTxQueue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True if the RTS pin is controllable via the RTS property
|
||||
/// </summary>
|
||||
protected bool RtSavailable { get { return (_stateRts < 2); } }
|
||||
|
||||
/// <summary>
|
||||
/// Set the state of the RTS modem control output
|
||||
/// </summary>
|
||||
protected bool Rts
|
||||
{
|
||||
set
|
||||
{
|
||||
if (_stateRts > 1) return;
|
||||
CheckOnline();
|
||||
if (value)
|
||||
{
|
||||
if (Win32Com.EscapeCommFunction(_hPort, Win32Com.SETRTS))
|
||||
_stateRts = 1;
|
||||
else
|
||||
ThrowException("Unexpected Failure");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Win32Com.EscapeCommFunction(_hPort, Win32Com.CLRRTS))
|
||||
_stateRts = 1;
|
||||
else
|
||||
ThrowException("Unexpected Failure");
|
||||
}
|
||||
}
|
||||
get
|
||||
{
|
||||
return (_stateRts == 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True if the DTR pin is controllable via the DTR property
|
||||
/// </summary>
|
||||
protected bool DtrAvailable { get { return (_stateDtr < 2); } }
|
||||
|
||||
/// <summary>
|
||||
/// The state of the DTR modem control output
|
||||
/// </summary>
|
||||
protected bool Dtr
|
||||
{
|
||||
set
|
||||
{
|
||||
if (_stateDtr > 1) return;
|
||||
CheckOnline();
|
||||
if (value)
|
||||
{
|
||||
if (Win32Com.EscapeCommFunction(_hPort, Win32Com.SETDTR))
|
||||
_stateDtr = 1;
|
||||
else
|
||||
ThrowException("Unexpected Failure");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Win32Com.EscapeCommFunction(_hPort, Win32Com.CLRDTR))
|
||||
_stateDtr = 0;
|
||||
else
|
||||
ThrowException("Unexpected Failure");
|
||||
}
|
||||
}
|
||||
get
|
||||
{
|
||||
return (_stateDtr == 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assert or remove a break condition from the transmission line
|
||||
/// </summary>
|
||||
protected bool Break
|
||||
{
|
||||
set
|
||||
{
|
||||
if (_stateBrk > 1) return;
|
||||
CheckOnline();
|
||||
if (value)
|
||||
{
|
||||
if (Win32Com.EscapeCommFunction(_hPort, Win32Com.SETBREAK))
|
||||
_stateBrk = 0;
|
||||
else
|
||||
ThrowException("Unexpected Failure");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Win32Com.EscapeCommFunction(_hPort, Win32Com.CLRBREAK))
|
||||
_stateBrk = 0;
|
||||
else
|
||||
ThrowException("Unexpected Failure");
|
||||
}
|
||||
}
|
||||
get
|
||||
{
|
||||
return (_stateBrk == 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override this to provide processing after the port is openned (i.e. to configure remote
|
||||
/// device or just check presence).
|
||||
/// </summary>
|
||||
/// <returns>false to close the port again</returns>
|
||||
protected virtual bool AfterOpen() { return true; }
|
||||
|
||||
/// <summary>
|
||||
/// Override this to provide processing prior to port closure.
|
||||
/// </summary>
|
||||
/// <param name="error">True if closing due to an error</param>
|
||||
protected virtual void BeforeClose(bool error) { }
|
||||
|
||||
public event Action<byte> DataReceived;
|
||||
/// <summary>
|
||||
/// Override this to process received bytes.
|
||||
/// </summary>
|
||||
/// <param name="ch">The byte that was received</param>
|
||||
protected void OnRxChar(byte ch)
|
||||
{
|
||||
if (DataReceived != null)
|
||||
DataReceived(ch);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override this to take action when transmission is complete (i.e. all bytes have actually
|
||||
/// been sent, not just queued).
|
||||
/// </summary>
|
||||
protected virtual void OnTxDone() { }
|
||||
|
||||
/// <summary>
|
||||
/// Override this to take action when a break condition is detected on the input line.
|
||||
/// </summary>
|
||||
protected virtual void OnBreak() { }
|
||||
|
||||
/// <summary>
|
||||
/// Override this to take action when a ring condition is signalled by an attached modem.
|
||||
/// </summary>
|
||||
protected virtual void OnRing() { }
|
||||
|
||||
/// <summary>
|
||||
/// Override this to take action when one or more modem status inputs change state
|
||||
/// </summary>
|
||||
/// <param name="mask">The status inputs that have changed state</param>
|
||||
/// <param name="state">The state of the status inputs</param>
|
||||
protected virtual void OnStatusChange(ModemStatus mask, ModemStatus state) { }
|
||||
|
||||
/// <summary>
|
||||
/// Override this to take action when the reception thread closes due to an exception being thrown.
|
||||
/// </summary>
|
||||
/// <param name="e">The exception which was thrown</param>
|
||||
protected virtual void OnRxException(Exception e) { }
|
||||
|
||||
private void ReceiveThread()
|
||||
{
|
||||
var buf = new Byte[1];
|
||||
|
||||
var sg = new AutoResetEvent(false);
|
||||
var ov = new OVERLAPPED();
|
||||
var unmanagedOv = Marshal.AllocHGlobal(Marshal.SizeOf(ov));
|
||||
ov.Offset = 0; ov.OffsetHigh = 0;
|
||||
ov.hEvent = sg.Handle;
|
||||
Marshal.StructureToPtr(ov, unmanagedOv, true);
|
||||
|
||||
uint eventMask = 0;
|
||||
var uMask = Marshal.AllocHGlobal(Marshal.SizeOf(eventMask));
|
||||
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (!Win32Com.SetCommMask(_hPort, Win32Com.EV_RXCHAR | Win32Com.EV_TXEMPTY | Win32Com.EV_CTS | Win32Com.EV_DSR
|
||||
| Win32Com.EV_BREAK | Win32Com.EV_RLSD | Win32Com.EV_RING | Win32Com.EV_ERR))
|
||||
{
|
||||
throw new CommPortException("IO Error [001]");
|
||||
}
|
||||
Marshal.WriteInt32(uMask, 0);
|
||||
if (!Win32Com.WaitCommEvent(_hPort, uMask, unmanagedOv))
|
||||
{
|
||||
if (Marshal.GetLastWin32Error() == Win32Com.ERROR_IO_PENDING)
|
||||
{
|
||||
sg.WaitOne();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new CommPortException("IO Error [002]");
|
||||
}
|
||||
}
|
||||
eventMask = (uint)Marshal.ReadInt32(uMask);
|
||||
if ((eventMask & Win32Com.EV_ERR) != 0)
|
||||
{
|
||||
UInt32 errs;
|
||||
if (Win32Com.ClearCommError(_hPort, out errs, IntPtr.Zero))
|
||||
{
|
||||
var s = new StringBuilder("UART Error: ", 40);
|
||||
if ((errs & Win32Com.CE_FRAME) != 0) s = s.Append("Framing,");
|
||||
if ((errs & Win32Com.CE_IOE) != 0) s = s.Append("IO,");
|
||||
if ((errs & Win32Com.CE_OVERRUN) != 0) s = s.Append("Overrun,");
|
||||
if ((errs & Win32Com.CE_RXOVER) != 0) s = s.Append("Receive Cverflow,");
|
||||
if ((errs & Win32Com.CE_RXPARITY) != 0) s = s.Append("Parity,");
|
||||
if ((errs & Win32Com.CE_TXFULL) != 0) s = s.Append("Transmit Overflow,");
|
||||
s.Length = s.Length - 1;
|
||||
throw new CommPortException(s.ToString());
|
||||
}
|
||||
throw new CommPortException("IO Error [003]");
|
||||
}
|
||||
if ((eventMask & Win32Com.EV_RXCHAR) != 0)
|
||||
{
|
||||
uint gotbytes;
|
||||
do
|
||||
{
|
||||
if (!Win32Com.ReadFile(_hPort, buf, 1, out gotbytes, unmanagedOv))
|
||||
{
|
||||
if (Marshal.GetLastWin32Error() == Win32Com.ERROR_IO_PENDING)
|
||||
{
|
||||
Win32Com.CancelIo(_hPort);
|
||||
gotbytes = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new CommPortException("IO Error [004]");
|
||||
}
|
||||
}
|
||||
if (gotbytes == 1) OnRxChar(buf[0]);
|
||||
|
||||
} while (gotbytes > 0);
|
||||
}
|
||||
if ((eventMask & Win32Com.EV_TXEMPTY) != 0)
|
||||
{
|
||||
OnTxDone();
|
||||
}
|
||||
if ((eventMask & Win32Com.EV_BREAK) != 0) OnBreak();
|
||||
|
||||
uint i = 0;
|
||||
if ((eventMask & Win32Com.EV_CTS) != 0) i |= Win32Com.MS_CTS_ON;
|
||||
if ((eventMask & Win32Com.EV_DSR) != 0) i |= Win32Com.MS_DSR_ON;
|
||||
if ((eventMask & Win32Com.EV_RLSD) != 0) i |= Win32Com.MS_RLSD_ON;
|
||||
if ((eventMask & Win32Com.EV_RING) != 0) i |= Win32Com.MS_RING_ON;
|
||||
if (i != 0)
|
||||
{
|
||||
uint f;
|
||||
if (!Win32Com.GetCommModemStatus(_hPort, out f)) throw new CommPortException("IO Error [005]");
|
||||
OnStatusChange(new ModemStatus(i), new ModemStatus(f));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (uMask != IntPtr.Zero) Marshal.FreeHGlobal(uMask);
|
||||
if (unmanagedOv != IntPtr.Zero) Marshal.FreeHGlobal(unmanagedOv);
|
||||
if (!(e is ThreadAbortException))
|
||||
{
|
||||
_rxException = e;
|
||||
OnRxException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckOnline()
|
||||
{
|
||||
if ((_rxException != null) && (!_rxExceptionReported))
|
||||
{
|
||||
_rxExceptionReported = true;
|
||||
ThrowException("rx");
|
||||
}
|
||||
if (_online)
|
||||
{
|
||||
uint f;
|
||||
if (Win32Com.GetHandleInformation(_hPort, out f)) return true;
|
||||
ThrowException("Offline");
|
||||
return false;
|
||||
}
|
||||
if (_auto)
|
||||
{
|
||||
if (Open()) return true;
|
||||
}
|
||||
ThrowException("Offline");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Port Name
|
||||
/// </summary>
|
||||
public string PortName { get; set; }
|
||||
/// <summary>
|
||||
/// Baud Rate (default: 2400) unsupported rates will throw "Bad settings"
|
||||
/// </summary>
|
||||
public int BaudRate = 115200;
|
||||
/// <summary>
|
||||
/// The parity checking scheme (default: none)
|
||||
/// </summary>
|
||||
public Parity Parity = Parity.None;
|
||||
/// <summary>
|
||||
/// Number of databits 1..8 (default: 8) unsupported values will throw "Bad settings"
|
||||
/// </summary>
|
||||
public int DataBits = 8;
|
||||
/// <summary>
|
||||
/// Number of stop bits (default: one)
|
||||
/// </summary>
|
||||
public StopBits StopBits = StopBits.one;
|
||||
/// <summary>
|
||||
/// If true, transmission is halted unless CTS is asserted by the remote station (default: false)
|
||||
/// </summary>
|
||||
public bool TxFlowCts;
|
||||
/// <summary>
|
||||
/// If true, transmission is halted unless DSR is asserted by the remote station (default: false)
|
||||
/// </summary>
|
||||
public bool TxFlowDsr;
|
||||
/// <summary>
|
||||
/// If true, transmission is halted when Xoff is received and restarted when Xon is received (default: false)
|
||||
/// </summary>
|
||||
public bool TxFlowX;
|
||||
/// <summary>
|
||||
/// If false, transmission is suspended when this station has sent Xoff to the remote station (default: true)
|
||||
/// Set false if the remote station treats any character as an Xon.
|
||||
/// </summary>
|
||||
public bool TxWhenRxXoff = true;
|
||||
/// <summary>
|
||||
/// If true, received characters are ignored unless DSR is asserted by the remote station (default: false)
|
||||
/// </summary>
|
||||
public bool RxGateDsr;
|
||||
/// <summary>
|
||||
/// If true, Xon and Xoff characters are sent to control the data flow from the remote station (default: false)
|
||||
/// </summary>
|
||||
public bool RxFlowX;
|
||||
/// <summary>
|
||||
/// Specifies the use to which the RTS output is put (default: none)
|
||||
/// </summary>
|
||||
public HsOutput UseRts = HsOutput.None;
|
||||
/// <summary>
|
||||
/// Specidies the use to which the DTR output is put (default: none)
|
||||
/// </summary>
|
||||
public HsOutput UseDtr = HsOutput.None;
|
||||
/// <summary>
|
||||
/// The character used to signal Xon for X flow control (default: DC1)
|
||||
/// </summary>
|
||||
public ASCII XonChar = ASCII.DC1;
|
||||
/// <summary>
|
||||
/// The character used to signal Xoff for X flow control (default: DC3)
|
||||
/// </summary>
|
||||
public ASCII XoffChar = ASCII.DC3;
|
||||
/// <summary>
|
||||
/// The number of free bytes in the reception queue at which flow is disabled (default: 2048)
|
||||
/// </summary>
|
||||
public int RxHighWater = 2048;
|
||||
/// <summary>
|
||||
/// The number of bytes in the reception queue at which flow is re-enabled (default: 512)
|
||||
/// </summary>
|
||||
public int RxLowWater = 512;
|
||||
/// <summary>
|
||||
/// Multiplier. Max time for Send in ms = (Multiplier * Characters) + Constant
|
||||
/// (default: 0 = No timeout)
|
||||
/// </summary>
|
||||
public int SendTimeoutMultiplier;
|
||||
/// <summary>
|
||||
/// Constant. Max time for Send in ms = (Multiplier * Characters) + Constant (default: 0)
|
||||
/// </summary>
|
||||
public int SendTimeoutConstant;
|
||||
/// <summary>
|
||||
/// Requested size for receive queue (default: 0 = use operating system default)
|
||||
/// </summary>
|
||||
public int RxQueue;
|
||||
/// <summary>
|
||||
/// Requested size for transmit queue (default: 0 = use operating system default)
|
||||
/// </summary>
|
||||
public int TxQueue;
|
||||
/// <summary>
|
||||
/// If true, the port will automatically re-open on next send if it was previously closed due
|
||||
/// to an error (default: false)
|
||||
/// </summary>
|
||||
public bool AutoReopen;
|
||||
|
||||
/// <summary>
|
||||
/// If true, subsequent Send commands wait for completion of earlier ones enabling the results
|
||||
/// to be checked. If false, errors, including timeouts, may not be detected, but performance
|
||||
/// may be better.
|
||||
/// </summary>
|
||||
public bool CheckAllSends = true;
|
||||
|
||||
private Handshake _handShake;
|
||||
public Handshake Handshake
|
||||
{
|
||||
get { return _handShake; }
|
||||
set
|
||||
{
|
||||
Handshake = value;
|
||||
switch (Handshake)
|
||||
{
|
||||
case Handshake.None:
|
||||
TxFlowCts = false; TxFlowDsr = false; TxFlowX = false;
|
||||
RxFlowX = false; UseRts = HsOutput.Online; UseDtr = HsOutput.Online;
|
||||
TxWhenRxXoff = true; RxGateDsr = false;
|
||||
break;
|
||||
case Handshake.XonXoff:
|
||||
TxFlowCts = false; TxFlowDsr = false; TxFlowX = true;
|
||||
RxFlowX = true; UseRts = HsOutput.Online; UseDtr = HsOutput.Online;
|
||||
TxWhenRxXoff = true; RxGateDsr = false;
|
||||
XonChar = ASCII.DC1; XoffChar = ASCII.DC3;
|
||||
break;
|
||||
case Handshake.CtsRts:
|
||||
TxFlowCts = true; TxFlowDsr = false; TxFlowX = false;
|
||||
RxFlowX = false; UseRts = HsOutput.Handshake; UseDtr = HsOutput.Online;
|
||||
TxWhenRxXoff = true; RxGateDsr = false;
|
||||
break;
|
||||
case Handshake.DsrDtr:
|
||||
TxFlowCts = false; TxFlowDsr = true; TxFlowX = false;
|
||||
RxFlowX = false; UseRts = HsOutput.Online; UseDtr = HsOutput.Handshake;
|
||||
TxWhenRxXoff = true; RxGateDsr = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
21
PInvokeSerialPort/StopBits.cs
Executable file
21
PInvokeSerialPort/StopBits.cs
Executable file
@ -0,0 +1,21 @@
|
||||
namespace PInvokeSerialPort
|
||||
{
|
||||
/// <summary>
|
||||
/// Stop bit settings
|
||||
/// </summary>
|
||||
public enum StopBits
|
||||
{
|
||||
/// <summary>
|
||||
/// Line is asserted for 1 bit duration at end of each character
|
||||
/// </summary>
|
||||
one = 0,
|
||||
/// <summary>
|
||||
/// Line is asserted for 1.5 bit duration at end of each character
|
||||
/// </summary>
|
||||
onePointFive = 1,
|
||||
/// <summary>
|
||||
/// Line is asserted for 2 bit duration at end of each character
|
||||
/// </summary>
|
||||
two = 2
|
||||
};
|
||||
}
|
28
PInvokeSerialPort/Win32PInvoke/COMMPROP.cs
Executable file
28
PInvokeSerialPort/Win32PInvoke/COMMPROP.cs
Executable file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace PInvokeSerialPort.Win32PInvoke
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct COMMPROP
|
||||
{
|
||||
internal UInt16 wPacketLength;
|
||||
internal UInt16 wPacketVersion;
|
||||
internal UInt32 dwServiceMask;
|
||||
internal UInt32 dwReserved1;
|
||||
internal UInt32 dwMaxTxQueue;
|
||||
internal UInt32 dwMaxRxQueue;
|
||||
internal UInt32 dwMaxBaud;
|
||||
internal UInt32 dwProvSubType;
|
||||
internal UInt32 dwProvCapabilities;
|
||||
internal UInt32 dwSettableParams;
|
||||
internal UInt32 dwSettableBaud;
|
||||
internal UInt16 wSettableData;
|
||||
internal UInt16 wSettableStopParity;
|
||||
internal UInt32 dwCurrentTxQueue;
|
||||
internal UInt32 dwCurrentRxQueue;
|
||||
internal UInt32 dwProvSpec1;
|
||||
internal UInt32 dwProvSpec2;
|
||||
internal Byte wcProvChar;
|
||||
}
|
||||
}
|
15
PInvokeSerialPort/Win32PInvoke/COMMTIMEOUTS.cs
Executable file
15
PInvokeSerialPort/Win32PInvoke/COMMTIMEOUTS.cs
Executable file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace PInvokeSerialPort.Win32PInvoke
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct COMMTIMEOUTS
|
||||
{
|
||||
internal Int32 ReadIntervalTimeout;
|
||||
internal Int32 ReadTotalTimeoutMultiplier;
|
||||
internal Int32 ReadTotalTimeoutConstant;
|
||||
internal Int32 WriteTotalTimeoutMultiplier;
|
||||
internal Int32 WriteTotalTimeoutConstant;
|
||||
}
|
||||
}
|
20
PInvokeSerialPort/Win32PInvoke/COMSTAT.cs
Executable file
20
PInvokeSerialPort/Win32PInvoke/COMSTAT.cs
Executable file
@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace PInvokeSerialPort.Win32PInvoke
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct COMSTAT
|
||||
{
|
||||
internal const uint fCtsHold = 0x1;
|
||||
internal const uint fDsrHold = 0x2;
|
||||
internal const uint fRlsdHold = 0x4;
|
||||
internal const uint fXoffHold = 0x8;
|
||||
internal const uint fXoffSent = 0x10;
|
||||
internal const uint fEof = 0x20;
|
||||
internal const uint fTxim = 0x40;
|
||||
internal UInt32 Flags;
|
||||
internal UInt32 cbInQue;
|
||||
internal UInt32 cbOutQue;
|
||||
}
|
||||
}
|
41
PInvokeSerialPort/Win32PInvoke/DCB.cs
Executable file
41
PInvokeSerialPort/Win32PInvoke/DCB.cs
Executable file
@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace PInvokeSerialPort.Win32PInvoke
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct DCB
|
||||
{
|
||||
internal Int32 DCBlength;
|
||||
internal Int32 BaudRate;
|
||||
internal Int32 PackedValues;
|
||||
internal Int16 wReserved;
|
||||
internal Int16 XonLim;
|
||||
internal Int16 XoffLim;
|
||||
internal Byte ByteSize;
|
||||
internal Byte Parity;
|
||||
internal Byte StopBits;
|
||||
internal Byte XonChar;
|
||||
internal Byte XoffChar;
|
||||
internal Byte ErrorChar;
|
||||
internal Byte EofChar;
|
||||
internal Byte EvtChar;
|
||||
internal Int16 wReserved1;
|
||||
|
||||
internal void Init(bool parity, bool outCts, bool outDsr, int dtr, bool inDsr, bool txc, bool xOut,
|
||||
bool xIn, int rts)
|
||||
{
|
||||
DCBlength = 28; PackedValues = 0x8001;
|
||||
if (parity) PackedValues |= 0x0002;
|
||||
if (outCts) PackedValues |= 0x0004;
|
||||
if (outDsr) PackedValues |= 0x0008;
|
||||
PackedValues |= ((dtr & 0x0003) << 4);
|
||||
if (inDsr) PackedValues |= 0x0040;
|
||||
if (txc) PackedValues |= 0x0080;
|
||||
if (xOut) PackedValues |= 0x0100;
|
||||
if (xIn) PackedValues |= 0x0200;
|
||||
PackedValues |= ((rts & 0x0003) << 12);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
15
PInvokeSerialPort/Win32PInvoke/OVERLAPPED.cs
Executable file
15
PInvokeSerialPort/Win32PInvoke/OVERLAPPED.cs
Executable file
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace PInvokeSerialPort.Win32PInvoke
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct OVERLAPPED
|
||||
{
|
||||
internal UIntPtr Internal;
|
||||
internal UIntPtr InternalHigh;
|
||||
internal UInt32 Offset;
|
||||
internal UInt32 OffsetHigh;
|
||||
internal IntPtr hEvent;
|
||||
}
|
||||
}
|
155
PInvokeSerialPort/Win32PInvoke/Win32Com.cs
Executable file
155
PInvokeSerialPort/Win32PInvoke/Win32Com.cs
Executable file
@ -0,0 +1,155 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace PInvokeSerialPort.Win32PInvoke
|
||||
{
|
||||
internal class Win32Com
|
||||
{
|
||||
/// <summary>
|
||||
/// Opening Testing and Closing the Port Handle.
|
||||
/// </summary>
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
internal static extern IntPtr CreateFile(String lpFileName, UInt32 dwDesiredAccess, UInt32 dwShareMode,
|
||||
IntPtr lpSecurityAttributes, UInt32 dwCreationDisposition, UInt32 dwFlagsAndAttributes,
|
||||
IntPtr hTemplateFile);
|
||||
|
||||
//Constants for errors:
|
||||
internal const UInt32 ERROR_FILE_NOT_FOUND = 2;
|
||||
internal const UInt32 ERROR_INVALID_NAME = 123;
|
||||
internal const UInt32 ERROR_ACCESS_DENIED = 5;
|
||||
internal const UInt32 ERROR_IO_PENDING = 997;
|
||||
|
||||
//Constants for return value:
|
||||
internal const Int32 INVALID_HANDLE_VALUE = -1;
|
||||
|
||||
//Constants for dwFlagsAndAttributes:
|
||||
internal const UInt32 FILE_FLAG_OVERLAPPED = 0x40000000;
|
||||
|
||||
//Constants for dwCreationDisposition:
|
||||
internal const UInt32 OPEN_EXISTING = 3;
|
||||
|
||||
//Constants for dwDesiredAccess:
|
||||
internal const UInt32 GENERIC_READ = 0x80000000;
|
||||
internal const UInt32 GENERIC_WRITE = 0x40000000;
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
internal static extern Boolean CloseHandle(IntPtr hObject);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
internal static extern Boolean GetHandleInformation(IntPtr hObject, out UInt32 lpdwFlags);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Manipulating the communications settings.
|
||||
/// </summary>
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
internal static extern Boolean GetCommState(IntPtr hFile, ref DCB lpDCB);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
internal static extern Boolean GetCommTimeouts(IntPtr hFile, out COMMTIMEOUTS lpCommTimeouts);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
internal static extern Boolean BuildCommDCBAndTimeouts(String lpDef, ref DCB lpDCB, ref COMMTIMEOUTS lpCommTimeouts);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
internal static extern Boolean SetCommState(IntPtr hFile, [In] ref DCB lpDCB);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
internal static extern Boolean SetCommTimeouts(IntPtr hFile, [In] ref COMMTIMEOUTS lpCommTimeouts);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
internal static extern Boolean SetupComm(IntPtr hFile, UInt32 dwInQueue, UInt32 dwOutQueue);
|
||||
|
||||
/// <summary>
|
||||
/// Reading and writing.
|
||||
/// </summary>
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
internal static extern Boolean WriteFile(IntPtr fFile, Byte[] lpBuffer, UInt32 nNumberOfBytesToWrite,
|
||||
out UInt32 lpNumberOfBytesWritten, IntPtr lpOverlapped);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
internal static extern Boolean SetCommMask(IntPtr hFile, UInt32 dwEvtMask);
|
||||
|
||||
// Constants for dwEvtMask:
|
||||
internal const UInt32 EV_RXCHAR = 0x0001;
|
||||
internal const UInt32 EV_RXFLAG = 0x0002;
|
||||
internal const UInt32 EV_TXEMPTY = 0x0004;
|
||||
internal const UInt32 EV_CTS = 0x0008;
|
||||
internal const UInt32 EV_DSR = 0x0010;
|
||||
internal const UInt32 EV_RLSD = 0x0020;
|
||||
internal const UInt32 EV_BREAK = 0x0040;
|
||||
internal const UInt32 EV_ERR = 0x0080;
|
||||
internal const UInt32 EV_RING = 0x0100;
|
||||
internal const UInt32 EV_PERR = 0x0200;
|
||||
internal const UInt32 EV_RX80FULL = 0x0400;
|
||||
internal const UInt32 EV_EVENT1 = 0x0800;
|
||||
internal const UInt32 EV_EVENT2 = 0x1000;
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
internal static extern Boolean WaitCommEvent(IntPtr hFile, IntPtr lpEvtMask, IntPtr lpOverlapped);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
internal static extern Boolean CancelIo(IntPtr hFile);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
internal static extern Boolean ReadFile(IntPtr hFile, [Out] Byte[] lpBuffer, UInt32 nNumberOfBytesToRead,
|
||||
out UInt32 nNumberOfBytesRead, IntPtr lpOverlapped);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
internal static extern Boolean TransmitCommChar(IntPtr hFile, Byte cChar);
|
||||
|
||||
/// <summary>
|
||||
/// Control port functions.
|
||||
/// </summary>
|
||||
[DllImport("kernel32.dll")]
|
||||
internal static extern Boolean EscapeCommFunction(IntPtr hFile, UInt32 dwFunc);
|
||||
|
||||
// Constants for dwFunc:
|
||||
internal const UInt32 SETXOFF = 1;
|
||||
internal const UInt32 SETXON = 2;
|
||||
internal const UInt32 SETRTS = 3;
|
||||
internal const UInt32 CLRRTS = 4;
|
||||
internal const UInt32 SETDTR = 5;
|
||||
internal const UInt32 CLRDTR = 6;
|
||||
internal const UInt32 RESETDEV = 7;
|
||||
internal const UInt32 SETBREAK = 8;
|
||||
internal const UInt32 CLRBREAK = 9;
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
internal static extern Boolean GetCommModemStatus(IntPtr hFile, out UInt32 lpModemStat);
|
||||
|
||||
// Constants for lpModemStat:
|
||||
internal const UInt32 MS_CTS_ON = 0x0010;
|
||||
internal const UInt32 MS_DSR_ON = 0x0020;
|
||||
internal const UInt32 MS_RING_ON = 0x0040;
|
||||
internal const UInt32 MS_RLSD_ON = 0x0080;
|
||||
|
||||
/// <summary>
|
||||
/// Status Functions.
|
||||
/// </summary>
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
internal static extern Boolean GetOverlappedResult(IntPtr hFile, IntPtr lpOverlapped,
|
||||
out UInt32 nNumberOfBytesTransferred, Boolean bWait);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
internal static extern Boolean ClearCommError(IntPtr hFile, out UInt32 lpErrors, IntPtr lpStat);
|
||||
[DllImport("kernel32.dll")]
|
||||
internal static extern Boolean ClearCommError(IntPtr hFile, out UInt32 lpErrors, out COMSTAT cs);
|
||||
|
||||
//Constants for lpErrors:
|
||||
internal const UInt32 CE_RXOVER = 0x0001;
|
||||
internal const UInt32 CE_OVERRUN = 0x0002;
|
||||
internal const UInt32 CE_RXPARITY = 0x0004;
|
||||
internal const UInt32 CE_FRAME = 0x0008;
|
||||
internal const UInt32 CE_BREAK = 0x0010;
|
||||
internal const UInt32 CE_TXFULL = 0x0100;
|
||||
internal const UInt32 CE_PTO = 0x0200;
|
||||
internal const UInt32 CE_IOE = 0x0400;
|
||||
internal const UInt32 CE_DNS = 0x0800;
|
||||
internal const UInt32 CE_OOP = 0x1000;
|
||||
internal const UInt32 CE_MODE = 0x8000;
|
||||
[DllImport("kernel32.dll")]
|
||||
internal static extern Boolean GetCommProperties(IntPtr hFile, out COMMPROP cp);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user