blackmagic/src/platforms/pc/serial_win.c

138 lines
3.9 KiB
C

/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <sys/types.h>
#include "general.h"
#include <windows.h>
#include "remote.h"
#include "cl_utils.h"
HANDLE hComm;
int serial_open(BMP_CL_OPTIONS_t *cl_opts, char * serial)
{
(void) serial; /* FIXME: Does Windows allow open with USB serial no? */
if (!cl_opts->opt_device) {
DEBUG_WARN("Specify the serial device to use!\n");
return -1;
}
char device[256];
if (strstr(device, "\\\\.\\")) {
strncpy(device, cl_opts->opt_device, sizeof(cl_opts->opt_device) - 1);
} else {
strcpy(device, "\\\\.\\");
strncat(device, cl_opts->opt_device,
sizeof(cl_opts->opt_device) - strlen(cl_opts->opt_device) - 1);
}
hComm = CreateFile(device, //port name
GENERIC_READ | GENERIC_WRITE, //Read/Write
0, // No Sharing
NULL, // No Security
OPEN_EXISTING,// Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices}
if (hComm == INVALID_HANDLE_VALUE) {
DEBUG_WARN("Could not open %s: %ld\n", device,
GetLastError());
return -1;
}
DCB dcbSerialParams;
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (!GetCommState(hComm, &dcbSerialParams)) {
DEBUG_WARN("GetCommState failed %ld\n", GetLastError());
return -1;
}
dcbSerialParams.ByteSize = 8;
if (!SetCommState(hComm, &dcbSerialParams)) {
DEBUG_WARN("SetCommState failed %ld\n", GetLastError());
return -1;
}
COMMTIMEOUTS timeouts = {0};
timeouts.ReadIntervalTimeout = 10;
timeouts.ReadTotalTimeoutConstant = 10;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 10;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (!SetCommTimeouts(hComm, &timeouts)) {
DEBUG_WARN("SetCommTimeouts failed %ld\n", GetLastError());
return -1;
}
return 0;
}
void serial_close(void)
{
CloseHandle(hComm);
}
int platform_buffer_write(const uint8_t *data, int size)
{
DEBUG_WIRE("%s\n",data);
int s = 0;
do {
DWORD written;
if (!WriteFile(hComm, data + s, size - s, &written, NULL)) {
DEBUG_WARN("Serial write failed %ld, written %d\n",
GetLastError(), s);
return -1;
}
s += written;
} while (s < size);
return 0;
}
int platform_buffer_read(uint8_t *data, int maxsize)
{
DWORD s;
uint8_t response = 0;
uint32_t startTime = platform_time_ms();
uint32_t endTime = platform_time_ms() + RESP_TIMEOUT;
do {
if (!ReadFile(hComm, &response, 1, &s, NULL)) {
DEBUG_WARN("ERROR on read RESP\n");
exit(-3);
}
if (platform_time_ms() > endTime) {
DEBUG_WARN("Timeout on read RESP\n");
exit(-4);
}
} while (response != REMOTE_RESP);
uint8_t *c = data;
do {
if (!ReadFile(hComm, c, 1, &s, NULL)) {
DEBUG_WARN("Error on read\n");
exit(-3);
}
if (s > 0 ) {
DEBUG_WIRE("%c", *c);
if (*c == REMOTE_EOM) {
*c = 0;
DEBUG_WIRE("\n");
return (c - data);
} else {
c++;
}
}
} while (((c - data) < maxsize) && (platform_time_ms() < endTime));
DEBUG_WARN("Failed to read EOM at %d\n",
platform_time_ms() - startTime);
exit(-3);
return 0;
}