pc-hosted: Put serial handling in own files for unix and implement for windows.
- If host provided /dev/serial/by-id, device must not be given and multiple devices may be selected with -s <(partial) serial number> - On windows, device must by specifies with -d
This commit is contained in:
parent
18ae2bb50d
commit
b4ab9f328e
@ -3,9 +3,13 @@ SYS = $(shell $(CC) -dumpmachine)
|
|||||||
CFLAGS += -DPC_HOSTED -DNO_LIBOPENCM3 -DENABLE_DEBUG
|
CFLAGS += -DPC_HOSTED -DNO_LIBOPENCM3 -DENABLE_DEBUG
|
||||||
CFLAGS +=-I ./target -I./platforms/pc
|
CFLAGS +=-I ./target -I./platforms/pc
|
||||||
ifneq (, $(findstring mingw, $(SYS)))
|
ifneq (, $(findstring mingw, $(SYS)))
|
||||||
|
SRC += serial_win.c
|
||||||
LDFLAGS += -lws2_32
|
LDFLAGS += -lws2_32
|
||||||
else ifneq (, $(findstring cygwin, $(SYS)))
|
else ifneq (, $(findstring cygwin, $(SYS)))
|
||||||
|
SRC += serial_win.c
|
||||||
LDFLAGS += -lws2_32
|
LDFLAGS += -lws2_32
|
||||||
|
else
|
||||||
|
SRC += serial_unix.c
|
||||||
endif
|
endif
|
||||||
VPATH += platforms/pc
|
VPATH += platforms/pc
|
||||||
SRC += cl_utils.c timing.c utils.c
|
SRC += cl_utils.c timing.c utils.c
|
||||||
|
@ -25,77 +25,16 @@
|
|||||||
#include "remote.h"
|
#include "remote.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <termios.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "cl_utils.h"
|
#include "cl_utils.h"
|
||||||
|
static BMP_CL_OPTIONS_t cl_opts; /* Portable way to nullify the struct*/
|
||||||
/* Allow 100mS for responses to reach us */
|
|
||||||
#define RESP_TIMEOUT (100)
|
|
||||||
|
|
||||||
/* Define this to see the transactions across the link */
|
|
||||||
//#define DUMP_TRANSACTIONS
|
|
||||||
|
|
||||||
static int f; /* File descriptor for connection to GDB remote */
|
|
||||||
|
|
||||||
int set_interface_attribs (int fd, int speed, int parity)
|
|
||||||
|
|
||||||
/* A nice routine grabbed from
|
|
||||||
* https://stackoverflow.com/questions/6947413/how-to-open-read-and-write-from-serial-port-in-c
|
|
||||||
*/
|
|
||||||
|
|
||||||
{
|
|
||||||
struct termios tty;
|
|
||||||
memset (&tty, 0, sizeof tty);
|
|
||||||
if (tcgetattr (fd, &tty) != 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"error %d from tcgetattr", errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cfsetospeed (&tty, speed);
|
|
||||||
cfsetispeed (&tty, speed);
|
|
||||||
|
|
||||||
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
|
|
||||||
// disable IGNBRK for mismatched speed tests; otherwise receive break
|
|
||||||
// as \000 chars
|
|
||||||
tty.c_iflag &= ~IGNBRK; // disable break processing
|
|
||||||
tty.c_lflag = 0; // no signaling chars, no echo,
|
|
||||||
// no canonical processing
|
|
||||||
tty.c_oflag = 0; // no remapping, no delays
|
|
||||||
tty.c_cc[VMIN] = 0; // read doesn't block
|
|
||||||
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
|
|
||||||
|
|
||||||
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
|
|
||||||
|
|
||||||
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
|
|
||||||
// enable reading
|
|
||||||
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
|
|
||||||
tty.c_cflag |= parity;
|
|
||||||
tty.c_cflag &= ~CSTOPB;
|
|
||||||
tty.c_cflag &= ~CRTSCTS;
|
|
||||||
|
|
||||||
if (tcsetattr (fd, TCSANOW, &tty) != 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"error %d from tcsetattr", errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void platform_init(int argc, char **argv)
|
void platform_init(int argc, char **argv)
|
||||||
{
|
{
|
||||||
BMP_CL_OPTIONS_t cl_opts = {0};
|
|
||||||
cl_opts.opt_idstring = "Blackmagic Debug Probe Remote";
|
cl_opts.opt_idstring = "Blackmagic Debug Probe Remote";
|
||||||
cl_init(&cl_opts, argc, argv);
|
cl_init(&cl_opts, argc, argv);
|
||||||
char construct[PLATFORM_MAX_MSG_SIZE];
|
char construct[PLATFORM_MAX_MSG_SIZE];
|
||||||
@ -105,18 +44,8 @@ void platform_init(int argc, char **argv)
|
|||||||
printf("License GPLv3+: GNU GPL version 3 or later "
|
printf("License GPLv3+: GNU GPL version 3 or later "
|
||||||
"<http://gnu.org/licenses/gpl.html>\n\n");
|
"<http://gnu.org/licenses/gpl.html>\n\n");
|
||||||
|
|
||||||
f=open(cl_opts.opt_serial,O_RDWR|O_SYNC|O_NOCTTY);
|
if (serial_open(&cl_opts))
|
||||||
if (f<0)
|
exit(-1);
|
||||||
{
|
|
||||||
fprintf(stderr,"Couldn't open serial port %s\n", cl_opts.opt_serial);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (set_interface_attribs (f, 115000, 0)<0)
|
|
||||||
{
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int c=snprintf(construct,PLATFORM_MAX_MSG_SIZE,"%s",REMOTE_START_STR);
|
int c=snprintf(construct,PLATFORM_MAX_MSG_SIZE,"%s",REMOTE_START_STR);
|
||||||
platform_buffer_write((uint8_t *)construct,c);
|
platform_buffer_write((uint8_t *)construct,c);
|
||||||
c=platform_buffer_read((uint8_t *)construct, PLATFORM_MAX_MSG_SIZE);
|
c=platform_buffer_read((uint8_t *)construct, PLATFORM_MAX_MSG_SIZE);
|
||||||
@ -132,7 +61,7 @@ void platform_init(int argc, char **argv)
|
|||||||
int ret = cl_execute(&cl_opts);
|
int ret = cl_execute(&cl_opts);
|
||||||
if (cl_opts.opt_tpwr)
|
if (cl_opts.opt_tpwr)
|
||||||
platform_target_set_power(0);
|
platform_target_set_power(0);
|
||||||
close(f);
|
serial_close();
|
||||||
exit(ret);
|
exit(ret);
|
||||||
} else {
|
} else {
|
||||||
assert(gdb_if_init() == 0);
|
assert(gdb_if_init() == 0);
|
||||||
@ -217,96 +146,6 @@ void platform_buffer_flush(void)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int platform_buffer_write(const uint8_t *data, int size)
|
|
||||||
{
|
|
||||||
int s;
|
|
||||||
|
|
||||||
#ifdef DUMP_TRANSACTIONS
|
|
||||||
printf("%s\n",data);
|
|
||||||
#endif
|
|
||||||
s=write(f,data,size);
|
|
||||||
if (s<0)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"Failed to write\n");
|
|
||||||
exit(-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
int platform_buffer_read(uint8_t *data, int maxsize)
|
|
||||||
|
|
||||||
{
|
|
||||||
uint8_t *c;
|
|
||||||
int s;
|
|
||||||
int ret;
|
|
||||||
uint32_t endTime;
|
|
||||||
fd_set rset;
|
|
||||||
struct timeval tv;
|
|
||||||
|
|
||||||
c=data;
|
|
||||||
tv.tv_sec=0;
|
|
||||||
|
|
||||||
endTime=platform_time_ms()+RESP_TIMEOUT;
|
|
||||||
tv.tv_usec=1000*(endTime-platform_time_ms());
|
|
||||||
|
|
||||||
/* Look for start of response */
|
|
||||||
do
|
|
||||||
{
|
|
||||||
FD_ZERO(&rset);
|
|
||||||
FD_SET(f, &rset);
|
|
||||||
|
|
||||||
ret = select(f + 1, &rset, NULL, NULL, &tv);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"Failed on select\n");
|
|
||||||
exit(-4);
|
|
||||||
}
|
|
||||||
if(ret == 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"Timeout on read\n");
|
|
||||||
exit(-3);
|
|
||||||
}
|
|
||||||
|
|
||||||
s=read(f,c,1);
|
|
||||||
}
|
|
||||||
while ((s>0) && (*c!=REMOTE_RESP));
|
|
||||||
|
|
||||||
/* Now collect the response */
|
|
||||||
do
|
|
||||||
{
|
|
||||||
FD_ZERO(&rset);
|
|
||||||
FD_SET(f, &rset);
|
|
||||||
ret = select(f + 1, &rset, NULL, NULL, &tv);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"Failed on select\n");
|
|
||||||
exit(-4);
|
|
||||||
}
|
|
||||||
if(ret == 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"Timeout on read\n");
|
|
||||||
exit(-3);
|
|
||||||
}
|
|
||||||
s=read(f,c,1);
|
|
||||||
if (*c==REMOTE_EOM)
|
|
||||||
{
|
|
||||||
*c=0;
|
|
||||||
#ifdef DUMP_TRANSACTIONS
|
|
||||||
printf(" %s\n",data);
|
|
||||||
#endif
|
|
||||||
return (c-data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
c++;
|
|
||||||
}
|
|
||||||
while ((s>=0) && (c-data<maxsize));
|
|
||||||
|
|
||||||
fprintf(stderr,"Failed to read\n");
|
|
||||||
exit(-3);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *platform_target_voltage(void)
|
const char *platform_target_voltage(void)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -41,10 +41,12 @@
|
|||||||
#define SET_IDLE_STATE(state)
|
#define SET_IDLE_STATE(state)
|
||||||
#define SET_ERROR_STATE(state)
|
#define SET_ERROR_STATE(state)
|
||||||
|
|
||||||
|
/* Allow 100mS for responses to reach us */
|
||||||
|
#define RESP_TIMEOUT (100)
|
||||||
|
|
||||||
void platform_buffer_flush(void);
|
void platform_buffer_flush(void);
|
||||||
int platform_buffer_write(const uint8_t *data, int size);
|
int platform_buffer_write(const uint8_t *data, int size);
|
||||||
int platform_buffer_read(uint8_t *data, int size);
|
int platform_buffer_read(uint8_t *data, int size);
|
||||||
|
|
||||||
static inline int platform_hwversion(void)
|
static inline int platform_hwversion(void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -53,6 +53,9 @@ struct mmap_data {
|
|||||||
int fd;
|
int fd;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
int cl_debuglevel;
|
||||||
|
static struct mmap_data map; /* Portable way way to nullify the struct!*/
|
||||||
|
|
||||||
|
|
||||||
static int bmp_mmap(char *file, struct mmap_data *map)
|
static int bmp_mmap(char *file, struct mmap_data *map)
|
||||||
{
|
{
|
||||||
@ -116,6 +119,7 @@ static void cl_help(char **argv, BMP_CL_OPTIONS_t *opt)
|
|||||||
printf("Usage: %s [options]\n", argv[0]);
|
printf("Usage: %s [options]\n", argv[0]);
|
||||||
printf("\t-h\t\t: This help.\n");
|
printf("\t-h\t\t: This help.\n");
|
||||||
printf("\t-v[1|2]\t\t: Increasing verbosity\n");
|
printf("\t-v[1|2]\t\t: Increasing verbosity\n");
|
||||||
|
printf("\t-d \"path\"\t: Use serial device at \"path\"\n");
|
||||||
printf("\t-s \"string\"\t: Use dongle with (partial) "
|
printf("\t-s \"string\"\t: Use dongle with (partial) "
|
||||||
"serial number \"string\"\n");
|
"serial number \"string\"\n");
|
||||||
printf("\t-c \"string\"\t: Use ftdi dongle with type \"string\"\n");
|
printf("\t-c \"string\"\t: Use ftdi dongle with type \"string\"\n");
|
||||||
@ -145,7 +149,7 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
|
|||||||
opt->opt_target_dev = 1;
|
opt->opt_target_dev = 1;
|
||||||
opt->opt_flash_start = 0x08000000;
|
opt->opt_flash_start = 0x08000000;
|
||||||
opt->opt_flash_size = 16 * 1024 *1024;
|
opt->opt_flash_size = 16 * 1024 *1024;
|
||||||
while((c = getopt(argc, argv, "Ehv::s:c:CnN:tVta:S:jprR")) != -1) {
|
while((c = getopt(argc, argv, "Ehv::d:s:c:CnN:tVta:S:jprR")) != -1) {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 'c':
|
case 'c':
|
||||||
if (optarg)
|
if (optarg)
|
||||||
@ -156,7 +160,9 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
if (optarg)
|
if (optarg)
|
||||||
opt->opt_debuglevel = strtol(optarg, NULL, 0);
|
cl_debuglevel = strtol(optarg, NULL, 0);
|
||||||
|
else
|
||||||
|
cl_debuglevel = -1;
|
||||||
break;
|
break;
|
||||||
case 'j':
|
case 'j':
|
||||||
opt->opt_usejtag = true;
|
opt->opt_usejtag = true;
|
||||||
@ -167,6 +173,10 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
|
|||||||
case 'n':
|
case 'n':
|
||||||
opt->opt_no_wait = true;
|
opt->opt_no_wait = true;
|
||||||
break;
|
break;
|
||||||
|
case 'd':
|
||||||
|
if (optarg)
|
||||||
|
opt->opt_device = optarg;
|
||||||
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
if (optarg)
|
if (optarg)
|
||||||
opt->opt_serial = optarg;
|
opt->opt_serial = optarg;
|
||||||
@ -277,7 +287,6 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
|
|||||||
goto target_detach;
|
goto target_detach;
|
||||||
}
|
}
|
||||||
int read_file = -1;
|
int read_file = -1;
|
||||||
struct mmap_data map = {0};
|
|
||||||
if ((opt->opt_mode == BMP_MODE_FLASH_WRITE) ||
|
if ((opt->opt_mode == BMP_MODE_FLASH_WRITE) ||
|
||||||
(opt->opt_mode == BMP_MODE_FLASH_VERIFY)) {
|
(opt->opt_mode == BMP_MODE_FLASH_VERIFY)) {
|
||||||
int mmap_res = bmp_mmap(opt->opt_flash_file, &map);
|
int mmap_res = bmp_mmap(opt->opt_flash_file, &map);
|
||||||
|
@ -41,6 +41,7 @@ typedef struct BMP_CL_OPTIONS_s {
|
|||||||
bool opt_tpwr;
|
bool opt_tpwr;
|
||||||
bool opt_connect_under_reset;
|
bool opt_connect_under_reset;
|
||||||
char *opt_flash_file;
|
char *opt_flash_file;
|
||||||
|
char *opt_device;
|
||||||
char *opt_serial;
|
char *opt_serial;
|
||||||
char *opt_cable;
|
char *opt_cable;
|
||||||
int opt_debuglevel;
|
int opt_debuglevel;
|
||||||
@ -52,4 +53,6 @@ typedef struct BMP_CL_OPTIONS_s {
|
|||||||
|
|
||||||
void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv);
|
void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv);
|
||||||
int cl_execute(BMP_CL_OPTIONS_t *opt);
|
int cl_execute(BMP_CL_OPTIONS_t *opt);
|
||||||
|
int serial_open(BMP_CL_OPTIONS_t *opt);
|
||||||
|
void serial_close(void);
|
||||||
#endif
|
#endif
|
||||||
|
215
src/platforms/pc/serial_unix.c
Normal file
215
src/platforms/pc/serial_unix.c
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Black Magic Debug project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Dave Marples <dave@marples.net>
|
||||||
|
* with additions from 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 <sys/stat.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "general.h"
|
||||||
|
#include "remote.h"
|
||||||
|
#include "cl_utils.h"
|
||||||
|
|
||||||
|
static int fd; /* File descriptor for connection to GDB remote */
|
||||||
|
extern int cl_debuglevel;
|
||||||
|
/* A nice routine grabbed from
|
||||||
|
* https://stackoverflow.com/questions/6947413/how-to-open-read-and-write-from-serial-port-in-c
|
||||||
|
*/
|
||||||
|
static int set_interface_attribs(void)
|
||||||
|
{
|
||||||
|
struct termios tty;
|
||||||
|
memset (&tty, 0, sizeof tty);
|
||||||
|
if (tcgetattr (fd, &tty) != 0) {
|
||||||
|
fprintf(stderr,"error %d from tcgetattr", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
|
||||||
|
// disable IGNBRK for mismatched speed tests; otherwise receive break
|
||||||
|
// as \000 chars
|
||||||
|
tty.c_iflag &= ~IGNBRK; // disable break processing
|
||||||
|
tty.c_lflag = 0; // no signaling chars, no echo,
|
||||||
|
// no canonical processing
|
||||||
|
tty.c_oflag = 0; // no remapping, no delays
|
||||||
|
tty.c_cc[VMIN] = 0; // read doesn't block
|
||||||
|
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
|
||||||
|
|
||||||
|
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
|
||||||
|
|
||||||
|
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
|
||||||
|
// enable reading
|
||||||
|
tty.c_cflag &= ~CSTOPB;
|
||||||
|
tty.c_cflag &= ~CRTSCTS;
|
||||||
|
|
||||||
|
if (tcsetattr (fd, TCSANOW, &tty) != 0) {
|
||||||
|
fprintf(stderr,"error %d from tcsetattr", errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#define BMP_IDSTRING "usb-Black_Sphere_Technologies_Black_Magic_Probe"
|
||||||
|
#define DEVICE_BY_ID "/dev/serial/by-id/"
|
||||||
|
int serial_open(BMP_CL_OPTIONS_t *opt)
|
||||||
|
{
|
||||||
|
char name[256];
|
||||||
|
if (!opt->opt_device) {
|
||||||
|
/* Try to find some BMP if0*/
|
||||||
|
struct dirent *dp;
|
||||||
|
DIR *dir = opendir(DEVICE_BY_ID);
|
||||||
|
if (!dir) {
|
||||||
|
fprintf(stderr, "No serial device found\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int num_devices = 0;
|
||||||
|
int num_total = 0;
|
||||||
|
while ((dp = readdir(dir)) != NULL) {
|
||||||
|
if ((strstr(dp->d_name, BMP_IDSTRING)) &&
|
||||||
|
(strstr(dp->d_name, "-if00"))) {
|
||||||
|
num_total++;
|
||||||
|
if (((opt->opt_serial) &&
|
||||||
|
(!strstr(dp->d_name, opt->opt_serial))))
|
||||||
|
continue;
|
||||||
|
num_devices++;
|
||||||
|
strcpy(name, DEVICE_BY_ID);
|
||||||
|
strncat(name, dp->d_name, sizeof(name) - strlen(name) - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
if ((num_devices == 0) && (num_total == 0)){
|
||||||
|
fprintf(stderr, "No BMP probe found\n");
|
||||||
|
return -1;
|
||||||
|
} else if (num_devices != 1) {
|
||||||
|
fprintf(stderr, "Available Probes:\n");
|
||||||
|
dir = opendir(DEVICE_BY_ID);
|
||||||
|
if (dir) {
|
||||||
|
while ((dp = readdir(dir)) != NULL) {
|
||||||
|
if ((strstr(dp->d_name, BMP_IDSTRING)) &&
|
||||||
|
(strstr(dp->d_name, "-if00")))
|
||||||
|
fprintf(stderr, "%s\n", dp->d_name);
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
if (opt->opt_serial)
|
||||||
|
fprintf(stderr, "Do no match given serial \"%s\"\n", opt->opt_serial);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "Select Probe with -s <(Partial) Serial Number\n");
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Could not opendir %s: %s\n", name, strerror(errno));
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
strncpy(name, opt->opt_device, sizeof(name) - 1);
|
||||||
|
}
|
||||||
|
fd = open(name, O_RDWR | O_SYNC | O_NOCTTY);
|
||||||
|
if (fd < 0) {
|
||||||
|
fprintf(stderr,"Couldn't open serial port %s\n", name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* BMP only offers an USB-Serial connection with no real serial
|
||||||
|
* line in between. No need for baudrate or parity.!
|
||||||
|
*/
|
||||||
|
return set_interface_attribs();
|
||||||
|
}
|
||||||
|
|
||||||
|
void serial_close(void)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int platform_buffer_write(const uint8_t *data, int size)
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
|
||||||
|
if (cl_debuglevel)
|
||||||
|
printf("%s\n",data);
|
||||||
|
s = write(fd, data, size);
|
||||||
|
if (s < 0) {
|
||||||
|
fprintf(stderr, "Failed to write\n");
|
||||||
|
exit(-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int platform_buffer_read(uint8_t *data, int maxsize)
|
||||||
|
{
|
||||||
|
uint8_t *c;
|
||||||
|
int s;
|
||||||
|
int ret;
|
||||||
|
uint32_t endTime;
|
||||||
|
fd_set rset;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
c = data;
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
|
||||||
|
endTime = platform_time_ms() + RESP_TIMEOUT;
|
||||||
|
tv.tv_usec = 1000 * (endTime - platform_time_ms());
|
||||||
|
|
||||||
|
/* Look for start of response */
|
||||||
|
do {
|
||||||
|
FD_ZERO(&rset);
|
||||||
|
FD_SET(fd, &rset);
|
||||||
|
|
||||||
|
ret = select(fd + 1, &rset, NULL, NULL, &tv);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr,"Failed on select\n");
|
||||||
|
exit(-4);
|
||||||
|
}
|
||||||
|
if(ret == 0) {
|
||||||
|
fprintf(stderr,"Timeout on read RESP\n");
|
||||||
|
exit(-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
s = read(fd, c, 1);
|
||||||
|
}
|
||||||
|
while ((s > 0) && (*c != REMOTE_RESP));
|
||||||
|
/* Now collect the response */
|
||||||
|
do {
|
||||||
|
FD_ZERO(&rset);
|
||||||
|
FD_SET(fd, &rset);
|
||||||
|
ret = select(fd + 1, &rset, NULL, NULL, &tv);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr,"Failed on select\n");
|
||||||
|
exit(-4);
|
||||||
|
}
|
||||||
|
if(ret == 0) {
|
||||||
|
fprintf(stderr,"Timeout on read\n");
|
||||||
|
exit(-3);
|
||||||
|
}
|
||||||
|
s = read(fd, c, 1);
|
||||||
|
if (*c==REMOTE_EOM) {
|
||||||
|
*c = 0;
|
||||||
|
if (cl_debuglevel)
|
||||||
|
printf(" %s\n",data);
|
||||||
|
return (c - data);
|
||||||
|
} else {
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
}while ((s >= 0) && ((c - data) < maxsize));
|
||||||
|
|
||||||
|
fprintf(stderr,"Failed to read\n");
|
||||||
|
exit(-3);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
139
src/platforms/pc/serial_win.c
Normal file
139
src/platforms/pc/serial_win.c
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
extern int cl_debuglevel;
|
||||||
|
|
||||||
|
int serial_open(BMP_CL_OPTIONS_t *opt)
|
||||||
|
{
|
||||||
|
if (!opt->opt_device) {
|
||||||
|
fprintf(stderr,"Specify the serial device to use!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
char device[256];
|
||||||
|
if (strstr(opt->opt_device, "\\\\.\\")) {
|
||||||
|
strncpy(device, opt->opt_device, sizeof(device) - 1);
|
||||||
|
} else {
|
||||||
|
strcpy(device, "\\\\.\\");
|
||||||
|
strncat(device, opt->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) {
|
||||||
|
fprintf(stderr, "Could not open %s: %ld\n", device,
|
||||||
|
GetLastError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
DCB dcbSerialParams;
|
||||||
|
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
|
||||||
|
if (!GetCommState(hComm, &dcbSerialParams)) {
|
||||||
|
fprintf(stderr, "GetCommState failed %ld\n", GetLastError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
dcbSerialParams.ByteSize = 8;
|
||||||
|
if (!SetCommState(hComm, &dcbSerialParams)) {
|
||||||
|
fprintf(stderr, "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)) {
|
||||||
|
fprintf(stderr, "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)
|
||||||
|
{
|
||||||
|
if (cl_debuglevel)
|
||||||
|
printf("%s\n",data);
|
||||||
|
int s = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
DWORD written;
|
||||||
|
if (!WriteFile(hComm, data + s, size - s, &written, NULL)) {
|
||||||
|
fprintf(stderr, "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)) {
|
||||||
|
fprintf(stderr,"ERROR on read RESP\n");
|
||||||
|
exit(-3);
|
||||||
|
}
|
||||||
|
if (platform_time_ms() > endTime) {
|
||||||
|
fprintf(stderr,"Timeout on read RESP\n");
|
||||||
|
exit(-4);
|
||||||
|
}
|
||||||
|
} while (response != REMOTE_RESP);
|
||||||
|
uint8_t *c = data;
|
||||||
|
do {
|
||||||
|
if (!ReadFile(hComm, c, 1, &s, NULL)) {
|
||||||
|
fprintf(stderr,"Error on read\n");
|
||||||
|
exit(-3);
|
||||||
|
}
|
||||||
|
if (s > 0 ) {
|
||||||
|
if (cl_debuglevel)
|
||||||
|
printf("%c", *c);
|
||||||
|
if (*c == REMOTE_EOM) {
|
||||||
|
*c = 0;
|
||||||
|
if (cl_debuglevel)
|
||||||
|
printf("\n");
|
||||||
|
return (c - data);
|
||||||
|
} else {
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (((c - data) < maxsize) && (platform_time_ms() < endTime));
|
||||||
|
fprintf(stderr,"Failed to read EOM at %d\n",
|
||||||
|
platform_time_ms() - startTime);
|
||||||
|
exit(-3);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user