Serial通信的例子(一)
发表于:2007-06-30来源:作者:点击数:
标签:
namespace LoMaN.IO { using System; using System.IO; using System.Threading; using System.Runtime.InteropServices; public class SerialStream : Stream { public class SerialAsyncResult : IAsyncResult { public SerialAsyncResult(object asyncObje
namespace LoMaN.IO {
using System;
using System.IO;
using System.Threading;
using System.Runtime.InteropServices;
public class SerialStream : Stream {
public class SerialAsyncResult : IAsyncResult {
public SerialAsyncResult(object asyncObject) {
m_AsyncObject = asyncObject;
m_WaitHandle = new ManualResetEvent(false);
}
internal void Init(object stateObject, AsyncCallback callback, bool bIsRead) {
m_StateObject = stateObject;
m_Callback = callback;
m_bIsRead = bIsRead;
m_bCompleted = false;
m_WaitHandle.Reset();
}
internal void Reset() {
m_StateObject = null;
m_Callback = null;
m_bCompleted = true;
m_WaitHandle.Reset();
}
internal bool m_bIsRead;
internal bool m_bCompleted = true;
public bool IsCompleted { get { return m_bCompleted; } }
public bool CompletedSynchronously { get { return false; } }
private object m_AsyncObject;
public object AsyncObject { get { return m_AsyncObject; } }
private object m_StateObject;
public object AsyncState { get { return m_StateObject; } }
private ManualResetEvent m_WaitHandle;
public WaitHandle AsyncWaitHandle { get { return m_WaitHandle; } }
private AsyncCallback m_Callback;
public AsyncCallback Callback { get { return m_Callback; } }
}
private unsafe void AsyncFSCallback(uint errorCode, uint numBytes, NativeOverlapped* pOverlapped) {
SerialAsyncResult sar = (SerialAsyncResult)Overlapped.Unpack(pOverlapped).AsyncResult;
if (sar.m_bIsRead)
m_iReadCount = (int)numBytes;
else
m_iWriteCount = (int)numBytes;
((ManualResetEvent)sar.AsyncWaitHandle).Set();
if (errorCode == ERROR_OPERATION_ABORTED)
sar.m_bCompleted = false;
else
sar.m_bCompleted = true;
if (sar.Callback != null)
sar.Callback.Invoke(sar);
}
private IOCompletionCallback m_IOCompletionCallback;
private int m_hFile = 0;
private string m_sPort;
public string Port {
get {
return m_sPort;
}
set {
if (m_sPort != value) {
Close();
Open(value);
}
}
}
private const uint GENERIC_READ = 0x80000000;
private const uint GENERIC_WRITE = 0x40000000;
private const uint ERROR_OPERATION_ABORTED = 995;
private const uint ERROR_IO_PENDING = 997;
public void Open(string port) {
m_hFile = CreateFile(port, (uint)((m_bRead?GENERIC_READ:0)|(m_bWrite?GENERIC_WRITE:0)), 0, 0, 3, 0x40000000, 0);
if (m_hFile <= 0) {
m_hFile = 0;
throw new FileNotFoundException("Unable to open " + port);
}
m_sPort = port;
ThreadPool.BindHandle(new IntPtr(m_hFile));
}
public SerialStream(string port, FileA
clearcase/" target="_blank" >ccess access) {
m_bRead = ((int)access & (int)FileAccess.Read) != 0;
m_bWrite = ((int)access & (int)FileAccess.Write) != 0;
Open(port);
unsafe {
m_IOCompletionCallback = new IOCompletionCallback(AsyncFSCallback);
}
}
private bool m_bRead;
public override bool CanRead { get { return m_bRead; } }
private bool m_bWrite;
public override bool CanWrite { get { return m_bWrite; } }
public override bool CanSeek { get { return false; } }
public bool Closed { get { return m_hFile <= 0; } }
public override long Length { get { return 0; } }
public override void SetLength(long nLength) { }
public override void Close() {
CloseHandle(m_hFile);
m_hFile = 0;
m_sPort = null;
}
private int m_iReadCount;
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) {
SerialAsyncResult ar = new SerialAsyncResult(this);
ar.Init(state, callback, true);
Overlapped ov = new Overlapped(0, 0, ar.AsyncWaitHandle.Handle.ToInt32(), ar);
unsafe { fixed (byte* data = &buffer[0]) {
int read = 0;
NativeOverlapped* nov = ov.Pack(m_IOCompletionCallback);
ReadFile(m_hFile, data, count, &read, nov);
} }
if (GetLastError() == ERROR_IO_PENDING)
return ar;
else
throw new Exception("Unable to initialize read. Errorcode: " + GetLastError().ToString());
}
private int m_iWriteCount;
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) {
SerialAsyncResult ar = new SerialAsyncResult(this);
ar.Init(state, callback, false);
Overlapped ov = new Overlapped(0, 0, ar.AsyncWaitHandle.Handle.ToInt32(), ar);
unsafe { fixed (byte* data = &buffer[0]) {
int write = 0;
NativeOverlapped* nov = ov.Pack(m_IOCompletionCallback);
WriteFile(m_hFile, data, count, &write, nov);
} }
if (GetLastError() == ERROR_IO_PENDING)
return ar;
else
throw new Exception("Unable to initialize write. Errorcode: " + GetLastError().ToString());
}
public override int EndRead(IAsyncResult asyncResult) {
SerialAsyncResult sar = (SerialAsyncResult)asyncResult;
if (!sar.m_bIsRead)
throw new Exception("Invalid parameter: IAsyncResult is not from a read");
sar.AsyncWaitHandle.WaitOne();
if (!sar.m_bCompleted) {
((ManualResetEvent)sar.AsyncWaitHandle).Reset();
sar.AsyncWaitHandle.WaitOne();
}
sar.Reset();
return m_iReadCount;
}
public override void EndWrite(IAsyncResult asyncResult) {
SerialAsyncResult sar = (SerialAsyncResult)asyncResult;
if (sar.m_bIsRead)
throw new Exception("Invalid parameter: IAsyncResult is from a read");
sar.AsyncWaitHandle.WaitOne();
if (!sar.m_bCompleted) {
((ManualResetEvent)sar.AsyncWaitHandle).Reset();
sar.AsyncWaitHandle.WaitOne();
}
sar.Reset();
}
public override int Read(byte[] buffer, int offset, int count) {
return EndRead(BeginRead(buffer, offset, count, null, null));
}
public override void Write(byte[] buffer, int offset, int count) {
EndWrite(BeginWrite(buffer, offset, count, null, null));
}
public override void Flush() { FlushFileBuffers(m_hFile); }
private const uint PURGE_TXABORT = 0x0001; // Kill the pending/current writes to the comm port.
private const uint PURGE_RXABORT = 0x0002; // Kill the pending/current reads to the comm port.
private const uint PURGE_TXCLEAR = 0x0004; // Kill the transmit queue if there.
private const uint PURGE_RXCLEAR = 0x0008; // Kill the typeahead buffer if there.
public bool PurgeRead() { return(PurgeComm(m_hFile, PURGE_RXCLEAR)); }
public bool PurgeWrite() { return(PurgeComm(m_hFile, PURGE_TXCLEAR)); }
public bool CancelRead() { return(PurgeComm(m_hFile, PURGE_RXABORT)); }
public bool CancelWrite() { return(PurgeComm(m_hFile, PURGE_TXABORT)); }
public override long Seek(long offset, SeekOrigin origin) { return 0; }
原文转自:http://www.ltesting.net