windows-nt/Source/XPSP1/NT/sdktools/debuggers/dbgrpc/portio.cpp
2020-09-26 16:20:57 +08:00

381 lines
9 KiB
C++

//----------------------------------------------------------------------------
//
// Non-network I/O support.
//
// Copyright (C) Microsoft Corporation, 2000-2001.
//
//----------------------------------------------------------------------------
#include "pch.hpp"
#include <kdbg1394.h>
#include <ntdd1394.h>
//----------------------------------------------------------------------------
//
// COM.
//
//----------------------------------------------------------------------------
HRESULT
CreateOverlappedPair(LPOVERLAPPED Read, LPOVERLAPPED Write)
{
ZeroMemory(Read, sizeof(*Read));
ZeroMemory(Write, sizeof(*Write));
Read->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (Read->hEvent == NULL)
{
return WIN32_LAST_STATUS();
}
Write->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (Write->hEvent == NULL)
{
CloseHandle(Read->hEvent);
return WIN32_LAST_STATUS();
}
return S_OK;
}
BOOL
ComPortRead(HANDLE Port, PVOID Buffer, ULONG Len, PULONG Done,
LPOVERLAPPED Olap)
{
BOOL Status;
Status = ReadFile(Port, Buffer, Len, Done, Olap);
if (!Status)
{
if (GetLastError() == ERROR_IO_PENDING)
{
Status = GetOverlappedResult(Port, Olap, Done, TRUE);
}
else
{
DWORD TrashErr;
COMSTAT TrashStat;
// Device could be locked up. Clear it just in case.
ClearCommError(Port, &TrashErr, &TrashStat);
}
}
return Status;
}
BOOL
ComPortWrite(HANDLE Port, PVOID Buffer, ULONG Len, PULONG Done,
LPOVERLAPPED Olap)
{
BOOL Status;
Status = WriteFile(Port, Buffer, Len, Done, Olap);
if (!Status)
{
if (GetLastError() == ERROR_IO_PENDING)
{
Status = GetOverlappedResult(Port, Olap, Done, TRUE);
}
else
{
DWORD TrashErr;
COMSTAT TrashStat;
// Device could be locked up. Clear it just in case.
ClearCommError(Port, &TrashErr, &TrashStat);
}
}
return Status;
}
void
SetComPortName(PCSTR Name, PSTR Buffer)
{
if (*Name == 'c' || *Name == 'C')
{
strcpy(Buffer, "\\\\.\\");
strcpy(Buffer + 4, Name);
}
else if (*Name >= '0' && *Name <= '9')
{
PCSTR Scan = Name + 1;
while (*Scan >= '0' && *Scan <= '9')
{
Scan++;
}
if (*Scan == 0)
{
// The name was all digits so assume it's
// a plain com port number.
#ifndef NT_NATIVE
strcpy(Buffer, "\\\\.\\com");
#else
strcpy(Buffer, "\\Device\\Serial");
#endif
strcat(Buffer, Name);
}
else
{
strcpy(Buffer, Name);
}
}
else
{
strcpy(Buffer, Name);
}
}
ULONG
SelectComPortBaud(ULONG NewRate)
{
#define NUM_RATES 4
static DWORD s_Rates[NUM_RATES] = {19200, 38400, 57600, 115200};
static DWORD s_CurRate = NUM_RATES;
DWORD i;
if (NewRate > 0)
{
for (i = 0; NewRate > s_Rates[i] && i < NUM_RATES - 1; i++)
{
// Empty.
}
s_CurRate = (NewRate < s_Rates[i]) ? i : i + 1;
}
else
{
s_CurRate++;
}
if (s_CurRate >= NUM_RATES)
{
s_CurRate = 0;
}
return s_Rates[s_CurRate];
}
HRESULT
SetComPortBaud(HANDLE Port, ULONG NewRate, PULONG RateSet)
{
ULONG OldRate;
DCB LocalDcb;
if (Port == NULL)
{
return E_FAIL;
}
if (!GetCommState(Port, &LocalDcb))
{
return WIN32_LAST_STATUS();
}
OldRate = LocalDcb.BaudRate;
if (!NewRate)
{
NewRate = SelectComPortBaud(OldRate);
}
LocalDcb.BaudRate = NewRate;
LocalDcb.ByteSize = 8;
LocalDcb.Parity = NOPARITY;
LocalDcb.StopBits = ONESTOPBIT;
LocalDcb.fDtrControl = DTR_CONTROL_ENABLE;
LocalDcb.fRtsControl = RTS_CONTROL_ENABLE;
LocalDcb.fBinary = TRUE;
LocalDcb.fOutxCtsFlow = FALSE;
LocalDcb.fOutxDsrFlow = FALSE;
LocalDcb.fOutX = FALSE;
LocalDcb.fInX = FALSE;
if (!SetCommState(Port, &LocalDcb))
{
return WIN32_LAST_STATUS();
}
*RateSet = NewRate;
return S_OK;
}
HRESULT
OpenComPort(PSTR Port, ULONG BaudRate, ULONG Timeout,
PHANDLE Handle, PULONG BaudSet)
{
HANDLE ComHandle;
#ifndef NT_NATIVE
ComHandle = CreateFile(Port,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
#else
ComHandle = NtNativeCreateFileA(Port,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_OVERLAPPED,
NULL,
FALSE);
#endif
if (ComHandle == INVALID_HANDLE_VALUE)
{
return WIN32_LAST_STATUS();
}
if (!SetupComm(ComHandle, 4096, 4096))
{
CloseHandle(ComHandle);
return WIN32_LAST_STATUS();
}
HRESULT Status;
if ((Status = SetComPortBaud(ComHandle, BaudRate, BaudSet)) != S_OK)
{
CloseHandle(ComHandle);
return Status;
}
COMMTIMEOUTS To;
if (Timeout)
{
To.ReadIntervalTimeout = 0;
To.ReadTotalTimeoutMultiplier = 0;
To.ReadTotalTimeoutConstant = Timeout;
To.WriteTotalTimeoutMultiplier = 0;
To.WriteTotalTimeoutConstant = Timeout;
}
else
{
To.ReadIntervalTimeout = 0;
To.ReadTotalTimeoutMultiplier = 0xffffffff;
To.ReadTotalTimeoutConstant = 0xffffffff;
To.WriteTotalTimeoutMultiplier = 0xffffffff;
To.WriteTotalTimeoutConstant = 0xffffffff;
}
if (!SetCommTimeouts(ComHandle, &To))
{
CloseHandle(ComHandle);
return WIN32_LAST_STATUS();
}
*Handle = ComHandle;
return S_OK;
}
//----------------------------------------------------------------------------
//
// 1394.
//
//----------------------------------------------------------------------------
HRESULT
Create1394Channel(ULONG Channel, PSTR Name, PHANDLE Handle)
{
char BusName[] = "\\\\.\\1394BUS0";
HANDLE hDevice;
//
// we need to make sure the 1394vdbg driver is up and loaded.
// send the ADD_DEVICE ioctl to eject the VDO
// Assume one 1394 host controller...
//
hDevice = CreateFile(BusName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hDevice != INVALID_HANDLE_VALUE)
{
char DeviceId[] = "VIRTUAL_HOST_DEBUGGER";
ULONG ulStrLen;
PIEEE1394_API_REQUEST pApiReq;
PIEEE1394_VDEV_PNP_REQUEST pDevPnpReq;
DWORD dwBytesRet;
ulStrLen = strlen(DeviceId) + 1;
pApiReq = (PIEEE1394_API_REQUEST)
malloc(sizeof(IEEE1394_API_REQUEST) + ulStrLen);
if (pApiReq == NULL)
{
CloseHandle(hDevice);
return E_OUTOFMEMORY;
}
pApiReq->RequestNumber = IEEE1394_API_ADD_VIRTUAL_DEVICE;
pApiReq->Flags = IEEE1394_REQUEST_FLAG_PERSISTENT |
IEEE1394_REQUEST_FLAG_USE_LOCAL_HOST_EUI;
pDevPnpReq = &pApiReq->u.RemoveVirtualDevice;
pDevPnpReq->fulFlags = 0;
pDevPnpReq->Reserved = 0;
pDevPnpReq->InstanceId.QuadPart = 0;
strncpy((PSZ)&pDevPnpReq->DeviceId, DeviceId, ulStrLen);
// Failure of this call is not fatal.
DeviceIoControl( hDevice,
IOCTL_IEEE1394_API_REQUEST,
pApiReq,
sizeof(IEEE1394_API_REQUEST)+ulStrLen,
NULL,
0,
&dwBytesRet,
NULL
);
if (pApiReq)
{
free(pApiReq);
}
CloseHandle(hDevice);
}
else
{
return WIN32_LAST_STATUS();
}
return Open1394Channel(Channel, Name, Handle);
}
HRESULT
Open1394Channel(ULONG Channel, PSTR Name, PHANDLE Handle)
{
sprintf(Name, "\\\\.\\DBG1394_CHANNEL%02d", Channel);
*Handle = CreateFile(Name,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (*Handle == INVALID_HANDLE_VALUE)
{
return WIN32_LAST_STATUS();
}
return S_OK;
}