381 lines
9 KiB
C++
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;
|
|
}
|