blackmagic/src/platforms/pc/serial_win.c
2020-12-11 18:36:16 +01:00

180 lines
5.1 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"
static HANDLE hComm;
static char *find_bmp_by_serial(const char *serial)
{
char regpath[258];
/* First find the containers of the BMP comports */
sprintf(regpath,
"SYSTEM\\CurrentControlSet\\Enum\\USB\\VID_%04X&PID_%04X\\%s",
VENDOR_ID_BMP, PRODUCT_ID_BMP, serial);
HKEY hkeySection;
LSTATUS res;
res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &hkeySection);
if (res != ERROR_SUCCESS)
return NULL;
BYTE prefix[128];
DWORD maxlen = sizeof(prefix);
res = RegQueryValueEx(hkeySection, "ParentIdPrefix", NULL, NULL, prefix,
&maxlen);
RegCloseKey(hkeySection);
if (res != ERROR_SUCCESS)
return NULL;
printf("prefix %s\n", prefix);
sprintf(regpath,
"SYSTEM\\CurrentControlSet\\Enum\\USB\\VID_%04X&PID_%04X&MI_00\\%s"
"&0000\\Device Parameters",
VENDOR_ID_BMP, PRODUCT_ID_BMP, prefix);
printf("%s\n", regpath);
res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regpath, 0, KEY_READ, &hkeySection);
if (res != ERROR_SUCCESS) {
printf("Failuere\n");
return NULL;
}
BYTE port[128];
maxlen = sizeof(port);
res = RegQueryValueEx(hkeySection, "PortName", NULL, NULL, port, &maxlen);
RegCloseKey(hkeySection);
if (res != ERROR_SUCCESS)
return NULL;
printf("Portname %s\n", port);
return strdup((char*)port);
}
int serial_open(BMP_CL_OPTIONS_t *cl_opts, char * serial)
{
char device[256];
if (!cl_opts->opt_device)
cl_opts->opt_device = find_bmp_by_serial(serial);
if (!cl_opts->opt_device) {
DEBUG_WARN("Unexpected problems finding the device!\n");
return -1;
}
if (strstr(cl_opts->opt_device, "\\\\.\\")) {
strncpy(device, cl_opts->opt_device, sizeof(device) - 1);
} else {
strcpy(device, "\\\\.\\");
strncat(device, cl_opts->opt_device,
sizeof(device) - strlen(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;
dcbSerialParams.fDtrControl = DTR_CONTROL_ENABLE;
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() + cortexm_wait_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;
}