mirror of
https://github.com/microsoft/terminal.git
synced 2026-04-06 06:09:50 +00:00
Compare commits
1 Commits
feature/ll
...
dev/duhowe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
92a8c5894d |
@@ -1488,6 +1488,9 @@ namespace winrt::TerminalApp::implementation
|
||||
auto connectionType = profile.ConnectionType();
|
||||
Windows::Foundation::Collections::ValueSet valueSet;
|
||||
|
||||
// 36d045b3-13bf-4ac0-9947-e2fd8562baa1
|
||||
static constexpr winrt::guid sg{ std::string_view{ "36d045b3-13bf-4ac0-9947-e2fd8562baa1" } };
|
||||
|
||||
if (connectionType == TerminalConnection::AzureConnection::ConnectionType() &&
|
||||
TerminalConnection::AzureConnection::IsAzureConnectionAvailable())
|
||||
{
|
||||
@@ -1504,6 +1507,17 @@ namespace winrt::TerminalApp::implementation
|
||||
profile.Guid());
|
||||
}
|
||||
|
||||
else if (connectionType == sg)
|
||||
{
|
||||
connection = TerminalConnection::SerialConnection{};
|
||||
valueSet = TerminalConnection::SerialConnection::CreateSettings(
|
||||
settings.Commandline(),
|
||||
settings.InitialRows(),
|
||||
settings.InitialCols(),
|
||||
winrt::guid{},
|
||||
profile.Guid());
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
auto settingsInternal{ winrt::get_self<Settings::TerminalSettings>(settings) };
|
||||
|
||||
144
src/cascadia/TerminalConnection/SerialConnection.cpp
Normal file
144
src/cascadia/TerminalConnection/SerialConnection.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "SerialConnection.h"
|
||||
#include "SerialConnection.g.cpp"
|
||||
|
||||
using namespace winrt::Microsoft::Terminal::TerminalConnection;
|
||||
|
||||
namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
{
|
||||
winrt::Windows::Foundation::Collections::ValueSet SerialConnection::CreateSettings(hstring const& deviceDescription, uint32_t rows, uint32_t columns, winrt::guid const& guid, winrt::guid const& profileGuid)
|
||||
{
|
||||
Windows::Foundation::Collections::ValueSet vs{};
|
||||
|
||||
vs.Insert(L"device", Windows::Foundation::PropertyValue::CreateString(deviceDescription));
|
||||
vs.Insert(L"initialRows", Windows::Foundation::PropertyValue::CreateUInt32(rows));
|
||||
vs.Insert(L"initialCols", Windows::Foundation::PropertyValue::CreateUInt32(columns));
|
||||
vs.Insert(L"guid", Windows::Foundation::PropertyValue::CreateGuid(guid));
|
||||
vs.Insert(L"profileGuid", Windows::Foundation::PropertyValue::CreateGuid(profileGuid));
|
||||
|
||||
return vs;
|
||||
}
|
||||
|
||||
void SerialConnection::Initialize(winrt::Windows::Foundation::Collections::ValueSet const& settings)
|
||||
{
|
||||
std::wstring device{ winrt::unbox_value<hstring>(settings.Lookup(L"device")) };
|
||||
if (auto pos = device.find_first_of(L": "); pos != std::wstring::npos)
|
||||
{
|
||||
std::wstring comm{ device.substr(pos + 1) };
|
||||
if (!comm.empty())
|
||||
{
|
||||
_dcb.DCBlength = sizeof(_dcb);
|
||||
_dcbValid = !!BuildCommDCBW(comm.c_str(), &_dcb); // OK to fail
|
||||
if (!_dcbValid)
|
||||
{
|
||||
LOG_LAST_ERROR();
|
||||
}
|
||||
}
|
||||
device.resize(pos);
|
||||
}
|
||||
_devicePath = std::move(device);
|
||||
}
|
||||
|
||||
void SerialConnection::Start()
|
||||
{
|
||||
_transitionToState(ConnectionState::Connecting);
|
||||
_port.reset(CreateFileW(_devicePath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr));
|
||||
if (_dcbValid)
|
||||
{
|
||||
SetCommState(_port.get(), &_dcb);
|
||||
}
|
||||
|
||||
COMMTIMEOUTS timeouts{
|
||||
.ReadIntervalTimeout = MAXDWORD,
|
||||
.ReadTotalTimeoutMultiplier = MAXDWORD,
|
||||
.ReadTotalTimeoutConstant = 10000,
|
||||
};
|
||||
SetCommTimeouts(_port.get(), &timeouts);
|
||||
|
||||
auto strong{ get_strong() };
|
||||
_ioThread = std::thread{
|
||||
[strong = std::move(strong), this]() {
|
||||
_transitionToState(ConnectionState::Connected);
|
||||
IoThreadBody();
|
||||
// strong maintains our lifetime until the I/O thread dies
|
||||
}
|
||||
};
|
||||
}
|
||||
void SerialConnection::WriteInput(array_view<char16_t const> buffer)
|
||||
{
|
||||
const auto data = winrt_array_to_wstring_view(buffer);
|
||||
std::string temp;
|
||||
LOG_IF_FAILED(til::u16u8(data, temp, _u16State));
|
||||
if (!WriteFile(_port.get(), temp.data(), static_cast<DWORD>(temp.length()), nullptr, nullptr))
|
||||
{
|
||||
_transitionToState(ConnectionState::Failed);
|
||||
_port.reset();
|
||||
}
|
||||
//FlushFileBuffers(_port.get());
|
||||
}
|
||||
void SerialConnection::Resize(uint32_t rows, uint32_t columns)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(rows);
|
||||
UNREFERENCED_PARAMETER(columns);
|
||||
return;
|
||||
}
|
||||
void SerialConnection::Close()
|
||||
{
|
||||
_transitionToState(ConnectionState::Closing);
|
||||
_port.reset();
|
||||
_ioThread.join();
|
||||
_transitionToState(ConnectionState::Closed);
|
||||
}
|
||||
|
||||
void SerialConnection::IoThreadBody()
|
||||
{
|
||||
char buffer[128 * 1024];
|
||||
DWORD read = 0;
|
||||
|
||||
til::u8state u8State;
|
||||
std::wstring wstr;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
DCB ndcb{};
|
||||
ndcb.DCBlength = sizeof(ndcb);
|
||||
GetCommState(_port.get(), &ndcb);
|
||||
// When we have a `wstr` that's ready for processing we must do so without blocking.
|
||||
// Otherwise, whatever the user typed will be delayed until the next IO operation.
|
||||
// With overlapped IO that's not a problem because the ReadFile() calls won't block.
|
||||
if (!ReadFile(_port.get(), &buffer[0], sizeof(buffer), &read, nullptr))
|
||||
{
|
||||
if (GetLastError() != ERROR_IO_PENDING)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we hit a parsing error, eat it. It's bad utf-8, we can't do anything with it.
|
||||
LOG_IF_FAILED(til::u8u16({ &buffer[0], gsl::narrow_cast<size_t>(read) }, wstr, u8State));
|
||||
|
||||
if (!wstr.empty())
|
||||
{
|
||||
try
|
||||
{
|
||||
TerminalOutput.raise(wstr);
|
||||
}
|
||||
CATCH_LOG();
|
||||
}
|
||||
|
||||
if (read == 0)
|
||||
{
|
||||
// TODO???
|
||||
//break;
|
||||
}
|
||||
|
||||
if (_isStateAtOrBeyond(ConnectionState::Closing))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
38
src/cascadia/TerminalConnection/SerialConnection.h
Normal file
38
src/cascadia/TerminalConnection/SerialConnection.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "SerialConnection.g.h"
|
||||
#include "BaseTerminalConnection.h"
|
||||
#include <til/spsc.h>
|
||||
|
||||
namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
||||
{
|
||||
struct SerialConnection : SerialConnectionT<SerialConnection>, BaseTerminalConnection<SerialConnection>
|
||||
{
|
||||
SerialConnection() = default;
|
||||
|
||||
static winrt::Windows::Foundation::Collections::ValueSet CreateSettings(hstring const& deviceDescription, uint32_t rows, uint32_t columns, winrt::guid const& guid, winrt::guid const& profileGuid);
|
||||
|
||||
void Initialize(winrt::Windows::Foundation::Collections::ValueSet const& settings);
|
||||
void Start();
|
||||
void WriteInput(array_view<char16_t const> data);
|
||||
void Resize(uint32_t rows, uint32_t columns);
|
||||
void Close();
|
||||
|
||||
til::event<TerminalOutputHandler> TerminalOutput;
|
||||
|
||||
private:
|
||||
std::wstring _devicePath;
|
||||
wil::unique_hfile _port;
|
||||
bool _dcbValid{ false };
|
||||
DCB _dcb{};
|
||||
void IoThreadBody();
|
||||
std::thread _ioThread;
|
||||
til::spsc::producer<char16_t> _chan{ nullptr };
|
||||
|
||||
til::u16state _u16State;
|
||||
};
|
||||
}
|
||||
namespace winrt::Microsoft::Terminal::TerminalConnection::factory_implementation
|
||||
{
|
||||
BASIC_FACTORY(SerialConnection)
|
||||
}
|
||||
17
src/cascadia/TerminalConnection/SerialConnection.idl
Normal file
17
src/cascadia/TerminalConnection/SerialConnection.idl
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import "ITerminalConnection.idl";
|
||||
|
||||
namespace Microsoft.Terminal.TerminalConnection
|
||||
{
|
||||
runtimeclass SerialConnection : [default] ITerminalConnection
|
||||
{
|
||||
SerialConnection();
|
||||
static Windows.Foundation.Collections.ValueSet CreateSettings(String deviceDescription,
|
||||
UInt32 rows,
|
||||
UInt32 columns,
|
||||
Guid guid,
|
||||
Guid profileGuid);
|
||||
};
|
||||
}
|
||||
@@ -33,6 +33,9 @@
|
||||
<ClInclude Include="EchoConnection.h">
|
||||
<DependentUpon>EchoConnection.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SerialConnection.h">
|
||||
<DependentUpon>SerialConnection.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CTerminalHandoff.cpp" />
|
||||
@@ -52,6 +55,9 @@
|
||||
<ClCompile Include="ConptyConnection.cpp">
|
||||
<DependentUpon>ConptyConnection.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SerialConnection.cpp">
|
||||
<DependentUpon>SerialConnection.idl</DependentUpon>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -60,6 +66,7 @@
|
||||
<Midl Include="ConptyConnection.idl" />
|
||||
<Midl Include="EchoConnection.idl" />
|
||||
<Midl Include="AzureConnection.idl" />
|
||||
<Midl Include="SerialConnection.idl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PRIResource Include="Resources\en-US\Resources.resw">
|
||||
|
||||
Reference in New Issue
Block a user