Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature serial port #1834

Merged
merged 10 commits into from
May 12, 2022
1 change: 1 addition & 0 deletions build.proj
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
<ItemGroup>
<_ProjectsToPackage Include="$(MSBuildThisFileDirectory)src\Iot.Device.Bindings\Iot.Device.Bindings.csproj" />
<_ProjectsToPackage Include="$(MSBuildThisFileDirectory)src\System.Device.Gpio\System.Device.Gpio.csproj" />
<_ProjectsToPackage Include="$(MSBuildThisFileDirectory)src\System.Device.Ports\System.Device.Ports.SerialPort\System.Device.Ports.SerialPort.csproj" />
</ItemGroup>

<MSBuild Projects="@(_ProjectsToPackage)" Targets="Pack" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<IsPackable>false</IsPackable>
<!-- Keep quiet about duplicate package references from props files -->
<NoWarn>$(NoWarn);NETSDK1023</NoWarn>
joperezr marked this conversation as resolved.
Show resolved Hide resolved
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\System.Device.Ports.SerialPort\System.Device.Ports.SerialPort.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Device.Ports.SerialPort
{
/// <summary>
/// Defines how the transfer is done between
/// the sender (DTE) and the receiver (DCE).
/// </summary>
public enum Handshake
{
/// <summary>
/// This is the most common option.
/// All the trasmitted and received data may flow at the same time.
/// </summary>
None,

/// <summary>
/// The data flow is controlled using the two ascii characters
/// XOn (17) and XOff (19).<par />
/// The receiver can stop receiving data by sending XOff and
/// restarting the flow by sending XOn to the transmitter.<para/>
/// This flow precludes the use of those two characters in
/// the message data.
/// </summary>
XOnXOff,

/// <summary>
/// The data flow is controlled using the RTS and CTS wires
/// and is used when a half-duplex communication is desired.
/// The RTS line is set by the transmitter. The receiver
/// should assert the CTS to let the trasmitter begin.
/// </summary>
RequestToSend,

/// <summary>
/// Both the Request-to-Send (RTS) hardware control and
/// the XON/XOFF software controls are used
/// </summary>
RequestToSendXOnXOff
Copy link
Contributor

@pgrawehr pgrawehr Mar 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This enum should be reviewed. RequestToSendXOnXOff is probably never used (I can't think of a reason why you would use hw flow control and sw flow control at the same time), but instead RtsCts handshake (bidirectional full hardware flow control) should be added.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally agree, I also have never seen that mix

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will have to futher discuss what handshakes we want to support because I am reading an old book on the serial port and there are plenty variations.

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Device.Ports.SerialPort
{
internal class LinuxSerialPort : SerialPort
{
private const string DefaultPortName = "/dev/tty0";

public LinuxSerialPort()
{
_portName = DefaultPortName;
}

protected internal override void SetBaudRate(int baudRate)
{
throw new NotImplementedException();
}

protected internal override void SetParity(Parity parity)
{
throw new NotImplementedException();
}

protected internal override void SetDataBits(int dataBits)
{
throw new NotImplementedException();
}

protected internal override void SetStopBits(StopBits stopBits)
{
throw new NotImplementedException();
}

protected internal override void SetBreakState(bool breakState)
{
throw new NotImplementedException();
}

protected internal override int GetBytesToRead()
{
throw new NotImplementedException();
}

protected internal override int GetBytesToWrite()
{
throw new NotImplementedException();
}

protected internal override int GetCDHolding()
{
throw new NotImplementedException();
}

protected internal override int GetCtsHolding()
{
throw new NotImplementedException();
}

protected internal override void SetDiscardNull(bool value)
{
throw new NotImplementedException();
}

protected internal override int GetDsrHolding()
{
throw new NotImplementedException();
}

protected internal override void SetDtrEnable(bool value)
{
throw new NotImplementedException();
}

protected internal override void SetHandshake(Handshake handshake)
{
throw new NotImplementedException();
}

protected internal override byte SetParityReplace(byte parityReplace)
{
throw new NotImplementedException();
}

protected internal override void SetReadTimeout(int timeout)
{
throw new NotImplementedException();
}

protected internal override void SetRtsEnable(bool rtsEnable)
{
throw new NotImplementedException();
}

protected internal override void SetWriteBufferSize(int writeBufferSize)
{
throw new NotImplementedException();
}

protected internal override void SetWriteTimeout(int writeTimeout)
{
throw new NotImplementedException();
}

protected internal override void OpenPort()
{
throw new NotImplementedException();
}

protected internal override void ClosePort()
{
throw new NotImplementedException();
}

public override void DiscardInBuffer()
{
throw new NotImplementedException();
}

public override void DiscardOutBuffer()
{
throw new NotImplementedException();
}

protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}

protected internal override void InitializeBuffers(int readBufferSize, int writeBufferSize)
{
throw new NotImplementedException();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
MAXDWORD
DCB
COMMTIMEOUTS
COMSTAT
COMMPROP

SetCommState
SetCommBreak
SetCommMask
SetCommTimeouts
SetupComm
PurgeComm
ClearCommBreak
ClearCommError
WaitCommEvent
EscapeCommFunction
GetCommModemStatus
GetFileType
GetCommProperties
FlushFileBuffers
CreateFile
ReadFile
WriteFile
GetOverlappedResult
CloseHandle

WIN32_ERROR

36 changes: 36 additions & 0 deletions src/System.Device.Ports/System.Device.Ports.SerialPort/Parity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Device.Ports.SerialPort
{
/// <summary>
/// Specifies the parity bit for a SerialPort object.
/// </summary>
public enum Parity
{
/// <summary>
/// No parity bit is senty or expected.
/// </summary>
None = 0,

/// <summary>
/// Sets the parity bit so that the count of bits set is an odd number.
/// </summary>
Odd = 1,

/// <summary>
/// Sets the parity bit so that the count of bits set is an even number.
/// </summary>
Even = 2,

/// <summary>
/// Leaves the parity bit set to 1.
/// </summary>
Mark = 3,

/// <summary>
/// Leaves the parity bit set to 0.
/// </summary>
Space = 4
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Device.Ports.SerialPort
{
/// <summary>
/// Specifies the type of character that was received on the serial port of the SerialPort object.
/// </summary>
public enum SerialData
{
/// <summary>
/// A character was received and placed in the input buffer.
/// In the Windows implementation, this is EV_RXCHAR.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd leave platform implementation details out of here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree. I just ported the class in the project to resolve other issues in the first place.

/// </summary>
Chars = 0x01,

/// <summary>
/// The end of file character was received and placed in the input buffer.
/// In the Windows implementation, this is EV_RXFLAG.
/// </summary>
Eof = 0x02
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something to think about is a nothing of WatchChar we have introduced in nanoFramework: https://github.com/nanoframework/System.IO.Ports/blob/develop/System.IO.Ports/SerialData.cs.

See usage here: https://github.com/nanoframework/System.IO.Ports#case-of-watchchar

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, this is substantially the same principle used in Win32 for watching a specific character.
Why did you rename the Eof=0x02 to WatchChar=0x02 in SerialData give they have the same meaning?
If I understand well this enum can be left as-is for compat reasons. Then we can add the WatchChar property to specify what is the character that will trigger the event.
Did I miss something?

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Device.Ports.SerialPort
{
/// <summary>
/// The arguments for the SerialDataReceived event
/// </summary>
public class SerialDataReceivedEventArgs : EventArgs
{
internal SerialDataReceivedEventArgs(SerialData eventCode)
{
EventType = eventCode;
}

/// <summary>
/// The nature of data recevied from the serial port
/// </summary>
public SerialData EventType { get; private set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Device.Ports.SerialPort
{
/// <summary>
/// Represents the method that will handle the DataReceived event of a SerialPort object.
/// </summary>
/// <param name="sender">The sender of the event, which is the SerialPort object.</param>
/// <param name="e">A SerialDataReceivedEventArgs object that contains the event data.</param>
public delegate void SerialDataReceivedEventHandler(object sender, SerialDataReceivedEventArgs e);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Device.Ports.SerialPort
{
/// <summary>
/// Specifies errors that occur on the SerialPort object.
/// </summary>
public enum SerialError
{
/// <summary>
/// The application tried to transmit a character,
/// but the output buffer was full.
/// </summary>
TXFull = 0x100,

/// <summary>
/// An input buffer overflow has occurred.
/// There is either no room in the input buffer, or a character
/// was received after the end-of-file (EOF) character.
/// </summary>
RXOver = 0x01,

/// <summary>
/// A character-buffer overrun has occurred.
/// The next character is lost.
/// </summary>
Overrun = 0x02,

/// <summary>
/// The hardware detected a parity error.
/// </summary>
RXParity = 0x04,

/// <summary>
/// The hardware detected a framing error.
/// </summary>
Frame = 0x08,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Device.Ports.SerialPort
{
/// <summary>
/// Prepares data for the ErrorReceived event.
/// </summary>
public class SerialErrorReceivedEventArgs : EventArgs
{
internal SerialErrorReceivedEventArgs(SerialError eventCode)
{
EventType = eventCode;
}

/// <summary>
/// The nature of data recevied from the serial port
/// </summary>
public SerialError EventType { get; private set; }
}
}
Loading