configure.ac: Replace --enable-verbose-usb-comms with a new runtime log level.
--enable-verbose actually did the same as --enable-verbose-usb-comms, so the new code replaces it too. Change-Id: I1d1ddd5d681009663e0c52a75ad76fe71dbc172a Signed-off-by: R. Diez <rdiez-2006@rd10.de> Reviewed-on: https://review.openocd.org/c/openocd/+/9281 Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com> Tested-by: jenkins Reviewed-by: Marc Schink <dev@zapb.de>
This commit is contained in:
21
configure.ac
21
configure.ac
@@ -268,27 +268,6 @@ AS_IF([test "x$enable_gcov" = "xyes"], [
|
||||
AC_DEFINE([USE_GCOV], [0], [0 to leave coverage collection disabled.])
|
||||
])
|
||||
|
||||
# set default for debug_usb_comms, overridden by following options
|
||||
debug_usb_comms=no
|
||||
|
||||
AC_ARG_ENABLE([verbose],
|
||||
AS_HELP_STRING([--enable-verbose],
|
||||
[Enable verbose JTAG I/O messages (for debugging).]),
|
||||
[
|
||||
debug_usb_comms=$enableval
|
||||
], [])
|
||||
|
||||
AC_ARG_ENABLE([verbose_usb_comms],
|
||||
AS_HELP_STRING([--enable-verbose-usb-comms],
|
||||
[Enable verbose USB communication messages (for debugging)]),
|
||||
[debug_usb_comms=$enableval], [])
|
||||
|
||||
AC_MSG_CHECKING([whether to enable verbose USB communication messages]);
|
||||
AC_MSG_RESULT([$debug_usb_comms])
|
||||
AS_IF([test "x$debug_usb_comms" = "xyes"], [
|
||||
AC_DEFINE([_DEBUG_USB_COMMS_],[1], [Print verbose USB communication messages])
|
||||
])
|
||||
|
||||
debug_malloc=no
|
||||
AC_ARG_ENABLE([malloc_logging],
|
||||
AS_HELP_STRING([--enable-malloc-logging],
|
||||
|
||||
@@ -9566,7 +9566,8 @@ Level 0 is error messages only;
|
||||
level 1 adds warnings;
|
||||
level 2 adds informational messages;
|
||||
level 3 adds debugging messages;
|
||||
and level 4 adds verbose low-level debug messages.
|
||||
level 4 adds verbose low-level debug messages;
|
||||
and level 5 adds USB communication messages.
|
||||
The default is level 2, but that can be overridden on
|
||||
the command line along with the location of that log
|
||||
file (which is normally the server's standard output).
|
||||
|
||||
@@ -53,13 +53,14 @@ static int64_t last_time;
|
||||
|
||||
static int64_t start;
|
||||
|
||||
static const char * const log_strings[6] = {
|
||||
static const char * const log_strings[7] = {
|
||||
"User : ",
|
||||
"Error: ",
|
||||
"Warn : ", /* want a space after each colon, all same width, colons aligned */
|
||||
"Info : ",
|
||||
"Debug: ",
|
||||
"Debug: "
|
||||
"Debug: ",
|
||||
"Debug: ", /* corresponds to LOG_LVL_DEBUG_USB */
|
||||
};
|
||||
|
||||
static int count;
|
||||
@@ -212,7 +213,7 @@ COMMAND_HANDLER(handle_debug_level_command)
|
||||
} else if (CMD_ARGC == 1) {
|
||||
int new_level;
|
||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], new_level);
|
||||
if ((new_level > LOG_LVL_DEBUG_IO) || (new_level < LOG_LVL_SILENT)) {
|
||||
if (new_level > LOG_LVL_DEBUG_USB || new_level < LOG_LVL_SILENT) {
|
||||
command_print(CMD, "level must be between %d and %d", LOG_LVL_SILENT, LOG_LVL_DEBUG_IO);
|
||||
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,9 @@
|
||||
* LOG_LVL_INFO - state information, etc.
|
||||
* LOG_LVL_DEBUG - debug statements, execution trace
|
||||
* LOG_LVL_DEBUG_IO - verbose debug, low-level I/O trace
|
||||
* LOG_LVL_DEBUG_USB - verbose USB trace
|
||||
* In the past this corresponded to build configuration options
|
||||
--enable-verbose and --enable-verbose-usb-comms.
|
||||
*/
|
||||
enum log_levels {
|
||||
LOG_LVL_SILENT = -3,
|
||||
@@ -47,6 +50,7 @@ enum log_levels {
|
||||
LOG_LVL_INFO = 2,
|
||||
LOG_LVL_DEBUG = 3,
|
||||
LOG_LVL_DEBUG_IO = 4,
|
||||
LOG_LVL_DEBUG_USB = 5,
|
||||
};
|
||||
|
||||
void log_printf(enum log_levels level, const char *file, unsigned int line,
|
||||
@@ -100,6 +104,8 @@ extern int debug_level;
|
||||
|
||||
#define LOG_LEVEL_IS(FOO) ((debug_level) >= (FOO))
|
||||
|
||||
#define LOG_DEBUG_USB(expr, ...) LOG_CUSTOM_LEVEL(LOG_LVL_DEBUG_USB, expr, ##__VA_ARGS__)
|
||||
|
||||
#define LOG_DEBUG_IO(expr ...) \
|
||||
do { \
|
||||
if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) \
|
||||
|
||||
@@ -76,9 +76,7 @@ static int armjtagew_usb_read(struct armjtagew *armjtagew, int exp_in_length);
|
||||
/* helper functions */
|
||||
static int armjtagew_get_version_info(void);
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
static void armjtagew_debug_buffer(uint8_t *buffer, int length);
|
||||
#endif
|
||||
|
||||
static struct armjtagew *armjtagew_handle;
|
||||
|
||||
@@ -127,9 +125,8 @@ static int armjtagew_execute_queue(struct jtag_command *cmd_queue)
|
||||
scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
|
||||
LOG_DEBUG_IO("scan input, length = %d", scan_size);
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
armjtagew_debug_buffer(buffer, (scan_size + 7) / 8);
|
||||
#endif
|
||||
|
||||
type = jtag_scan_type(cmd->cmd.scan);
|
||||
armjtagew_scan(cmd->cmd.scan->ir_scan,
|
||||
type, buffer,
|
||||
@@ -641,9 +638,7 @@ static int armjtagew_tap_execute(void)
|
||||
|
||||
LOG_DEBUG_IO("pending scan result, length = %d", length);
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
armjtagew_debug_buffer(buffer, byte_length);
|
||||
#endif
|
||||
|
||||
if (jtag_read_buffer(buffer, command) != ERROR_OK) {
|
||||
armjtagew_tap_init();
|
||||
@@ -743,9 +738,8 @@ static int armjtagew_usb_write(struct armjtagew *armjtagew, int out_length)
|
||||
|
||||
LOG_DEBUG_IO("armjtagew_usb_write, out_length = %d, result = %d", out_length, result);
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
armjtagew_debug_buffer(usb_out_buffer, out_length);
|
||||
#endif
|
||||
|
||||
if (result != ERROR_OK)
|
||||
return -1;
|
||||
return transferred;
|
||||
@@ -760,29 +754,29 @@ static int armjtagew_usb_read(struct armjtagew *armjtagew, int exp_in_length)
|
||||
|
||||
LOG_DEBUG_IO("armjtagew_usb_read, result = %d", result);
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
armjtagew_debug_buffer(usb_in_buffer, result);
|
||||
#endif
|
||||
|
||||
if (result != ERROR_OK)
|
||||
return -1;
|
||||
return transferred;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
#define BYTES_PER_LINE 16
|
||||
|
||||
static void armjtagew_debug_buffer(uint8_t *buffer, int length)
|
||||
{
|
||||
if (!LOG_LEVEL_IS(LOG_LVL_DEBUG_USB))
|
||||
return;
|
||||
|
||||
char line[8 + 3 * BYTES_PER_LINE + 1];
|
||||
|
||||
for (int i = 0; i < length; i += BYTES_PER_LINE) {
|
||||
int n = snprintf(line, 9, "%04x", i);
|
||||
for (int j = i; j < i + BYTES_PER_LINE && j < length; j++)
|
||||
n += snprintf(line + n, 4, " %02x", buffer[j]);
|
||||
LOG_DEBUG("%s", line);
|
||||
LOG_DEBUG_USB("%s", line);
|
||||
|
||||
/* Prevent GDB timeout (writing to log might take some time) */
|
||||
keep_alive();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -134,10 +134,7 @@ static int opendous_usb_read(struct opendous_jtag *opendous_jtag);
|
||||
|
||||
/* helper functions */
|
||||
static int opendous_get_version_info(void);
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
static void opendous_debug_buffer(uint8_t *buffer, int length);
|
||||
#endif
|
||||
|
||||
static struct opendous_jtag *opendous_jtag_handle;
|
||||
|
||||
@@ -282,9 +279,8 @@ static int opendous_execute_queue(struct jtag_command *cmd_queue)
|
||||
scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
|
||||
LOG_DEBUG_IO("scan input, length = %d", scan_size);
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
opendous_debug_buffer(buffer, (scan_size + 7) / 8);
|
||||
#endif
|
||||
|
||||
type = jtag_scan_type(cmd->cmd.scan);
|
||||
opendous_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size, cmd->cmd.scan);
|
||||
break;
|
||||
@@ -604,10 +600,7 @@ int opendous_tap_execute(void)
|
||||
int byte_length;
|
||||
int i, j;
|
||||
int result;
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
int byte_length_out;
|
||||
#endif
|
||||
|
||||
if (tap_length > 0) {
|
||||
|
||||
@@ -615,10 +608,8 @@ int opendous_tap_execute(void)
|
||||
/* LOG_INFO("OPENDOUS tap execute %d",tap_length); */
|
||||
byte_length = (tap_length + 3) / 4;
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
byte_length_out = (tap_length + 7) / 8;
|
||||
LOG_DEBUG("opendous is sending %d bytes", byte_length);
|
||||
#endif
|
||||
LOG_DEBUG_USB("opendous is sending %d bytes", byte_length);
|
||||
|
||||
for (j = 0, i = 0; j < byte_length;) {
|
||||
|
||||
@@ -647,10 +638,8 @@ int opendous_tap_execute(void)
|
||||
j += transmit;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
LOG_DEBUG("opendous tap result %d", byte_length_out);
|
||||
LOG_DEBUG_USB("opendous tap result %d", byte_length_out);
|
||||
opendous_debug_buffer(tdo_buffer, byte_length_out);
|
||||
#endif
|
||||
|
||||
/* LOG_INFO("eStick tap execute %d",tap_length); */
|
||||
for (i = 0; i < pending_scan_results_length; i++) {
|
||||
@@ -666,9 +655,7 @@ int opendous_tap_execute(void)
|
||||
|
||||
LOG_DEBUG_IO("pending scan result, length = %d", length);
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
opendous_debug_buffer(buffer, byte_length_out);
|
||||
#endif
|
||||
|
||||
if (jtag_read_buffer(buffer, command) != ERROR_OK) {
|
||||
opendous_tap_init();
|
||||
@@ -739,9 +726,8 @@ int opendous_usb_write(struct opendous_jtag *opendous_jtag, int out_length)
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
LOG_DEBUG("USB write begin");
|
||||
#endif
|
||||
LOG_DEBUG_USB("USB write begin");
|
||||
|
||||
if (opendous_probe->CONTROL_TRANSFER) {
|
||||
result = jtag_libusb_control_transfer(opendous_jtag->usb_handle,
|
||||
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
|
||||
@@ -754,15 +740,13 @@ int opendous_usb_write(struct opendous_jtag *opendous_jtag, int out_length)
|
||||
jtag_libusb_bulk_write(opendous_jtag->usb_handle, OPENDOUS_WRITE_ENDPOINT,
|
||||
(char *)usb_out_buffer, out_length, OPENDOUS_USB_TIMEOUT, &result);
|
||||
}
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
LOG_DEBUG("USB write end: %d bytes", result);
|
||||
#endif
|
||||
|
||||
LOG_DEBUG_USB("USB write end: %d bytes", result);
|
||||
|
||||
LOG_DEBUG_IO("opendous_usb_write, out_length = %d, result = %d", out_length, result);
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
opendous_debug_buffer(usb_out_buffer, out_length);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -771,9 +755,8 @@ int opendous_usb_read(struct opendous_jtag *opendous_jtag)
|
||||
{
|
||||
int transferred;
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
LOG_DEBUG("USB read begin");
|
||||
#endif
|
||||
LOG_DEBUG_USB("USB read begin");
|
||||
|
||||
int result;
|
||||
if (opendous_probe->CONTROL_TRANSFER) {
|
||||
result = jtag_libusb_control_transfer(opendous_jtag->usb_handle,
|
||||
@@ -787,29 +770,29 @@ int opendous_usb_read(struct opendous_jtag *opendous_jtag)
|
||||
jtag_libusb_bulk_read(opendous_jtag->usb_handle, OPENDOUS_READ_ENDPOINT,
|
||||
(char *)usb_in_buffer, OPENDOUS_IN_BUFFER_SIZE, OPENDOUS_USB_TIMEOUT, &result);
|
||||
}
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
LOG_DEBUG("USB read end: %d bytes", result);
|
||||
#endif
|
||||
|
||||
LOG_DEBUG_USB("USB read end: %d bytes", result);
|
||||
|
||||
LOG_DEBUG_IO("opendous_usb_read, result = %d", result);
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
opendous_debug_buffer(usb_in_buffer, result);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
#define BYTES_PER_LINE 16
|
||||
|
||||
void opendous_debug_buffer(uint8_t *buffer, int length)
|
||||
{
|
||||
if (!LOG_LEVEL_IS(LOG_LVL_DEBUG_USB))
|
||||
return;
|
||||
|
||||
char line[8 + 3 * BYTES_PER_LINE + 1];
|
||||
|
||||
for (int i = 0; i < length; i += BYTES_PER_LINE) {
|
||||
int n = snprintf(line, 9, "%04x", i);
|
||||
for (int j = i; j < i + BYTES_PER_LINE && j < length; j++)
|
||||
n += snprintf(line + n, 4, " %02x", buffer[j]);
|
||||
LOG_DEBUG("%s", line);
|
||||
LOG_DEBUG_USB("%s", line);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -119,8 +119,6 @@ static const uint16_t cy7c65215_pids[] = {0x0007, 0};
|
||||
|
||||
static unsigned int ep_in, ep_out;
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
|
||||
#define DEBUG_TYPE_READ 0
|
||||
#define DEBUG_TYPE_WRITE 1
|
||||
#define DEBUG_TYPE_OCD_READ 2
|
||||
@@ -129,6 +127,9 @@ static unsigned int ep_in, ep_out;
|
||||
#define LINE_LEN 16
|
||||
static void openjtag_debug_buffer(uint8_t *buffer, int length, uint8_t type)
|
||||
{
|
||||
if (!LOG_LEVEL_IS(LOG_LVL_DEBUG_USB))
|
||||
return;
|
||||
|
||||
char line[128];
|
||||
char s[4];
|
||||
int i;
|
||||
@@ -149,7 +150,7 @@ static void openjtag_debug_buffer(uint8_t *buffer, int length, uint8_t type)
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_DEBUG("%s", line);
|
||||
LOG_DEBUG_USB("%s", line);
|
||||
|
||||
for (i = 0; i < length; i += LINE_LEN) {
|
||||
switch (type) {
|
||||
@@ -171,13 +172,11 @@ static void openjtag_debug_buffer(uint8_t *buffer, int length, uint8_t type)
|
||||
sprintf(s, " %02x", buffer[j]);
|
||||
strcat(line, s);
|
||||
}
|
||||
LOG_DEBUG("%s", line);
|
||||
LOG_DEBUG_USB("%s", line);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int8_t openjtag_get_tap_state(int8_t state)
|
||||
{
|
||||
|
||||
@@ -207,9 +206,8 @@ static int openjtag_buf_write_standard(
|
||||
uint8_t *buf, int size, uint32_t *bytes_written)
|
||||
{
|
||||
int retval;
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
|
||||
openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE);
|
||||
#endif
|
||||
|
||||
retval = ftdi_write_data(&ftdic, buf, size);
|
||||
if (retval < 0) {
|
||||
@@ -228,9 +226,7 @@ static int openjtag_buf_write_cy7c65215(
|
||||
{
|
||||
int ret;
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE);
|
||||
#endif
|
||||
|
||||
if (size == 0) {
|
||||
*bytes_written = 0;
|
||||
@@ -287,9 +283,7 @@ static int openjtag_buf_read_standard(
|
||||
*bytes_read += retval;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ);
|
||||
#endif
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
@@ -320,9 +314,7 @@ static int openjtag_buf_read_cy7c65215(
|
||||
*bytes_read = ret;
|
||||
|
||||
out:
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ);
|
||||
#endif
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
@@ -585,10 +577,9 @@ static int openjtag_execute_tap_queue(void)
|
||||
count++;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
openjtag_debug_buffer(buffer,
|
||||
DIV_ROUND_UP(openjtag_scan_result_buffer[res_count].bits, 8), DEBUG_TYPE_OCD_READ);
|
||||
#endif
|
||||
|
||||
jtag_read_buffer(buffer, openjtag_scan_result_buffer[res_count].command);
|
||||
|
||||
free(openjtag_scan_result_buffer[res_count].buffer);
|
||||
@@ -725,9 +716,8 @@ static void openjtag_execute_scan(struct jtag_command *cmd)
|
||||
tap_set_end_state(cmd->cmd.scan->end_state);
|
||||
scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
openjtag_debug_buffer(buffer, (scan_size + 7) / 8, DEBUG_TYPE_BUFFER);
|
||||
#endif
|
||||
|
||||
/* set state */
|
||||
old_state = tap_get_end_state();
|
||||
openjtag_set_state(cmd->cmd.scan->ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT);
|
||||
|
||||
@@ -126,17 +126,17 @@ static int icdi_send_packet(void *handle, int len)
|
||||
|
||||
len += sprintf(&h->write_buffer[len], PACKET_END "%02x", cksum);
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
if (LOG_LEVEL_IS(LOG_LVL_DEBUG_USB)) {
|
||||
char buffer[50];
|
||||
char ch = h->write_buffer[1];
|
||||
if (ch == 'x' || ch == 'X')
|
||||
LOG_DEBUG("writing packet: <binary>");
|
||||
else {
|
||||
memcpy(buffer, h->write_buffer, len >= 50 ? 50-1 : len);
|
||||
if (ch == 'x' || ch == 'X') {
|
||||
LOG_DEBUG_USB("writing packet: <binary>");
|
||||
} else {
|
||||
memcpy(buffer, h->write_buffer, len >= 50 ? 50 - 1 : len);
|
||||
buffer[len] = 0;
|
||||
LOG_DEBUG("writing packet: %s", buffer);
|
||||
LOG_DEBUG_USB("writing packet: %s", buffer);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
|
||||
@@ -155,9 +155,7 @@ static int icdi_send_packet(void *handle, int len)
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
LOG_DEBUG("received reply: '%c' : count %d", h->read_buffer[0], transferred);
|
||||
#endif
|
||||
LOG_DEBUG_USB("received reply: '%c' : count %d", h->read_buffer[0], transferred);
|
||||
|
||||
if (h->read_buffer[0] == '-') {
|
||||
LOG_DEBUG("Resending packet %d", ++retry);
|
||||
@@ -182,9 +180,7 @@ static int icdi_send_packet(void *handle, int len)
|
||||
result = libusb_bulk_transfer(h->usb_dev, ICDI_READ_ENDPOINT, (unsigned char *)h->read_buffer + h->read_count,
|
||||
h->max_packet - h->read_count, &transferred, ICDI_READ_TIMEOUT);
|
||||
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
LOG_DEBUG("received data: count %d", transferred);
|
||||
#endif
|
||||
LOG_DEBUG_USB("received data: count %d", transferred);
|
||||
|
||||
/* check for errors but retry for timeout */
|
||||
if (result != 0) {
|
||||
|
||||
@@ -2175,12 +2175,10 @@ static int ulink_init(void)
|
||||
ulink_handle = NULL;
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
#ifdef _DEBUG_USB_COMMS_
|
||||
else {
|
||||
/* Successfully received Bulk IN packet -> continue */
|
||||
LOG_INFO("Recovered from lost Bulk IN packet");
|
||||
LOG_DEBUG_USB("Recovered from lost Bulk IN packet");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
ulink_clear_queue(ulink_handle);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user