From be019508759ed49dfcd3024cda6acbfbaa273771 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Sun, 29 Jan 2023 18:19:49 +0800
Subject: [PATCH 01/36] sipeed-slogic-analyzer: Initial driver skeleton.

---
 Makefile.am                                   |   6 +
 configure.ac                                  |   1 +
 src/hardware/sipeed-slogic-analyzer/api.c     | 154 ++++++++++++++++++
 .../sipeed-slogic-analyzer/protocol.c         |  43 +++++
 .../sipeed-slogic-analyzer/protocol.h         |  35 ++++
 5 files changed, 239 insertions(+)
 create mode 100644 src/hardware/sipeed-slogic-analyzer/api.c
 create mode 100644 src/hardware/sipeed-slogic-analyzer/protocol.c
 create mode 100644 src/hardware/sipeed-slogic-analyzer/protocol.h

diff --git a/Makefile.am b/Makefile.am
index 3b68142f2..7f21304dc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -701,6 +701,12 @@ src_libdrivers_la_SOURCES += \
 	src/hardware/siglent-sds/protocol.c \
 	src/hardware/siglent-sds/api.c
 endif
+if HW_SIPEED_SLOGIC_ANALYZER
+src_libdrivers_la_SOURCES += \
+	src/hardware/sipeed-slogic-analyzer/protocol.h \
+	src/hardware/sipeed-slogic-analyzer/protocol.c \
+	src/hardware/sipeed-slogic-analyzer/api.c
+endif
 if HW_SYSCLK_LWLA
 src_libdrivers_la_SOURCES += \
 	src/hardware/sysclk-lwla/lwla.h \
diff --git a/configure.ac b/configure.ac
index 194559ed9..7e6999c08 100644
--- a/configure.ac
+++ b/configure.ac
@@ -385,6 +385,7 @@ SR_DRIVER([serial DMM], [serial-dmm], [serial_comm])
 SR_DRIVER([serial LCR], [serial-lcr], [serial_comm])
 SR_DRIVER([SIGLENT SDL10x0], [siglent-sdl10x0])
 SR_DRIVER([Siglent SDS], [siglent-sds])
+SR_DRIVER([Sipeed Slogic Analyzer], [sipeed-slogic-analyzer])
 SR_DRIVER([Sysclk LWLA], [sysclk-lwla], [libusb])
 SR_DRIVER([Sysclk SLA5032], [sysclk-sla5032], [libusb])
 SR_DRIVER([Teleinfo], [teleinfo], [serial_comm])
diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
new file mode 100644
index 000000000..365e85920
--- /dev/null
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -0,0 +1,154 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2023 taorye <taorye@outlook.com>
+ *
+ * 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 <config.h>
+#include "protocol.h"
+
+static struct sr_dev_driver sipeed_slogic_analyzer_driver_info;
+
+static GSList *scan(struct sr_dev_driver *di, GSList *options)
+{
+	struct drv_context *drvc;
+	GSList *devices;
+
+	(void)options;
+
+	devices = NULL;
+	drvc = di->context;
+	drvc->instances = NULL;
+
+	/* TODO: scan for devices, either based on a SR_CONF_CONN option
+	 * or on a USB scan. */
+
+	return devices;
+}
+
+static int dev_open(struct sr_dev_inst *sdi)
+{
+	(void)sdi;
+
+	/* TODO: get handle from sdi->conn and open it. */
+
+	return SR_OK;
+}
+
+static int dev_close(struct sr_dev_inst *sdi)
+{
+	(void)sdi;
+
+	/* TODO: get handle from sdi->conn and close it. */
+
+	return SR_OK;
+}
+
+static int config_get(uint32_t key, GVariant **data,
+	const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
+{
+	int ret;
+
+	(void)sdi;
+	(void)data;
+	(void)cg;
+
+	ret = SR_OK;
+	switch (key) {
+	/* TODO */
+	default:
+		return SR_ERR_NA;
+	}
+
+	return ret;
+}
+
+static int config_set(uint32_t key, GVariant *data,
+	const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
+{
+	int ret;
+
+	(void)sdi;
+	(void)data;
+	(void)cg;
+
+	ret = SR_OK;
+	switch (key) {
+	/* TODO */
+	default:
+		ret = SR_ERR_NA;
+	}
+
+	return ret;
+}
+
+static int config_list(uint32_t key, GVariant **data,
+	const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
+{
+	int ret;
+
+	(void)sdi;
+	(void)data;
+	(void)cg;
+
+	ret = SR_OK;
+	switch (key) {
+	/* TODO */
+	default:
+		return SR_ERR_NA;
+	}
+
+	return ret;
+}
+
+static int dev_acquisition_start(const struct sr_dev_inst *sdi)
+{
+	/* TODO: configure hardware, reset acquisition state, set up
+	 * callbacks and send header packet. */
+
+	(void)sdi;
+
+	return SR_OK;
+}
+
+static int dev_acquisition_stop(struct sr_dev_inst *sdi)
+{
+	/* TODO: stop acquisition. */
+
+	(void)sdi;
+
+	return SR_OK;
+}
+
+static struct sr_dev_driver sipeed_slogic_analyzer_driver_info = {
+	.name = "sipeed-slogic-analyzer",
+	.longname = "Sipeed Slogic Analyzer",
+	.api_version = 1,
+	.init = std_init,
+	.cleanup = std_cleanup,
+	.scan = scan,
+	.dev_list = std_dev_list,
+	.dev_clear = std_dev_clear,
+	.config_get = config_get,
+	.config_set = config_set,
+	.config_list = config_list,
+	.dev_open = dev_open,
+	.dev_close = dev_close,
+	.dev_acquisition_start = dev_acquisition_start,
+	.dev_acquisition_stop = dev_acquisition_stop,
+	.context = NULL,
+};
+SR_REGISTER_DEV_DRIVER(sipeed_slogic_analyzer_driver_info);
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
new file mode 100644
index 000000000..7b01e9812
--- /dev/null
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2023 taorye <taorye@outlook.com>
+ *
+ * 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 <config.h>
+#include "protocol.h"
+
+SR_PRIV int sipeed_slogic_analyzer_receive_data(int fd, int revents, void *cb_data)
+{
+	const struct sr_dev_inst *sdi;
+	struct dev_context *devc;
+
+	(void)fd;
+
+	sdi = cb_data;
+	if (!sdi)
+		return TRUE;
+
+	devc = sdi->priv;
+	if (!devc)
+		return TRUE;
+
+	if (revents == G_IO_IN) {
+		/* TODO */
+	}
+
+	return TRUE;
+}
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
new file mode 100644
index 000000000..fab48d9aa
--- /dev/null
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the libsigrok project.
+ *
+ * Copyright (C) 2023 taorye <taorye@outlook.com>
+ *
+ * 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/>.
+ */
+
+#ifndef LIBSIGROK_HARDWARE_SIPEED_SLOGIC_ANALYZER_PROTOCOL_H
+#define LIBSIGROK_HARDWARE_SIPEED_SLOGIC_ANALYZER_PROTOCOL_H
+
+#include <stdint.h>
+#include <glib.h>
+#include <libsigrok/libsigrok.h>
+#include "libsigrok-internal.h"
+
+#define LOG_PREFIX "sipeed-slogic-analyzer"
+
+struct dev_context {
+};
+
+SR_PRIV int sipeed_slogic_analyzer_receive_data(int fd, int revents, void *cb_data);
+
+#endif

From a2255a5139b1d36aa2cb97b67cc8c04371fe28c8 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Mon, 20 Feb 2023 09:43:04 +0800
Subject: [PATCH 02/36] sipeed-slogic-analyzer: Add support for SlogicCombo8

feat: use pattern to control active channels

feat: capture data and regroup channels

feat: now support max 160Msps(2ch)

fix: limit samplerate and auto fit channel and ...

enable to reconnect by rescan and add new samplerates

test for windows

test windows libusb

test for continous and multi channel

test

fix: hardware/sipeed-slogic-analyzer/api.c conn init with NULL instead of UB
---
 src/hardware/sipeed-slogic-analyzer/api.c     | 245 +++++++++++++---
 .../sipeed-slogic-analyzer/protocol.c         | 272 +++++++++++++++++-
 .../sipeed-slogic-analyzer/protocol.h         | 143 ++++++++-
 3 files changed, 611 insertions(+), 49 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
index 365e85920..573c3e89e 100644
--- a/src/hardware/sipeed-slogic-analyzer/api.c
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -20,55 +20,214 @@
 #include <config.h>
 #include "protocol.h"
 
+static const uint32_t scanopts[] = {
+	SR_CONF_CONN,
+};
+
+static const uint32_t drvopts[] = {
+	SR_CONF_LOGIC_ANALYZER,
+};
+
+static const uint32_t devopts[] = {
+	SR_CONF_CONTINUOUS,
+	SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
+	SR_CONF_SAMPLERATE    | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
+	SR_CONF_TRIGGER_MATCH | SR_CONF_GET | SR_CONF_LIST,
+};
+
+static const int32_t trigger_matches[] = {
+	SR_TRIGGER_ZERO,
+	SR_TRIGGER_ONE,
+	SR_TRIGGER_RISING,
+	SR_TRIGGER_FALLING,
+	SR_TRIGGER_EDGE,
+};
+
 static struct sr_dev_driver sipeed_slogic_analyzer_driver_info;
 
 static GSList *scan(struct sr_dev_driver *di, GSList *options)
 {
+	int ret;
+	struct sr_dev_inst *sdi;
+	struct sr_usb_dev_inst *usb;
 	struct drv_context *drvc;
+	struct dev_context *devc;
+
+	struct sr_config *option;
+	struct libusb_device_descriptor des;
 	GSList *devices;
+	GSList *l, *conn_devices;
+	const char *conn;
+	char cbuf[128];
+	char *iManufacturer, *iProduct, *iSerialNumber, *iPortPath;
 
 	(void)options;
 
+	conn = NULL;
+
 	devices = NULL;
 	drvc = di->context;
 	drvc->instances = NULL;
-
-	/* TODO: scan for devices, either based on a SR_CONF_CONN option
+	
+	/* scan for devices, either based on a SR_CONF_CONN option
 	 * or on a USB scan. */
+	for (l = options; l; l = l->next) {
+		option = l->data;
+		switch (option->key) {
+		case SR_CONF_CONN:
+			conn = g_variant_get_string(option->data, NULL);
+			sr_info("use conn: %s", conn);
+			break;
+		default:
+			sr_warn("Unhandled option key: %u", option->key);
+		}
+	}
+	
+	if(!conn) {
+		conn = "359f.0300";
+	}
 
-	return devices;
+	/* Find all slogic compatible devices. */
+	conn_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, conn);
+	for(l = conn_devices; l; l = l->next) {
+		usb = l->data;
+		ret = sr_usb_open(drvc->sr_ctx->libusb_ctx, usb);
+		if (SR_OK != ret) continue;
+		libusb_get_device_descriptor(
+			libusb_get_device(usb->devhdl), &des);
+		libusb_get_string_descriptor_ascii(usb->devhdl,
+				des.iManufacturer, cbuf, sizeof(cbuf));
+		iManufacturer = g_strdup(cbuf);
+		libusb_get_string_descriptor_ascii(usb->devhdl,
+				des.iProduct, cbuf, sizeof(cbuf));
+		iProduct = g_strdup(cbuf);
+		libusb_get_string_descriptor_ascii(usb->devhdl,
+				des.iSerialNumber, cbuf, sizeof(cbuf));
+		iSerialNumber = g_strdup(cbuf);
+		usb_get_port_path(libusb_get_device(usb->devhdl),
+				cbuf, sizeof(cbuf));
+		iPortPath = g_strdup(cbuf);
+		sr_usb_close(usb);
+
+		sdi = sr_dev_inst_user_new(iManufacturer, iProduct, NULL);
+		if (!sdi) continue;
+
+		for (int i = 0; i < 8; i++) {
+			sr_snprintf_ascii(cbuf, sizeof(cbuf), "D%d", i);
+			sr_dev_inst_channel_add(sdi, i, SR_CHANNEL_LOGIC, cbuf);
+		}
+		
+		sdi->serial_num = iSerialNumber;
+		sdi->connection_id = iPortPath;
+		sdi->status = SR_ST_INACTIVE;
+		sdi->conn = usb;
+		sdi->inst_type = SR_INST_USB;
+
+		devc = g_malloc0(sizeof(struct dev_context));
+		sdi->priv = devc;
+
+
+
+		devices = g_slist_append(devices, sdi);
+	}
+	// g_slist_free_full(conn_devices, (GDestroyNotify)sr_usb_dev_inst_free);
+
+	return std_scan_complete(di, devices);
 }
 
 static int dev_open(struct sr_dev_inst *sdi)
 {
-	(void)sdi;
+	int ret;
+	struct sr_usb_dev_inst *usb;
+	struct dev_context *devc;
+	struct sr_dev_driver *di;
+	struct drv_context *drvc;
+
 
+	if (!sdi) return SR_ERR_DEV_CLOSED;
 	/* TODO: get handle from sdi->conn and open it. */
+	usb  = sdi->conn;
+	devc = sdi->priv;
+	di	 = sdi->driver;
+	drvc = di->context;
+
+	ret = sr_usb_open(drvc->sr_ctx->libusb_ctx, usb);
+	if (SR_OK != ret) return ret;
+
+	ret = libusb_claim_interface(usb->devhdl, 0);
+	if (ret != LIBUSB_SUCCESS) {
+		switch (ret) {
+		case LIBUSB_ERROR_BUSY:
+			sr_err("Unable to claim USB interface. Another "
+			       "program or driver has already claimed it.");
+			break;
+		case LIBUSB_ERROR_NO_DEVICE:
+			sr_err("Device has been disconnected.");
+			break;
+		default:
+			sr_err("Unable to claim interface: %s.",
+			       libusb_error_name(ret));
+			break;
+		}
+		return SR_ERR;
+	}
 
-	return SR_OK;
+	devc_set_samplerate(devc, samplerates[7]);
+	
+	return std_dummy_dev_open(sdi);
 }
 
 static int dev_close(struct sr_dev_inst *sdi)
 {
-	(void)sdi;
+	int ret;
+	struct sr_usb_dev_inst *usb;
+	struct dev_context *devc;
+	struct sr_dev_driver *di;
+	struct drv_context *drvc;
 
 	/* TODO: get handle from sdi->conn and close it. */
+	usb  = sdi->conn;
+	devc = sdi->priv;
+	di	 = sdi->driver;
+	drvc = di->context;
 
-	return SR_OK;
+	ret = libusb_release_interface(usb->devhdl, 0);
+	if (ret != LIBUSB_SUCCESS) {
+		switch (ret) {
+		case LIBUSB_ERROR_NO_DEVICE:
+			sr_err("Device has been disconnected.");
+			// return SR_ERR_DEV_CLOSED;
+			break;
+		default:
+			sr_err("Unable to release Interface for %s.",
+					libusb_error_name(ret));
+			break;
+		}
+	}
+	
+	sr_usb_close(usb);
+	
+	return std_dummy_dev_close(sdi);
 }
 
 static int config_get(uint32_t key, GVariant **data,
 	const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 {
 	int ret;
+	struct dev_context *devc;
 
-	(void)sdi;
-	(void)data;
 	(void)cg;
 
+	devc = sdi->priv;
+
 	ret = SR_OK;
 	switch (key) {
-	/* TODO */
+	case SR_CONF_SAMPLERATE:
+		*data = g_variant_new_uint64(devc->cur_samplerate);
+		break;
+	case SR_CONF_LIMIT_SAMPLES:
+		*data = g_variant_new_uint64(devc->limit_samples);
+		break;
 	default:
 		return SR_ERR_NA;
 	}
@@ -80,14 +239,35 @@ static int config_set(uint32_t key, GVariant *data,
 	const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 {
 	int ret;
+	struct dev_context *devc;
 
-	(void)sdi;
-	(void)data;
 	(void)cg;
 
+	devc = sdi->priv;
+
 	ret = SR_OK;
 	switch (key) {
-	/* TODO */
+	case SR_CONF_SAMPLERATE:
+		if (std_u64_idx(data, ARRAY_AND_SIZE(samplerates)) < 0) {
+			ret = SR_ERR_ARG;
+		} else {
+			devc_set_samplerate(devc, g_variant_get_uint64(data));
+			{
+			size_t idx = 0;
+				for (GSList *l = sdi->channels; l; l = l->next, idx += 1) {
+					struct sr_channel *ch = l->data;
+					if (ch->type == SR_CHANNEL_LOGIC) { /* Might as well do this now, these are static. */
+						sr_dev_channel_enable(ch, (idx >= devc->cur_samplechannel) ? FALSE : TRUE);
+					} else {
+						return SR_ERR_BUG;
+					}
+				}
+			}
+		}
+		break;
+	case SR_CONF_LIMIT_SAMPLES:
+		devc->limit_samples = g_variant_get_uint64(data);
+		break;
 	default:
 		ret = SR_ERR_NA;
 	}
@@ -100,39 +280,26 @@ static int config_list(uint32_t key, GVariant **data,
 {
 	int ret;
 
-	(void)sdi;
-	(void)data;
-	(void)cg;
-
 	ret = SR_OK;
 	switch (key) {
 	/* TODO */
+	case SR_CONF_SCAN_OPTIONS:
+	case SR_CONF_DEVICE_OPTIONS:
+		ret = STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
+		break;
+	case SR_CONF_SAMPLERATE:
+		*data = std_gvar_samplerates(ARRAY_AND_SIZE(samplerates));
+		break;
+	case SR_CONF_TRIGGER_MATCH:
+		*data = std_gvar_array_i32(ARRAY_AND_SIZE(trigger_matches));
+		break;
 	default:
-		return SR_ERR_NA;
+		ret = SR_ERR_NA;
 	}
 
 	return ret;
 }
 
-static int dev_acquisition_start(const struct sr_dev_inst *sdi)
-{
-	/* TODO: configure hardware, reset acquisition state, set up
-	 * callbacks and send header packet. */
-
-	(void)sdi;
-
-	return SR_OK;
-}
-
-static int dev_acquisition_stop(struct sr_dev_inst *sdi)
-{
-	/* TODO: stop acquisition. */
-
-	(void)sdi;
-
-	return SR_OK;
-}
-
 static struct sr_dev_driver sipeed_slogic_analyzer_driver_info = {
 	.name = "sipeed-slogic-analyzer",
 	.longname = "Sipeed Slogic Analyzer",
@@ -147,8 +314,8 @@ static struct sr_dev_driver sipeed_slogic_analyzer_driver_info = {
 	.config_list = config_list,
 	.dev_open = dev_open,
 	.dev_close = dev_close,
-	.dev_acquisition_start = dev_acquisition_start,
-	.dev_acquisition_stop = dev_acquisition_stop,
+	.dev_acquisition_start = sipeed_slogic_acquisition_start,
+	.dev_acquisition_stop = sipeed_slogic_acquisition_stop,
 	.context = NULL,
 };
 SR_REGISTER_DEV_DRIVER(sipeed_slogic_analyzer_driver_info);
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index 7b01e9812..211b174d6 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -20,24 +20,278 @@
 #include <config.h>
 #include "protocol.h"
 
-SR_PRIV int sipeed_slogic_analyzer_receive_data(int fd, int revents, void *cb_data)
-{
+static int handle_events(int fd, int revents, void *cb_data);
+
+static void submit_data(void *data, size_t len, struct sr_dev_inst *sdi) {
+	struct sr_datafeed_logic logic = {
+		.length = len,
+		.unitsize = 1,
+		.data = data,
+	};
+
+	struct sr_datafeed_packet packet = {
+		.type = SR_DF_LOGIC,
+		.payload = &logic
+	};
+
+	sr_session_send(sdi, &packet);
+}
+
+static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
+
+	int ret;
 	const struct sr_dev_inst *sdi;
 	struct dev_context *devc;
+	struct sr_usb_dev_inst *usb;
+
+	sdi  = transfer->user_data;
+	devc = sdi->priv;
+	usb  = sdi->conn;
+
+	sr_dbg("usb status: %d", transfer->status);
+	switch (transfer->status) {
+		case LIBUSB_TRANSFER_COMPLETED: 
+		case LIBUSB_TRANSFER_TIMED_OUT: { /* may have received some data */
+			sr_dbg("\ttransfing: %u, transfered: %u, sum: %u/%u",
+					devc->bytes_transferring, devc->bytes_transfered,
+					(devc->bytes_transfered + devc->bytes_transferring),
+					devc->bytes_need_transfer);
+
+			devc->bytes_transfered += transfer->actual_length;
+			devc->bytes_transferring -= transfer->length;
+
+			if (transfer->actual_length == 0) {
+				devc->transfers_used -= 1;
+				break;
+			}
+
+			{
+				uint8_t *ptr = transfer->buffer;
+				size_t len = transfer->actual_length;
+				if (devc->cur_samplechannel != 8) {
+					size_t step = 8 / devc->cur_samplechannel;
+					uint8_t mask = 0xff >> (8 - devc->cur_samplechannel);
+					len *= step;
+					ptr = g_malloc(len);
+					for(size_t i=0; i<transfer->actual_length; i++) {
+						for(size_t j=0; j<step; j++) {
+							ptr[i*step+j] = mask & (transfer->buffer[i] >> (j * devc->cur_samplechannel));
+						}
+					}
+				}
+				submit_data(ptr, len, sdi);
+				if (devc->cur_samplechannel != 8) {
+					g_free(ptr);
+				}
+			}
+
+			size_t bytes_to_transfer = devc->bytes_need_transfer -
+				(devc->bytes_transfered + devc->bytes_transferring);
+			if (bytes_to_transfer > devc->transfers_buffer_size) {
+				bytes_to_transfer = devc->transfers_buffer_size;
+			}
+			if (bytes_to_transfer) {
+				transfer->length = bytes_to_transfer;
+				transfer->actual_length = 0;
+				transfer->timeout = devc->timeout * devc->transfers_used;
+				ret = libusb_submit_transfer(transfer);
+				if (ret) {
+					sr_warn("Failed to submit transfer: %s", libusb_error_name(ret));
+					devc->transfers_used -= 1;
+				}
+				sr_dbg("submit transfer: %p", transfer);
+
+				devc->bytes_transferring += bytes_to_transfer;
+			} else {
+				devc->transfers_used -= 1;
+			}
+		} break;
+
+		case LIBUSB_TRANSFER_NO_DEVICE: {
+			devc->transfers_used = 0;
+		} break;
+
+		default: {
+			devc->transfers_used -= 1;
+		} break;
+	}
+
+	if (devc->transfers_used == 0) {
+		sr_dbg("free all transfers");
+
+		sr_dbg("Bulk in %u/%u bytes", devc->bytes_transfered,
+				devc->bytes_need_transfer);
+		
+		sr_dev_acquisition_stop(sdi);
+	}
+};
+
+static int handle_events(int fd, int revents, void *cb_data)
+{
+	struct sr_dev_inst *sdi;
+	struct sr_dev_driver *di;
+	struct dev_context *devc;
+	struct drv_context *drvc;
+	struct timeval tv;
 
 	(void)fd;
+	(void)revents;
 
 	sdi = cb_data;
-	if (!sdi)
-		return TRUE;
-
 	devc = sdi->priv;
-	if (!devc)
-		return TRUE;
+	di = sdi->driver;
+	drvc = di->context;
 
-	if (revents == G_IO_IN) {
-		/* TODO */
+	sr_dbg("handle_events enter");
+
+	if (devc->acq_aborted == TRUE) {
+		for (size_t i = 0; i < NUM_MAX_TRANSFERS; ++i) {
+			struct libusb_transfer *transfer = devc->transfers[i];
+			if (transfer) {
+				libusb_cancel_transfer(transfer);
+				g_free(transfer->buffer);
+				libusb_free_transfer(transfer);
+			}
+			devc->transfers[i] = NULL;
+		}
+
+		usb_source_remove(sdi->session, drvc->sr_ctx);
+		std_session_send_df_end(sdi);
 	}
 
+	memset(&tv, 0, sizeof(struct timeval));
+	libusb_handle_events_timeout_completed(drvc->sr_ctx->libusb_ctx, &tv,
+			&devc->acq_aborted);
+
 	return TRUE;
 }
+
+SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
+{
+	// sr_dbg("Enter func %s", __func__);
+	/* TODO: configure hardware, reset acquisition state, set up
+	 * callbacks and send header packet. */
+
+	struct sr_dev_driver *di;
+	struct dev_context *devc;
+	struct drv_context *drvc;
+	struct sr_usb_dev_inst *usb;
+
+	struct cmd_start_acquisition cmd;
+	int ret;
+	size_t size_transfer_buf;
+
+	devc = sdi->priv;
+	di = sdi->driver;
+	drvc = di->context;
+	usb  = sdi->conn;
+
+	// TODO
+	// if(devc->cur_samplechannel != 8) return SR_ERR_SAMPLERATE;
+
+	sr_dbg("samplerate: %uHz@%uch, samples: %u",
+			devc->cur_samplerate / SR_MHZ(1), 
+			devc->cur_samplechannel, 
+			devc->limit_samples);
+
+	clear_ep(EP_IN, usb->devhdl);
+
+	devc->acq_aborted = FALSE;
+  	devc->bytes_need_transfer = 0;
+	devc->bytes_transferring = 0;
+	devc->bytes_transfered = 0;
+	devc->transfers_used = 0;
+	memset(devc->transfers, 0, sizeof(devc->transfers));
+
+	devc->transfers_buffer_size = get_buffer_size(devc);
+	sr_dbg("transfers_buffer_size: %u", devc->transfers_buffer_size);
+
+	devc->timeout = get_timeout(devc);
+	sr_dbg("timeout: %ums", devc->timeout);
+	usb_source_add(sdi->session, drvc->sr_ctx, 10,
+			handle_events, (void *)sdi);
+
+	/* compute needed bytes */
+	uint64_t samples_in_bytes = devc->limit_samples * devc->cur_samplechannel / 8;
+	devc->bytes_need_transfer = samples_in_bytes / devc->transfers_buffer_size;
+	devc->bytes_need_transfer += !!(samples_in_bytes % devc->transfers_buffer_size);
+	devc->bytes_need_transfer *= devc->transfers_buffer_size;
+
+
+	while (devc->transfers_used < NUM_MAX_TRANSFERS && devc->bytes_transfered
+			+ devc->bytes_transferring < devc->bytes_need_transfer)
+	{
+		uint8_t *dev_buf = g_malloc(devc->transfers_buffer_size);
+		if (!dev_buf) {
+			sr_dbg("Failed to allocate memory");
+			sr_dev_acquisition_stop(sdi);
+			return SR_ERR_MALLOC;
+			break;
+		}
+
+		struct libusb_transfer *transfer = libusb_alloc_transfer(0);
+		if (!transfer) {
+			g_free(dev_buf);
+			sr_dbg("Failed to allocate transfer");
+			sr_dev_acquisition_stop(sdi);
+			return SR_ERR_MALLOC;
+			break;
+		}
+
+		size_t bytes_to_transfer = devc->bytes_need_transfer -
+			devc->bytes_transfered - devc->bytes_transferring;
+		if (bytes_to_transfer > devc->transfers_buffer_size) {
+			bytes_to_transfer = devc->transfers_buffer_size;
+		}
+
+		libusb_fill_bulk_transfer(transfer, usb->devhdl, EP_IN | LIBUSB_ENDPOINT_IN,
+									dev_buf, bytes_to_transfer, receive_transfer,
+									sdi, devc->timeout * (devc->transfers_used + 1));
+		transfer->actual_length = 0;
+
+		ret = libusb_submit_transfer(transfer);
+		if (ret) {
+			sr_dbg("Failed to submit transfer: %s.", libusb_error_name(ret));
+			g_free(transfer->buffer);
+			libusb_free_transfer(transfer);
+			sr_dev_acquisition_stop(sdi);
+			return SR_ERR_IO;
+			break;
+		}
+		devc->transfers[devc->transfers_used] = transfer;
+
+		devc->bytes_transferring += bytes_to_transfer;
+		devc->transfers_used += 1;
+	}
+	sr_dbg("Submited %u transfers", devc->transfers_used);
+
+	std_session_send_df_frame_begin(sdi);
+	std_session_send_df_header(sdi);
+
+
+	cmd.sample_rate = devc->cur_samplerate / SR_MHZ(1);
+	cmd.sample_channel = devc->cur_samplechannel;
+
+	ret = libusb_control_transfer(
+		usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, CMD_START, 0x0000,
+		0x0000, (unsigned char *)&cmd, 3 /*sizeof(cmd)*/, 100);
+	if (ret < 0) {
+		sr_dbg("Unable to send start command: %s", libusb_error_name(ret));
+		return SR_ERR_NA;
+	}
+	sr_dbg("CMD_STARTED");
+
+	return SR_OK;
+}
+
+SR_PRIV int sipeed_slogic_acquisition_stop(struct sr_dev_inst *sdi)
+{
+
+	struct dev_context *devc;
+
+	devc = sdi->priv;
+
+	devc->acq_aborted = TRUE;
+
+	return SR_OK;
+}
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
index fab48d9aa..34f793bcc 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
@@ -22,14 +22,155 @@
 
 #include <stdint.h>
 #include <glib.h>
+#include <libusb.h>
 #include <libsigrok/libsigrok.h>
 #include "libsigrok-internal.h"
 
 #define LOG_PREFIX "sipeed-slogic-analyzer"
 
+#define EP_IN 0x01
+#define SIZE_MAX_EP_HS 512
+#define NUM_MAX_TRANSFERS 64
+
+static const uint64_t samplerates[] = {
+	/* 160M = 2*2*2*2*2*5M */
+	SR_MHZ(1),
+	SR_MHZ(2),
+	SR_MHZ(4),
+	SR_MHZ(5),
+	SR_MHZ(8),
+	SR_MHZ(10),
+	SR_MHZ(16),
+	SR_MHZ(20),
+	SR_MHZ(32),
+	SR_MHZ(36),
+	SR_MHZ(40),
+	/* x 4ch */
+	SR_MHZ(64),
+	SR_MHZ(80),
+	/* x 2ch */
+	SR_MHZ(120),
+	SR_MHZ(128),
+	SR_MHZ(144),
+	SR_MHZ(160),
+};
+
 struct dev_context {
+	struct {
+		uint64_t limit_samples;
+		uint64_t cur_samplerate;
+		uint64_t cur_samplechannel;
+	};
+
+	uint64_t num_transfers;
+	struct libusb_transfer *transfers[NUM_MAX_TRANSFERS];
+
+	gboolean acq_aborted;
+
+	uint64_t timeout;
+
+	size_t transfers_buffer_size;
+
+	size_t bytes_need_transfer;
+	size_t bytes_transferring;
+	size_t bytes_transfered;
+	size_t transfers_used;
+
+	gboolean trigger_fired;
+	struct soft_trigger_logic *stl;
+
+	uint64_t num_frames;
+	uint64_t sent_samples;
+	int submitted_transfers;
+	int empty_transfer_count;
+
+
+	double voltage_threshold[2];
+	/* Triggers */
+	uint64_t capture_ratio;
 };
 
-SR_PRIV int sipeed_slogic_analyzer_receive_data(int fd, int revents, void *cb_data);
+static inline void devc_set_samplerate(struct dev_context *devc, uint64_t new_samplerate) {
+	devc->cur_samplerate = new_samplerate;
+	if (new_samplerate >= SR_MHZ(120)) {
+		devc->cur_samplechannel = 2;
+	} else if (new_samplerate >= SR_MHZ(40)) {
+		devc->cur_samplechannel = 4;
+	} else {
+		devc->cur_samplechannel = 8;
+	}
+	sr_info("rebind sample channel to %uCH", devc->cur_samplechannel);
+}
+
+#pragma pack(push, 1)
+struct cmd_start_acquisition {
+  union {
+    struct {
+      uint8_t sample_rate_l;
+      uint8_t sample_rate_h;
+    };
+    uint16_t sample_rate;
+  };
+	uint8_t sample_channel;
+};
+#pragma pack(pop)
+
+/* Protocol commands */
+#define CMD_START	0xb1
+#define CMD_STOP	0xb3
+
+SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi);
+SR_PRIV int sipeed_slogic_acquisition_stop(struct sr_dev_inst *sdi);
+
+static inline size_t to_bytes_per_ms(struct dev_context *devc)
+{
+	return (devc->cur_samplerate * devc->cur_samplechannel) / 8 / 1000;
+}
+
+static inline size_t get_buffer_size(struct dev_context *devc)
+{
+	/**
+	 * The buffer should be large enough to hold 10ms of data and
+	 * a multiple of 210 * 512.
+	 */
+	// const size_t pack_size = SIZE_MAX_EP_HS;
+	// size_t s = 10 * to_bytes_per_ms(devc);
+	// size_t rem = s % (210 * pack_size);
+	// if (rem) s += 210 * pack_size - rem;
+	// return s;
+	return 210 * SIZE_MAX_EP_HS;
+}
+
+static inline size_t get_number_of_transfers(struct dev_context *devc)
+{
+	/* Total buffer size should be able to hold about 500ms of data. */
+	// size_t s = 500 * to_bytes_per_ms(devc);
+	// size_t n = s / get_buffer_size(devc);
+	// size_t rem = s % get_buffer_size(devc);
+	// if (rem) n += 1;
+	// if (n > NUM_MAX_TRANSFERS)
+	// 	return NUM_MAX_TRANSFERS;
+	// return n;
+	return 1;
+}
+
+static inline size_t get_timeout(struct dev_context *devc)
+{
+	size_t total_size = get_buffer_size(devc) *
+			get_number_of_transfers(devc);
+	size_t timeout = total_size / to_bytes_per_ms(devc);
+	return timeout * 5 / 4; /* Leave a headroom of 25% percent. */
+}
+
+static inline void clear_ep(uint8_t ep, libusb_device_handle *usbh) {
+	sr_dbg("Clearring EP: %u", ep);
+	uint8_t tmp[512];
+	int actual_length = 0;
+	do {
+		libusb_bulk_transfer(usbh, ep | LIBUSB_ENDPOINT_IN,
+				tmp, sizeof(tmp), &actual_length, 100);
+	} while (actual_length);
+	sr_dbg("Cleared EP: %u", ep);
+}
 
 #endif

From b37a62787af02312cbed57f065d74905c5f4b6eb Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Fri, 14 Feb 2025 18:44:29 +0800
Subject: [PATCH 03/36] sipeed-slogic-analyzer: Add support for SlogicBasic16U3

feat: do rst before and then start

fix: todo: re impl temporary remove too heavy logic that badly affect usb transfer

fix: use internal timer instead of libusb's pollfd which can't work on Windows

tmp: 16ch format
---
 src/hardware/sipeed-slogic-analyzer/api.c     |  4 +-
 .../sipeed-slogic-analyzer/protocol.c         | 86 +++++++++++++++----
 .../sipeed-slogic-analyzer/protocol.h         |  7 +-
 3 files changed, 78 insertions(+), 19 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
index 573c3e89e..ad9ac2b36 100644
--- a/src/hardware/sipeed-slogic-analyzer/api.c
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -84,7 +84,7 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 	}
 	
 	if(!conn) {
-		conn = "359f.0300";
+		conn = "359f.3031";
 	}
 
 	/* Find all slogic compatible devices. */
@@ -112,7 +112,7 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 		sdi = sr_dev_inst_user_new(iManufacturer, iProduct, NULL);
 		if (!sdi) continue;
 
-		for (int i = 0; i < 8; i++) {
+		for (int i = 0; i < 16; i++) {
 			sr_snprintf_ascii(cbuf, sizeof(cbuf), "D%d", i);
 			sr_dev_inst_channel_add(sdi, i, SR_CHANNEL_LOGIC, cbuf);
 		}
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index 211b174d6..2d13a54c5 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -48,14 +48,16 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 	devc = sdi->priv;
 	usb  = sdi->conn;
 
-	sr_dbg("usb status: %d", transfer->status);
+	sr_dbg("[%p]usb status: %d", transfer, transfer->status);
 	switch (transfer->status) {
 		case LIBUSB_TRANSFER_COMPLETED: 
 		case LIBUSB_TRANSFER_TIMED_OUT: { /* may have received some data */
-			sr_dbg("\ttransfing: %u, transfered: %u, sum: %u/%u",
-					devc->bytes_transferring, devc->bytes_transfered,
-					(devc->bytes_transfered + devc->bytes_transferring),
-					devc->bytes_need_transfer);
+			sr_dbg("\ttransfing: %u - %u, done: %u + %u, remain: %u/%u",
+				devc->bytes_transferring, transfer->length,
+				devc->bytes_transfered, transfer->actual_length,
+				devc->bytes_need_transfer + (transfer->length - transfer->actual_length) - (devc->bytes_transfered + devc->bytes_transferring),
+				devc->bytes_need_transfer
+			);
 
 			devc->bytes_transfered += transfer->actual_length;
 			devc->bytes_transferring -= transfer->length;
@@ -65,7 +67,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 				break;
 			}
 
-			{
+			if (devc->cur_samplechannel != 16) {
 				uint8_t *ptr = transfer->buffer;
 				size_t len = transfer->actual_length;
 				if (devc->cur_samplechannel != 8) {
@@ -83,6 +85,43 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 				if (devc->cur_samplechannel != 8) {
 					g_free(ptr);
 				}
+			} else {
+				// sr_dbg("samplechannel: %d, actual_length: %u", devc->cur_samplechannel, transfer->actual_length);
+				// devc->cur_samplechannel == 16
+				uint8_t * d = transfer->buffer;
+				size_t len = transfer->actual_length;
+				// sr_dbg("HEAD: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
+				// 	d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
+
+				uint8_t *ptr = g_malloc(len);
+
+				for(size_t i=0; i<len; i+=devc->cur_samplechannel) {
+					for(size_t j=0; j< 8; j++) {
+						#define B(n) (((d[i+(n)] >> 7-j) & 0x1) << ((n)%8))
+						ptr[i+j*2+0] =
+							B(0)|B(1)|B(2)|B(3)|B(4)|B(5)|B(6)|B(7);
+						ptr[i+j*2+1] =
+							B(8)|B(9)|B(10)|B(11)|B(12)|B(13)|B(14)|B(15);
+						#undef B
+
+						// ptr[i+j*2+0] |= 0x1;
+						// ptr[i+j*2+1] |= 0x80;
+					}
+				}
+
+				struct sr_datafeed_logic logic = {
+					.length = len,
+					.unitsize = 2,
+					.data = ptr,
+				};
+			
+				struct sr_datafeed_packet packet = {
+					.type = SR_DF_LOGIC,
+					.payload = &logic
+				};
+			
+				sr_session_send(sdi, &packet);
+				g_free(ptr);
 			}
 
 			size_t bytes_to_transfer = devc->bytes_need_transfer -
@@ -93,7 +132,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 			if (bytes_to_transfer) {
 				transfer->length = bytes_to_transfer;
 				transfer->actual_length = 0;
-				transfer->timeout = devc->timeout * devc->transfers_used;
+				transfer->timeout = 1000 + devc->timeout * devc->transfers_used;
 				ret = libusb_submit_transfer(transfer);
 				if (ret) {
 					sr_warn("Failed to submit transfer: %s", libusb_error_name(ret));
@@ -155,7 +194,8 @@ static int handle_events(int fd, int revents, void *cb_data)
 			devc->transfers[i] = NULL;
 		}
 
-		usb_source_remove(sdi->session, drvc->sr_ctx);
+		// usb_source_remove(sdi->session, drvc->sr_ctx);
+		sr_session_source_remove(sdi->session, -1 * (size_t)drvc->sr_ctx->libusb_ctx);
 		std_session_send_df_end(sdi);
 	}
 
@@ -189,12 +229,23 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	// TODO
 	// if(devc->cur_samplechannel != 8) return SR_ERR_SAMPLERATE;
 
+	uint8_t cmd_rst[] = {0x02, 0x00, 0x00, 0x00};
+	ret = libusb_control_transfer(
+		usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, 1, 4,
+		0x0000, (unsigned char *)&cmd_rst, sizeof(cmd_rst), 100);
+	if (ret < 0) {
+		sr_dbg("Unable to send start command: %s", libusb_error_name(ret));
+		return SR_ERR_NA;
+	}
+	sr_dbg("CMD_RST");
+
+
 	sr_dbg("samplerate: %uHz@%uch, samples: %u",
 			devc->cur_samplerate / SR_MHZ(1), 
 			devc->cur_samplechannel, 
 			devc->limit_samples);
 
-	clear_ep(EP_IN, usb->devhdl);
+	// clear_ep(EP_IN, usb->devhdl);
 
 	devc->acq_aborted = FALSE;
   	devc->bytes_need_transfer = 0;
@@ -208,8 +259,10 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 
 	devc->timeout = get_timeout(devc);
 	sr_dbg("timeout: %ums", devc->timeout);
-	usb_source_add(sdi->session, drvc->sr_ctx, 10,
-			handle_events, (void *)sdi);
+	// usb_source_add(sdi->session, drvc->sr_ctx, 10,
+	// 		handle_events, (void *)sdi);
+
+	sr_session_source_add(sdi->session, -1 * (size_t)drvc->sr_ctx->libusb_ctx, 0, devc->timeout, handle_events, (void *)sdi);
 
 	/* compute needed bytes */
 	uint64_t samples_in_bytes = devc->limit_samples * devc->cur_samplechannel / 8;
@@ -217,7 +270,6 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	devc->bytes_need_transfer += !!(samples_in_bytes % devc->transfers_buffer_size);
 	devc->bytes_need_transfer *= devc->transfers_buffer_size;
 
-
 	while (devc->transfers_used < NUM_MAX_TRANSFERS && devc->bytes_transfered
 			+ devc->bytes_transferring < devc->bytes_need_transfer)
 	{
@@ -246,7 +298,7 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 
 		libusb_fill_bulk_transfer(transfer, usb->devhdl, EP_IN | LIBUSB_ENDPOINT_IN,
 									dev_buf, bytes_to_transfer, receive_transfer,
-									sdi, devc->timeout * (devc->transfers_used + 1));
+									sdi, 3500 + devc->timeout * (devc->transfers_used + 1));
 		transfer->actual_length = 0;
 
 		ret = libusb_submit_transfer(transfer);
@@ -272,9 +324,13 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	cmd.sample_rate = devc->cur_samplerate / SR_MHZ(1);
 	cmd.sample_channel = devc->cur_samplechannel;
 
+	// ret = libusb_control_transfer(
+	// 	usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, CMD_START, 0x0000,
+	// 	0x0000, (unsigned char *)&cmd, 3 /*sizeof(cmd)*/, 100);
+	uint8_t cmd_start[] = {0x01, 0x00, 0x00, 0x00};
 	ret = libusb_control_transfer(
-		usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, CMD_START, 0x0000,
-		0x0000, (unsigned char *)&cmd, 3 /*sizeof(cmd)*/, 100);
+		usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, 1, 4,
+		0x0000, (unsigned char *)&cmd_start, sizeof(cmd_start), 100);
 	if (ret < 0) {
 		sr_dbg("Unable to send start command: %s", libusb_error_name(ret));
 		return SR_ERR_NA;
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
index 34f793bcc..fbd6142f5 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
@@ -28,7 +28,7 @@
 
 #define LOG_PREFIX "sipeed-slogic-analyzer"
 
-#define EP_IN 0x01
+#define EP_IN 0x02
 #define SIZE_MAX_EP_HS 512
 #define NUM_MAX_TRANSFERS 64
 
@@ -42,6 +42,7 @@ static const uint64_t samplerates[] = {
 	SR_MHZ(10),
 	SR_MHZ(16),
 	SR_MHZ(20),
+	SR_MHZ(25),
 	SR_MHZ(32),
 	SR_MHZ(36),
 	SR_MHZ(40),
@@ -92,7 +93,9 @@ struct dev_context {
 
 static inline void devc_set_samplerate(struct dev_context *devc, uint64_t new_samplerate) {
 	devc->cur_samplerate = new_samplerate;
-	if (new_samplerate >= SR_MHZ(120)) {
+	if (1) {
+		devc->cur_samplechannel = 16;
+	} else if (new_samplerate >= SR_MHZ(120)) {
 		devc->cur_samplechannel = 2;
 	} else if (new_samplerate >= SR_MHZ(40)) {
 		devc->cur_samplechannel = 4;

From 53d1c217747e4ae8fc0673889df047b64dc7b3f7 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Thu, 13 Mar 2025 15:30:20 +0800
Subject: [PATCH 04/36] sipeed-slogic-analyzer: feat: use SR_CONF_BUFFERSIZE to
 configurate the channel

---
 src/hardware/sipeed-slogic-analyzer/api.c     | 151 ++++++++++++++----
 .../sipeed-slogic-analyzer/protocol.c         |  28 +---
 .../sipeed-slogic-analyzer/protocol.h         |  54 ++-----
 3 files changed, 145 insertions(+), 88 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
index ad9ac2b36..5239ca05f 100644
--- a/src/hardware/sipeed-slogic-analyzer/api.c
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -32,9 +32,66 @@ static const uint32_t devopts[] = {
 	SR_CONF_CONTINUOUS,
 	SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
 	SR_CONF_SAMPLERATE    | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
+	SR_CONF_BUFFERSIZE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
 	SR_CONF_TRIGGER_MATCH | SR_CONF_GET | SR_CONF_LIST,
 };
 
+enum {
+	SLogic_LITE_8 = 0,
+	SLogic_BASIC_16_U3,
+};
+
+static const struct slogic_model support_models[] = {
+	[SLogic_LITE_8] = {
+		.name = "Slogic Lite 8",
+		.max_samplerate = SR_MHZ(160),
+		.max_samplechannel = 8,
+		.max_bandwidth = SR_MHZ(320),
+	},
+	[SLogic_BASIC_16_U3] = {
+		.name = "Slogic Basic 16 U3",
+		.max_samplerate = SR_MHZ(1600),
+		.max_samplechannel = 16,
+		.max_bandwidth = SR_MHZ(3200),
+	},
+};
+
+static const uint64_t samplerates[] = {
+	/* 160M = 2^5*5M */
+	/* 1600M = 2^6*5^2M */
+	SR_MHZ(1),
+	SR_MHZ(2),
+	SR_MHZ(4),
+	SR_MHZ(5),
+	SR_MHZ(8),
+	SR_MHZ(10),
+	SR_MHZ(16),
+	SR_MHZ(20),
+	SR_MHZ(32),
+
+	/* Slogic Lite 8 */
+	/* x 8ch */
+	SR_MHZ(40),
+	/* x 4ch */
+	SR_MHZ(80),
+	/* x 2ch */
+	SR_MHZ(160),
+
+	/* Slogic Basic 16 U3 */
+	/* x 16ch */
+	SR_MHZ(200),
+	/* x 8ch */
+	SR_MHZ(400),
+	/* x 4ch */
+	SR_MHZ(800),
+	/* x 2ch */
+	SR_MHZ(1600),
+};
+
+static const uint64_t buffersizes[] = {
+	2, 4, 8, 16
+};
+
 static const int32_t trigger_matches[] = {
 	SR_TRIGGER_ZERO,
 	SR_TRIGGER_ONE,
@@ -61,13 +118,17 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 	char cbuf[128];
 	char *iManufacturer, *iProduct, *iSerialNumber, *iPortPath;
 
+	struct sr_channel *ch;
+	unsigned int i;
+	gchar *channel_name;
+
 	(void)options;
 
 	conn = NULL;
 
 	devices = NULL;
 	drvc = di->context;
-	drvc->instances = NULL;
+	// drvc->instances = NULL;
 	
 	/* scan for devices, either based on a SR_CONF_CONN option
 	 * or on a USB scan. */
@@ -110,13 +171,6 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 		sr_usb_close(usb);
 
 		sdi = sr_dev_inst_user_new(iManufacturer, iProduct, NULL);
-		if (!sdi) continue;
-
-		for (int i = 0; i < 16; i++) {
-			sr_snprintf_ascii(cbuf, sizeof(cbuf), "D%d", i);
-			sr_dev_inst_channel_add(sdi, i, SR_CHANNEL_LOGIC, cbuf);
-		}
-		
 		sdi->serial_num = iSerialNumber;
 		sdi->connection_id = iPortPath;
 		sdi->status = SR_ST_INACTIVE;
@@ -126,7 +180,24 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 		devc = g_malloc0(sizeof(struct dev_context));
 		sdi->priv = devc;
 
+		{
+			devc->model = &support_models[SLogic_BASIC_16_U3];
+
+			devc->limit_samplechannel = devc->model->max_samplechannel;
+			devc->limit_samplerate = devc->model->max_bandwidth / devc->model->max_samplechannel;
 
+			devc->cur_samplechannel = devc->limit_samplechannel;
+			devc->cur_samplerate = devc->limit_samplerate;
+
+			devc->digital_group = sr_channel_group_new(sdi, "LA", NULL);
+			for (i = 0; i < 16; i++) {
+				channel_name = g_strdup_printf("D%u", i);
+				ch = sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_name);
+				g_free(channel_name);
+				devc->digital_group->channels = g_slist_append(
+					devc->digital_group->channels, ch);
+			}
+		}
 
 		devices = g_slist_append(devices, sdi);
 	}
@@ -172,8 +243,6 @@ static int dev_open(struct sr_dev_inst *sdi)
 		return SR_ERR;
 	}
 
-	devc_set_samplerate(devc, samplerates[7]);
-	
 	return std_dummy_dev_open(sdi);
 }
 
@@ -204,9 +273,9 @@ static int dev_close(struct sr_dev_inst *sdi)
 			break;
 		}
 	}
-	
+
 	sr_usb_close(usb);
-	
+
 	return std_dummy_dev_close(sdi);
 }
 
@@ -225,8 +294,11 @@ static int config_get(uint32_t key, GVariant **data,
 	case SR_CONF_SAMPLERATE:
 		*data = g_variant_new_uint64(devc->cur_samplerate);
 		break;
+	case SR_CONF_BUFFERSIZE:
+		*data = g_variant_new_uint64(devc->cur_samplechannel);
+		break;
 	case SR_CONF_LIMIT_SAMPLES:
-		*data = g_variant_new_uint64(devc->limit_samples);
+		*data = g_variant_new_uint64(devc->cur_limit_samples);
 		break;
 	default:
 		return SR_ERR_NA;
@@ -248,25 +320,42 @@ static int config_set(uint32_t key, GVariant *data,
 	ret = SR_OK;
 	switch (key) {
 	case SR_CONF_SAMPLERATE:
-		if (std_u64_idx(data, ARRAY_AND_SIZE(samplerates)) < 0) {
-			ret = SR_ERR_ARG;
+		if (g_variant_get_uint64(data) > devc->limit_samplerate || std_u64_idx(data, ARRAY_AND_SIZE(samplerates)) < 0) {
+			devc->cur_samplerate = devc->limit_samplerate;
+			sr_warn("Reach limit or not supported, wrap to %uMHz.", devc->limit_samplerate/SR_MHZ(1));
 		} else {
-			devc_set_samplerate(devc, g_variant_get_uint64(data));
-			{
-			size_t idx = 0;
-				for (GSList *l = sdi->channels; l; l = l->next, idx += 1) {
-					struct sr_channel *ch = l->data;
-					if (ch->type == SR_CHANNEL_LOGIC) { /* Might as well do this now, these are static. */
-						sr_dev_channel_enable(ch, (idx >= devc->cur_samplechannel) ? FALSE : TRUE);
-					} else {
-						return SR_ERR_BUG;
-					}
+			devc->cur_samplerate = g_variant_get_uint64(data);
+		}
+		devc->limit_samplechannel = devc->model->max_bandwidth / devc->cur_samplerate;
+		if (devc->limit_samplechannel > devc->model->max_samplechannel)
+			devc->limit_samplechannel = devc->model->max_samplechannel;
+		break;
+	case SR_CONF_BUFFERSIZE:
+		if (g_variant_get_uint64(data) > devc->limit_samplechannel || std_u64_idx(data, ARRAY_AND_SIZE(buffersizes)) < 0) {
+			devc->cur_samplechannel = devc->limit_samplechannel;
+			sr_warn("Reach limit or not supported, wrap to %uch.", devc->limit_samplechannel);
+		} else {
+			devc->cur_samplechannel = g_variant_get_uint64(data);
+		}
+		devc->limit_samplerate = devc->model->max_bandwidth / devc->cur_samplechannel;
+		if (devc->limit_samplerate > devc->model->max_samplerate)
+			devc->limit_samplerate = devc->model->max_samplerate;
+
+		// [en|dis]able channels and dbg
+		{
+			for (GSList *l = devc->digital_group->channels; l; l = l->next) {
+				struct sr_channel *ch = l->data;
+				if (ch->type == SR_CHANNEL_LOGIC) { /* Might as well do this now, these are static. */
+					sr_dev_channel_enable(ch, (ch->index >= devc->cur_samplechannel) ? FALSE : TRUE);
+				} else {
+					sr_warn("devc->digital_group->channels[%u] is not Logic?", ch->index);
 				}
+				sr_dbg("\tch[%2u] %-3s:%d %sabled priv:%p.", ch->index, ch->name, ch->type, ch->enabled?"en":"dis", ch->priv);
 			}
 		}
 		break;
 	case SR_CONF_LIMIT_SAMPLES:
-		devc->limit_samples = g_variant_get_uint64(data);
+		devc->cur_limit_samples = g_variant_get_uint64(data);
 		break;
 	default:
 		ret = SR_ERR_NA;
@@ -279,6 +368,11 @@ static int config_list(uint32_t key, GVariant **data,
 	const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
 {
 	int ret;
+	struct dev_context *devc;
+
+	(void)cg;
+
+	devc = sdi ? (sdi->priv) : NULL;
 
 	ret = SR_OK;
 	switch (key) {
@@ -288,7 +382,10 @@ static int config_list(uint32_t key, GVariant **data,
 		ret = STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
 		break;
 	case SR_CONF_SAMPLERATE:
-		*data = std_gvar_samplerates(ARRAY_AND_SIZE(samplerates));
+		*data = std_gvar_samplerates(samplerates, 1+std_u64_idx(g_variant_new_uint64(devc->limit_samplerate), ARRAY_AND_SIZE(samplerates)));
+		break;
+	case SR_CONF_BUFFERSIZE:
+		*data = std_gvar_array_u64(buffersizes, 1+std_u64_idx(g_variant_new_uint64(devc->limit_samplechannel), ARRAY_AND_SIZE(buffersizes)));
 		break;
 	case SR_CONF_TRIGGER_MATCH:
 		*data = std_gvar_array_i32(ARRAY_AND_SIZE(trigger_matches));
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index 2d13a54c5..556301652 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -67,25 +67,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 				break;
 			}
 
-			if (devc->cur_samplechannel != 16) {
-				uint8_t *ptr = transfer->buffer;
-				size_t len = transfer->actual_length;
-				if (devc->cur_samplechannel != 8) {
-					size_t step = 8 / devc->cur_samplechannel;
-					uint8_t mask = 0xff >> (8 - devc->cur_samplechannel);
-					len *= step;
-					ptr = g_malloc(len);
-					for(size_t i=0; i<transfer->actual_length; i++) {
-						for(size_t j=0; j<step; j++) {
-							ptr[i*step+j] = mask & (transfer->buffer[i] >> (j * devc->cur_samplechannel));
-						}
-					}
-				}
-				submit_data(ptr, len, sdi);
-				if (devc->cur_samplechannel != 8) {
-					g_free(ptr);
-				}
-			} else {
+			{
 				// sr_dbg("samplechannel: %d, actual_length: %u", devc->cur_samplechannel, transfer->actual_length);
 				// devc->cur_samplechannel == 16
 				uint8_t * d = transfer->buffer;
@@ -95,7 +77,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 
 				uint8_t *ptr = g_malloc(len);
 
-				for(size_t i=0; i<len; i+=devc->cur_samplechannel) {
+				for(size_t i=0; i<len; i+=16) {
 					for(size_t j=0; j< 8; j++) {
 						#define B(n) (((d[i+(n)] >> 7-j) & 0x1) << ((n)%8))
 						ptr[i+j*2+0] =
@@ -111,7 +93,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 
 				struct sr_datafeed_logic logic = {
 					.length = len,
-					.unitsize = 2,
+					.unitsize = (devc->cur_samplechannel + 7)/8,
 					.data = ptr,
 				};
 			
@@ -243,7 +225,7 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	sr_dbg("samplerate: %uHz@%uch, samples: %u",
 			devc->cur_samplerate / SR_MHZ(1), 
 			devc->cur_samplechannel, 
-			devc->limit_samples);
+			devc->cur_limit_samples);
 
 	// clear_ep(EP_IN, usb->devhdl);
 
@@ -265,7 +247,7 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	sr_session_source_add(sdi->session, -1 * (size_t)drvc->sr_ctx->libusb_ctx, 0, devc->timeout, handle_events, (void *)sdi);
 
 	/* compute needed bytes */
-	uint64_t samples_in_bytes = devc->limit_samples * devc->cur_samplechannel / 8;
+	uint64_t samples_in_bytes = devc->cur_limit_samples * devc->cur_samplechannel / 8;
 	devc->bytes_need_transfer = samples_in_bytes / devc->transfers_buffer_size;
 	devc->bytes_need_transfer += !!(samples_in_bytes % devc->transfers_buffer_size);
 	devc->bytes_need_transfer *= devc->transfers_buffer_size;
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
index fbd6142f5..4017485d4 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
@@ -32,36 +32,28 @@
 #define SIZE_MAX_EP_HS 512
 #define NUM_MAX_TRANSFERS 64
 
-static const uint64_t samplerates[] = {
-	/* 160M = 2*2*2*2*2*5M */
-	SR_MHZ(1),
-	SR_MHZ(2),
-	SR_MHZ(4),
-	SR_MHZ(5),
-	SR_MHZ(8),
-	SR_MHZ(10),
-	SR_MHZ(16),
-	SR_MHZ(20),
-	SR_MHZ(25),
-	SR_MHZ(32),
-	SR_MHZ(36),
-	SR_MHZ(40),
-	/* x 4ch */
-	SR_MHZ(64),
-	SR_MHZ(80),
-	/* x 2ch */
-	SR_MHZ(120),
-	SR_MHZ(128),
-	SR_MHZ(144),
-	SR_MHZ(160),
+struct slogic_model {
+	char *name;
+	uint64_t max_samplerate; // limit by hardware
+	uint64_t max_samplechannel; // limit by hardware
+	uint64_t max_bandwidth; // limit by hardware
 };
 
 struct dev_context {
+	struct slogic_model *model;
+
+	struct sr_channel_group *digital_group;
+
+	struct {
+		uint64_t limit_samplerate;
+		uint64_t limit_samplechannel;
+	};
+
 	struct {
-		uint64_t limit_samples;
+		uint64_t cur_limit_samples;
 		uint64_t cur_samplerate;
 		uint64_t cur_samplechannel;
-	};
+	}; // var
 
 	uint64_t num_transfers;
 	struct libusb_transfer *transfers[NUM_MAX_TRANSFERS];
@@ -91,20 +83,6 @@ struct dev_context {
 	uint64_t capture_ratio;
 };
 
-static inline void devc_set_samplerate(struct dev_context *devc, uint64_t new_samplerate) {
-	devc->cur_samplerate = new_samplerate;
-	if (1) {
-		devc->cur_samplechannel = 16;
-	} else if (new_samplerate >= SR_MHZ(120)) {
-		devc->cur_samplechannel = 2;
-	} else if (new_samplerate >= SR_MHZ(40)) {
-		devc->cur_samplechannel = 4;
-	} else {
-		devc->cur_samplechannel = 8;
-	}
-	sr_info("rebind sample channel to %uCH", devc->cur_samplechannel);
-}
-
 #pragma pack(push, 1)
 struct cmd_start_acquisition {
   union {

From e45e2ed2283dd63ca223cc9d8f25cc4b0fbb4206 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Thu, 13 Mar 2025 18:49:17 +0800
Subject: [PATCH 05/36] sipeed-slogic-analyzer: feat: get the biggest
 per_transfer_nbytes

---
 src/hardware/sipeed-slogic-analyzer/api.c     |   6 +-
 .../sipeed-slogic-analyzer/protocol.c         | 111 +++++++++++-------
 .../sipeed-slogic-analyzer/protocol.h         |  73 +++++++++++-
 3 files changed, 147 insertions(+), 43 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
index 5239ca05f..d779fe690 100644
--- a/src/hardware/sipeed-slogic-analyzer/api.c
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -44,12 +44,14 @@ enum {
 static const struct slogic_model support_models[] = {
 	[SLogic_LITE_8] = {
 		.name = "Slogic Lite 8",
+		.ep_in = 0x02 | LIBUSB_ENDPOINT_IN,
 		.max_samplerate = SR_MHZ(160),
 		.max_samplechannel = 8,
 		.max_bandwidth = SR_MHZ(320),
 	},
 	[SLogic_BASIC_16_U3] = {
 		.name = "Slogic Basic 16 U3",
+		.ep_in = 0x02 | LIBUSB_ENDPOINT_IN,
 		.max_samplerate = SR_MHZ(1600),
 		.max_samplechannel = 16,
 		.max_bandwidth = SR_MHZ(3200),
@@ -168,7 +170,6 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 		usb_get_port_path(libusb_get_device(usb->devhdl),
 				cbuf, sizeof(cbuf));
 		iPortPath = g_strdup(cbuf);
-		sr_usb_close(usb);
 
 		sdi = sr_dev_inst_user_new(iManufacturer, iProduct, NULL);
 		sdi->serial_num = iSerialNumber;
@@ -197,8 +198,11 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 				devc->digital_group->channels = g_slist_append(
 					devc->digital_group->channels, ch);
 			}
+
+			devc->speed = libusb_get_device_speed(libusb_get_device(usb->devhdl));
 		}
 
+		sr_usb_close(usb);
 		devices = g_slist_append(devices, sdi);
 	}
 	// g_slist_free_full(conn_devices, (GDestroyNotify)sr_usb_dev_inst_free);
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index 556301652..441135aa4 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -45,10 +45,12 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 	struct sr_usb_dev_inst *usb;
 
 	sdi  = transfer->user_data;
+	if (!sdi)
+		return;
 	devc = sdi->priv;
 	usb  = sdi->conn;
 
-	sr_dbg("[%p]usb status: %d", transfer, transfer->status);
+	sr_spew("[%p]usb status: %d", transfer, transfer->status);
 	switch (transfer->status) {
 		case LIBUSB_TRANSFER_COMPLETED: 
 		case LIBUSB_TRANSFER_TIMED_OUT: { /* may have received some data */
@@ -163,7 +165,7 @@ static int handle_events(int fd, int revents, void *cb_data)
 	di = sdi->driver;
 	drvc = di->context;
 
-	sr_dbg("handle_events enter");
+	sr_spew("handle_events enter");
 
 	if (devc->acq_aborted == TRUE) {
 		for (size_t i = 0; i < NUM_MAX_TRANSFERS; ++i) {
@@ -199,7 +201,6 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	struct drv_context *drvc;
 	struct sr_usb_dev_inst *usb;
 
-	struct cmd_start_acquisition cmd;
 	int ret;
 	size_t size_transfer_buf;
 
@@ -208,26 +209,70 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	drvc = di->context;
 	usb  = sdi->conn;
 
-	// TODO
-	// if(devc->cur_samplechannel != 8) return SR_ERR_SAMPLERATE;
-
 	uint8_t cmd_rst[] = {0x02, 0x00, 0x00, 0x00};
-	ret = libusb_control_transfer(
-		usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, 1, 4,
-		0x0000, (unsigned char *)&cmd_rst, sizeof(cmd_rst), 100);
+	ret = slogic_basic_16_u3_reg_write(sdi, 0x0004, ARRAY_AND_SIZE(cmd_rst));
 	if (ret < 0) {
-		sr_dbg("Unable to send start command: %s", libusb_error_name(ret));
-		return SR_ERR_NA;
+		sr_err("Unhandled `CMD_RST`");
+		return ret;
 	}
-	sr_dbg("CMD_RST");
-
+	// clear_ep(EP_IN, usb->devhdl);
 
-	sr_dbg("samplerate: %uHz@%uch, samples: %u",
-			devc->cur_samplerate / SR_MHZ(1), 
+	sr_info("Need %ux %uch@%uMHz in %ums.", 
+			devc->cur_limit_samples,
 			devc->cur_samplechannel, 
-			devc->cur_limit_samples);
+			devc->cur_samplerate / SR_MHZ(1),
+			1000 * devc->cur_limit_samples / devc->cur_samplerate
+	);
+
+	devc->per_transfer_duration = 500;
+	devc->per_transfer_nbytes = devc->cur_samplerate / SR_KHZ(1) * devc->cur_samplechannel / 8 * devc->per_transfer_duration /* ms */;
+	devc->per_transfer_nbytes = (devc->per_transfer_nbytes + 1023) & ~1023;
+
+	do {
+		struct libusb_transfer *transfer = libusb_alloc_transfer(0);
+		if (!transfer) {
+			sr_err("Failed to allocate libusb transfer!");
+			return SR_ERR_IO;
+		}
+		while (devc->per_transfer_nbytes > 128*1024) { // 128kiB > 500ms * 1MHZ * 2ch
+			devc->per_transfer_duration = devc->per_transfer_nbytes / (devc->cur_samplerate / SR_KHZ(1) * devc->cur_samplechannel / 8);
+			sr_dbg("Plan to receive %u bytes per %ums...", devc->per_transfer_nbytes, devc->per_transfer_duration);
+			
+			uint8_t *dev_buf = g_malloc(devc->per_transfer_nbytes);
+			if (!dev_buf) {
+				sr_warn("Failed to allocate memory: %u bytes!", devc->per_transfer_nbytes);
+				devc->per_transfer_nbytes >>= 1;
+				continue;
+			}
+
+			libusb_fill_bulk_transfer(transfer, usb->devhdl, devc->model->ep_in,
+										dev_buf, devc->per_transfer_nbytes, receive_transfer,
+										NULL, devc->per_transfer_duration);
+
+			ret = libusb_submit_transfer(transfer);
+			libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &(struct timeval){0, 0});
+			if (ret) {
+				sr_warn("Failed to submit transfer: %s!", libusb_error_name(ret));
+				g_free(transfer->buffer);
+				if (ret == LIBUSB_ERROR_NO_MEM)
+					devc->per_transfer_nbytes >>= 1;
+				else
+					return SR_ERR_IO;
+				continue;
+			} else {
+				ret = libusb_cancel_transfer(transfer);
+				libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &(struct timeval){0, 0});
+				g_free(transfer->buffer);
+				break;
+			}
+		}
+		libusb_free_transfer(transfer);
+		if (devc->per_transfer_nbytes < 128*1024) {
+			return SR_ERR_MALLOC;
+		}
+		sr_dbg("Nice plan! :)");
+	} while (0);
 
-	// clear_ep(EP_IN, usb->devhdl);
 
 	devc->acq_aborted = FALSE;
   	devc->bytes_need_transfer = 0;
@@ -257,18 +302,14 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	{
 		uint8_t *dev_buf = g_malloc(devc->transfers_buffer_size);
 		if (!dev_buf) {
-			sr_dbg("Failed to allocate memory");
-			sr_dev_acquisition_stop(sdi);
-			return SR_ERR_MALLOC;
+			sr_warn("Failed to allocate memory");
 			break;
 		}
 
 		struct libusb_transfer *transfer = libusb_alloc_transfer(0);
 		if (!transfer) {
 			g_free(dev_buf);
-			sr_dbg("Failed to allocate transfer");
-			sr_dev_acquisition_stop(sdi);
-			return SR_ERR_MALLOC;
+			sr_warn("Failed to allocate transfer");
 			break;
 		}
 
@@ -285,11 +326,9 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 
 		ret = libusb_submit_transfer(transfer);
 		if (ret) {
-			sr_dbg("Failed to submit transfer: %s.", libusb_error_name(ret));
+			sr_warn("Failed to submit transfer[%d]: %s.", devc->transfers_used, libusb_error_name(ret));
 			g_free(transfer->buffer);
 			libusb_free_transfer(transfer);
-			sr_dev_acquisition_stop(sdi);
-			return SR_ERR_IO;
 			break;
 		}
 		devc->transfers[devc->transfers_used] = transfer;
@@ -299,25 +338,15 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	}
 	sr_dbg("Submited %u transfers", devc->transfers_used);
 
-	std_session_send_df_frame_begin(sdi);
 	std_session_send_df_header(sdi);
+	std_session_send_df_frame_begin(sdi);
 
-
-	cmd.sample_rate = devc->cur_samplerate / SR_MHZ(1);
-	cmd.sample_channel = devc->cur_samplechannel;
-
-	// ret = libusb_control_transfer(
-	// 	usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, CMD_START, 0x0000,
-	// 	0x0000, (unsigned char *)&cmd, 3 /*sizeof(cmd)*/, 100);
-	uint8_t cmd_start[] = {0x01, 0x00, 0x00, 0x00};
-	ret = libusb_control_transfer(
-		usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, 1, 4,
-		0x0000, (unsigned char *)&cmd_start, sizeof(cmd_start), 100);
+	uint8_t cmd_run[] = {0x01, 0x00, 0x00, 0x00};
+	ret = slogic_basic_16_u3_reg_write(sdi, 0x0004, ARRAY_AND_SIZE(cmd_run));
 	if (ret < 0) {
-		sr_dbg("Unable to send start command: %s", libusb_error_name(ret));
-		return SR_ERR_NA;
+		sr_err("Unhandled `CMD_RUN`");
+		return ret;
 	}
-	sr_dbg("CMD_STARTED");
 
 	return SR_OK;
 }
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
index 4017485d4..5d3429701 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
@@ -34,6 +34,7 @@
 
 struct slogic_model {
 	char *name;
+	uint8_t ep_in;
 	uint64_t max_samplerate; // limit by hardware
 	uint64_t max_samplechannel; // limit by hardware
 	uint64_t max_bandwidth; // limit by hardware
@@ -53,7 +54,17 @@ struct dev_context {
 		uint64_t cur_limit_samples;
 		uint64_t cur_samplerate;
 		uint64_t cur_samplechannel;
-	}; // var
+	}; // configuration
+
+	struct {
+		enum libusb_speed speed;
+
+		uint64_t samples_need_nbytes;
+		uint64_t samples_got_nbytes;
+
+		uint64_t per_transfer_duration; /* unit: ms */
+		uint64_t per_transfer_nbytes;
+	}; // usb
 
 	uint64_t num_transfers;
 	struct libusb_transfer *transfers[NUM_MAX_TRANSFERS];
@@ -154,4 +165,64 @@ static inline void clear_ep(uint8_t ep, libusb_device_handle *usbh) {
 	sr_dbg("Cleared EP: %u", ep);
 }
 
+#define CONTROL_IN_REQ_REG_READ 	0x00
+#define CONTROL_OUT_REQ_REG_WRITE 	0x01
+
+static inline int slogic_basic_16_u3_reg_write(const struct sr_dev_inst *sdi, uint16_t value, uint8_t *data, size_t len)
+{
+	int ret;
+	struct dev_context *devc;
+	struct sr_usb_dev_inst *usb;
+
+	devc = sdi->priv;
+	usb  = sdi->conn;
+
+	sr_spew("%s %u %p:%u.", __func__, value, data, len);
+	if (!data || !len) {
+		sr_err("%s failed(Nothing to write)!", __func__);
+		return SR_ERR_ARG;
+	}
+
+	if ((ret = libusb_control_transfer(
+		usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT,
+		CONTROL_OUT_REQ_REG_WRITE,
+		value, 0x0000,
+		(unsigned char *)data, len,
+		500
+	)) < 0) {
+		sr_err("%s failed(libusb: %s)!", __func__, libusb_error_name(ret));
+		return SR_ERR_NA;
+	}
+	return ret;
+}
+
+
+static inline int slogic_basic_16_u3_reg_read(const struct sr_dev_inst *sdi, uint16_t value, uint8_t *data, size_t len)
+{
+	int ret;
+	struct dev_context *devc;
+	struct sr_usb_dev_inst *usb;
+
+	devc = sdi->priv;
+	usb  = sdi->conn;
+
+	sr_spew("%s %u %p:%u.", __func__, value, data, len);
+	if (!data || !len) {
+		sr_err("%s failed(Nothing to read)!", __func__);
+		return SR_ERR_ARG;
+	}
+
+	if ((ret = libusb_control_transfer(
+		usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN,
+		CONTROL_IN_REQ_REG_READ,
+		value, 0x0000,
+		(unsigned char *)data, len,
+		500
+	)) < 0) {
+		sr_err("%s failed(libusb: %s)!", __func__, libusb_error_name(ret));
+		return SR_ERR_NA;
+	}
+	return ret;
+}
+
 #endif

From ff46931b33ac3025ec2c8d90f4e9ad49ef7f0c7d Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Thu, 13 Mar 2025 19:35:43 +0800
Subject: [PATCH 06/36] sipeed-slogic-analyzer: fix: align up to N*1024

---
 .../sipeed-slogic-analyzer/protocol.c         | 20 +++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index 441135aa4..e08ccf342 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -234,13 +234,14 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 			sr_err("Failed to allocate libusb transfer!");
 			return SR_ERR_IO;
 		}
-		while (devc->per_transfer_nbytes > 128*1024) { // 128kiB > 500ms * 1MHZ * 2ch
+		do {
+			devc->per_transfer_nbytes = (devc->per_transfer_nbytes + 1023) & ~1023;
 			devc->per_transfer_duration = devc->per_transfer_nbytes / (devc->cur_samplerate / SR_KHZ(1) * devc->cur_samplechannel / 8);
 			sr_dbg("Plan to receive %u bytes per %ums...", devc->per_transfer_nbytes, devc->per_transfer_duration);
 			
 			uint8_t *dev_buf = g_malloc(devc->per_transfer_nbytes);
 			if (!dev_buf) {
-				sr_warn("Failed to allocate memory: %u bytes!", devc->per_transfer_nbytes);
+				sr_dbg("Failed to allocate memory: %u bytes! Half .", devc->per_transfer_nbytes);
 				devc->per_transfer_nbytes >>= 1;
 				continue;
 			}
@@ -252,24 +253,23 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 			ret = libusb_submit_transfer(transfer);
 			libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &(struct timeval){0, 0});
 			if (ret) {
-				sr_warn("Failed to submit transfer: %s!", libusb_error_name(ret));
 				g_free(transfer->buffer);
-				if (ret == LIBUSB_ERROR_NO_MEM)
+				if (ret == LIBUSB_ERROR_NO_MEM) {
+					sr_dbg("Failed to submit transfer: %s!", libusb_error_name(ret));
 					devc->per_transfer_nbytes >>= 1;
-				else
+					continue;
+				} else {
+					sr_err("Failed to submit transfer: %s!", libusb_error_name(ret));
 					return SR_ERR_IO;
-				continue;
+				}
 			} else {
 				ret = libusb_cancel_transfer(transfer);
 				libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &(struct timeval){0, 0});
 				g_free(transfer->buffer);
 				break;
 			}
-		}
+		} while (devc->per_transfer_nbytes > 128*1024); // 128kiB > 500ms * 1MHZ * 2ch
 		libusb_free_transfer(transfer);
-		if (devc->per_transfer_nbytes < 128*1024) {
-			return SR_ERR_MALLOC;
-		}
 		sr_dbg("Nice plan! :)");
 	} while (0);
 

From 0dbc67da507356810dac8d64463554817844ce61 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Thu, 13 Mar 2025 21:02:24 +0800
Subject: [PATCH 07/36] sipeed-slogic-analyzer: refactor: trim `struct
 dev_context` and use samples_xxx_nbytes, per_transfer_xxx and
 num_transfers_xxx

---
 .../sipeed-slogic-analyzer/protocol.c         | 139 ++++++------------
 .../sipeed-slogic-analyzer/protocol.h         |  68 +--------
 2 files changed, 49 insertions(+), 158 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index e08ccf342..088210f33 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -22,10 +22,10 @@
 
 static int handle_events(int fd, int revents, void *cb_data);
 
-static void submit_data(void *data, size_t len, struct sr_dev_inst *sdi) {
+static void submit_data(void *data, size_t len, const struct sr_dev_inst *sdi) {
 	struct sr_datafeed_logic logic = {
 		.length = len,
-		.unitsize = 1,
+		.unitsize = (((struct dev_context *)(sdi->priv))->cur_samplechannel + 7)/8,
 		.data = data,
 	};
 
@@ -54,24 +54,17 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 	switch (transfer->status) {
 		case LIBUSB_TRANSFER_COMPLETED: 
 		case LIBUSB_TRANSFER_TIMED_OUT: { /* may have received some data */
-			sr_dbg("\ttransfing: %u - %u, done: %u + %u, remain: %u/%u",
-				devc->bytes_transferring, transfer->length,
-				devc->bytes_transfered, transfer->actual_length,
-				devc->bytes_need_transfer + (transfer->length - transfer->actual_length) - (devc->bytes_transfered + devc->bytes_transferring),
-				devc->bytes_need_transfer
-			);
-
-			devc->bytes_transfered += transfer->actual_length;
-			devc->bytes_transferring -= transfer->length;
+			if (transfer->actual_length > devc->samples_need_nbytes - devc->samples_got_nbytes)
+				transfer->actual_length = devc->samples_need_nbytes - devc->samples_got_nbytes;
+			devc->samples_got_nbytes += transfer->actual_length;
+			sr_dbg("[%u] got: %u/%u (%.2f%)", devc->num_transfers_completed, devc->samples_got_nbytes, devc->samples_need_nbytes, 100.f * devc->samples_got_nbytes / devc->samples_need_nbytes);
 
 			if (transfer->actual_length == 0) {
-				devc->transfers_used -= 1;
+				devc->num_transfers_used -= 1;
 				break;
 			}
 
 			{
-				// sr_dbg("samplechannel: %d, actual_length: %u", devc->cur_samplechannel, transfer->actual_length);
-				// devc->cur_samplechannel == 16
 				uint8_t * d = transfer->buffer;
 				size_t len = transfer->actual_length;
 				// sr_dbg("HEAD: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
@@ -87,63 +80,44 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 						ptr[i+j*2+1] =
 							B(8)|B(9)|B(10)|B(11)|B(12)|B(13)|B(14)|B(15);
 						#undef B
-
-						// ptr[i+j*2+0] |= 0x1;
-						// ptr[i+j*2+1] |= 0x80;
 					}
 				}
 
-				struct sr_datafeed_logic logic = {
-					.length = len,
-					.unitsize = (devc->cur_samplechannel + 7)/8,
-					.data = ptr,
-				};
-			
-				struct sr_datafeed_packet packet = {
-					.type = SR_DF_LOGIC,
-					.payload = &logic
-				};
-			
-				sr_session_send(sdi, &packet);
+				submit_data(ptr, len, sdi);
+
 				g_free(ptr);
 			}
 
-			size_t bytes_to_transfer = devc->bytes_need_transfer -
-				(devc->bytes_transfered + devc->bytes_transferring);
-			if (bytes_to_transfer > devc->transfers_buffer_size) {
-				bytes_to_transfer = devc->transfers_buffer_size;
-			}
-			if (bytes_to_transfer) {
-				transfer->length = bytes_to_transfer;
+			if (devc->samples_got_nbytes < devc->samples_need_nbytes) {
+				// transfer->length = bytes_to_transfer;
 				transfer->actual_length = 0;
-				transfer->timeout = 1000 + devc->timeout * devc->transfers_used;
 				ret = libusb_submit_transfer(transfer);
 				if (ret) {
 					sr_warn("Failed to submit transfer: %s", libusb_error_name(ret));
-					devc->transfers_used -= 1;
+					devc->num_transfers_used -= 1;
+				} else {
+					sr_dbg("submit transfer: %p", transfer);
 				}
-				sr_dbg("submit transfer: %p", transfer);
-
-				devc->bytes_transferring += bytes_to_transfer;
 			} else {
-				devc->transfers_used -= 1;
+				devc->num_transfers_used -= 1;
 			}
 		} break;
 
 		case LIBUSB_TRANSFER_NO_DEVICE: {
-			devc->transfers_used = 0;
+			devc->num_transfers_used = 0;
 		} break;
 
 		default: {
-			devc->transfers_used -= 1;
+			devc->num_transfers_used -= 1;
 		} break;
 	}
 
-	if (devc->transfers_used == 0) {
+	devc->num_transfers_completed += 1;
+
+	if (devc->num_transfers_used == 0) {
 		sr_dbg("free all transfers");
 
-		sr_dbg("Bulk in %u/%u bytes", devc->bytes_transfered,
-				devc->bytes_need_transfer);
+		sr_dbg("Bulk in %u/%u bytes", devc->samples_got_nbytes, devc->samples_need_nbytes);
 		
 		sr_dev_acquisition_stop(sdi);
 	}
@@ -155,7 +129,6 @@ static int handle_events(int fd, int revents, void *cb_data)
 	struct sr_dev_driver *di;
 	struct dev_context *devc;
 	struct drv_context *drvc;
-	struct timeval tv;
 
 	(void)fd;
 	(void)revents;
@@ -167,7 +140,7 @@ static int handle_events(int fd, int revents, void *cb_data)
 
 	sr_spew("handle_events enter");
 
-	if (devc->acq_aborted == TRUE) {
+	if (devc->acq_aborted) {
 		for (size_t i = 0; i < NUM_MAX_TRANSFERS; ++i) {
 			struct libusb_transfer *transfer = devc->transfers[i];
 			if (transfer) {
@@ -178,21 +151,17 @@ static int handle_events(int fd, int revents, void *cb_data)
 			devc->transfers[i] = NULL;
 		}
 
-		// usb_source_remove(sdi->session, drvc->sr_ctx);
 		sr_session_source_remove(sdi->session, -1 * (size_t)drvc->sr_ctx->libusb_ctx);
 		std_session_send_df_end(sdi);
 	}
 
-	memset(&tv, 0, sizeof(struct timeval));
-	libusb_handle_events_timeout_completed(drvc->sr_ctx->libusb_ctx, &tv,
-			&devc->acq_aborted);
+	libusb_handle_events_timeout_completed(drvc->sr_ctx->libusb_ctx, &(struct timeval){0, 0}, &devc->acq_aborted);
 
 	return TRUE;
 }
 
 SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 {
-	// sr_dbg("Enter func %s", __func__);
 	/* TODO: configure hardware, reset acquisition state, set up
 	 * callbacks and send header packet. */
 
@@ -202,7 +171,6 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	struct sr_usb_dev_inst *usb;
 
 	int ret;
-	size_t size_transfer_buf;
 
 	devc = sdi->priv;
 	di = sdi->driver;
@@ -217,6 +185,8 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	}
 	// clear_ep(EP_IN, usb->devhdl);
 
+	devc->samples_got_nbytes = 0;
+	devc->samples_need_nbytes = devc->cur_limit_samples * devc->cur_samplechannel / 8;
 	sr_info("Need %ux %uch@%uMHz in %ums.", 
 			devc->cur_limit_samples,
 			devc->cur_samplechannel, 
@@ -247,7 +217,7 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 			}
 
 			libusb_fill_bulk_transfer(transfer, usb->devhdl, devc->model->ep_in,
-										dev_buf, devc->per_transfer_nbytes, receive_transfer,
+										dev_buf, devc->per_transfer_nbytes, NULL,
 										NULL, devc->per_transfer_duration);
 
 			ret = libusb_submit_transfer(transfer);
@@ -270,73 +240,48 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 			}
 		} while (devc->per_transfer_nbytes > 128*1024); // 128kiB > 500ms * 1MHZ * 2ch
 		libusb_free_transfer(transfer);
-		sr_dbg("Nice plan! :)");
+		sr_info("Nice plan! :) => %u bytes per %ums.", devc->per_transfer_nbytes, devc->per_transfer_duration);
 	} while (0);
 
 
-	devc->acq_aborted = FALSE;
-  	devc->bytes_need_transfer = 0;
-	devc->bytes_transferring = 0;
-	devc->bytes_transfered = 0;
-	devc->transfers_used = 0;
+	devc->acq_aborted = 0;
+	devc->num_transfers_used = 0;
+	devc->num_transfers_completed = 0;
 	memset(devc->transfers, 0, sizeof(devc->transfers));
 
-	devc->transfers_buffer_size = get_buffer_size(devc);
-	sr_dbg("transfers_buffer_size: %u", devc->transfers_buffer_size);
-
-	devc->timeout = get_timeout(devc);
-	sr_dbg("timeout: %ums", devc->timeout);
-	// usb_source_add(sdi->session, drvc->sr_ctx, 10,
-	// 		handle_events, (void *)sdi);
-
-	sr_session_source_add(sdi->session, -1 * (size_t)drvc->sr_ctx->libusb_ctx, 0, devc->timeout, handle_events, (void *)sdi);
-
-	/* compute needed bytes */
-	uint64_t samples_in_bytes = devc->cur_limit_samples * devc->cur_samplechannel / 8;
-	devc->bytes_need_transfer = samples_in_bytes / devc->transfers_buffer_size;
-	devc->bytes_need_transfer += !!(samples_in_bytes % devc->transfers_buffer_size);
-	devc->bytes_need_transfer *= devc->transfers_buffer_size;
+	sr_session_source_add(sdi->session, -1 * (size_t)drvc->sr_ctx->libusb_ctx, 0, devc->per_transfer_duration / 2, handle_events, (void *)sdi);
 
-	while (devc->transfers_used < NUM_MAX_TRANSFERS && devc->bytes_transfered
-			+ devc->bytes_transferring < devc->bytes_need_transfer)
+	while (devc->num_transfers_used < NUM_MAX_TRANSFERS)
 	{
-		uint8_t *dev_buf = g_malloc(devc->transfers_buffer_size);
+		uint8_t *dev_buf = g_malloc(devc->per_transfer_nbytes);
 		if (!dev_buf) {
-			sr_warn("Failed to allocate memory");
+			sr_warn("Failed to allocate memory[%d]", devc->num_transfers_used);
 			break;
 		}
 
 		struct libusb_transfer *transfer = libusb_alloc_transfer(0);
 		if (!transfer) {
+			sr_warn("Failed to allocate transfer[%d]", devc->num_transfers_used);
 			g_free(dev_buf);
-			sr_warn("Failed to allocate transfer");
 			break;
 		}
 
-		size_t bytes_to_transfer = devc->bytes_need_transfer -
-			devc->bytes_transfered - devc->bytes_transferring;
-		if (bytes_to_transfer > devc->transfers_buffer_size) {
-			bytes_to_transfer = devc->transfers_buffer_size;
-		}
-
 		libusb_fill_bulk_transfer(transfer, usb->devhdl, EP_IN | LIBUSB_ENDPOINT_IN,
-									dev_buf, bytes_to_transfer, receive_transfer,
-									sdi, 3500 + devc->timeout * (devc->transfers_used + 1));
+									dev_buf, devc->per_transfer_nbytes, receive_transfer,
+									sdi, devc->per_transfer_duration);
 		transfer->actual_length = 0;
 
 		ret = libusb_submit_transfer(transfer);
 		if (ret) {
-			sr_warn("Failed to submit transfer[%d]: %s.", devc->transfers_used, libusb_error_name(ret));
+			sr_warn("Failed to submit transfer[%d]: %s.", devc->num_transfers_used, libusb_error_name(ret));
 			g_free(transfer->buffer);
 			libusb_free_transfer(transfer);
 			break;
 		}
-		devc->transfers[devc->transfers_used] = transfer;
-
-		devc->bytes_transferring += bytes_to_transfer;
-		devc->transfers_used += 1;
+		devc->transfers[devc->num_transfers_used] = transfer;
+		devc->num_transfers_used += 1;
 	}
-	sr_dbg("Submited %u transfers", devc->transfers_used);
+	sr_dbg("Submited %u transfers", devc->num_transfers_used);
 
 	std_session_send_df_header(sdi);
 	std_session_send_df_frame_begin(sdi);
@@ -358,7 +303,7 @@ SR_PRIV int sipeed_slogic_acquisition_stop(struct sr_dev_inst *sdi)
 
 	devc = sdi->priv;
 
-	devc->acq_aborted = TRUE;
+	devc->acq_aborted = 1;
 
 	return SR_OK;
 }
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
index 5d3429701..c9c9a34fe 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
@@ -64,34 +64,20 @@ struct dev_context {
 
 		uint64_t per_transfer_duration; /* unit: ms */
 		uint64_t per_transfer_nbytes;
-	}; // usb
-
-	uint64_t num_transfers;
-	struct libusb_transfer *transfers[NUM_MAX_TRANSFERS];
-
-	gboolean acq_aborted;
 
-	uint64_t timeout;
-
-	size_t transfers_buffer_size;
+		size_t num_transfers_completed;
+		size_t num_transfers_used;
+		struct libusb_transfer *transfers[NUM_MAX_TRANSFERS];
+	}; // usb
 
-	size_t bytes_need_transfer;
-	size_t bytes_transferring;
-	size_t bytes_transfered;
-	size_t transfers_used;
+	int acq_aborted;
 
+	/* Triggers */
+	uint64_t capture_ratio;
 	gboolean trigger_fired;
 	struct soft_trigger_logic *stl;
 
-	uint64_t num_frames;
-	uint64_t sent_samples;
-	int submitted_transfers;
-	int empty_transfer_count;
-
-
 	double voltage_threshold[2];
-	/* Triggers */
-	uint64_t capture_ratio;
 };
 
 #pragma pack(push, 1)
@@ -114,46 +100,6 @@ struct cmd_start_acquisition {
 SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi);
 SR_PRIV int sipeed_slogic_acquisition_stop(struct sr_dev_inst *sdi);
 
-static inline size_t to_bytes_per_ms(struct dev_context *devc)
-{
-	return (devc->cur_samplerate * devc->cur_samplechannel) / 8 / 1000;
-}
-
-static inline size_t get_buffer_size(struct dev_context *devc)
-{
-	/**
-	 * The buffer should be large enough to hold 10ms of data and
-	 * a multiple of 210 * 512.
-	 */
-	// const size_t pack_size = SIZE_MAX_EP_HS;
-	// size_t s = 10 * to_bytes_per_ms(devc);
-	// size_t rem = s % (210 * pack_size);
-	// if (rem) s += 210 * pack_size - rem;
-	// return s;
-	return 210 * SIZE_MAX_EP_HS;
-}
-
-static inline size_t get_number_of_transfers(struct dev_context *devc)
-{
-	/* Total buffer size should be able to hold about 500ms of data. */
-	// size_t s = 500 * to_bytes_per_ms(devc);
-	// size_t n = s / get_buffer_size(devc);
-	// size_t rem = s % get_buffer_size(devc);
-	// if (rem) n += 1;
-	// if (n > NUM_MAX_TRANSFERS)
-	// 	return NUM_MAX_TRANSFERS;
-	// return n;
-	return 1;
-}
-
-static inline size_t get_timeout(struct dev_context *devc)
-{
-	size_t total_size = get_buffer_size(devc) *
-			get_number_of_transfers(devc);
-	size_t timeout = total_size / to_bytes_per_ms(devc);
-	return timeout * 5 / 4; /* Leave a headroom of 25% percent. */
-}
-
 static inline void clear_ep(uint8_t ep, libusb_device_handle *usbh) {
 	sr_dbg("Clearring EP: %u", ep);
 	uint8_t tmp[512];

From bac09591fc6ddda6b476d08a6a6cb4f4f081a934 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Fri, 14 Mar 2025 15:25:15 +0800
Subject: [PATCH 08/36] sipeed-slogic-analyzer: feat: at least 2 transfers are
 pending in parallel, and evaluate transfer latency, also fix cancel_transfer
 must be handled

---
 .../sipeed-slogic-analyzer/protocol.c         | 73 ++++++++++++++-----
 .../sipeed-slogic-analyzer/protocol.h         |  8 +-
 2 files changed, 59 insertions(+), 22 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index 088210f33..a0561007a 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -50,21 +50,38 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 	devc = sdi->priv;
 	usb  = sdi->conn;
 
-	sr_spew("[%p]usb status: %d", transfer, transfer->status);
+	int64_t transfers_reached_time_now = g_get_monotonic_time();
+	int64_t transfers_reached_duration = transfers_reached_time_now - devc->transfers_reached_time_latest;
+
+	if (devc->acq_aborted == 1)
+		return;
+
+	sr_spew("Transfer[%d] status: %d(%s)", std_u64_idx(g_variant_new_uint64((uint64_t)transfer), (uint64_t*)devc->transfers, devc->num_transfers_used),
+		transfer->status, libusb_error_name(transfer->status));
 	switch (transfer->status) {
 		case LIBUSB_TRANSFER_COMPLETED: 
 		case LIBUSB_TRANSFER_TIMED_OUT: { /* may have received some data */
+			devc->transfers_reached_nbytes_latest = transfer->actual_length;
+			devc->transfers_reached_nbytes += devc->transfers_reached_nbytes_latest;
 			if (transfer->actual_length > devc->samples_need_nbytes - devc->samples_got_nbytes)
 				transfer->actual_length = devc->samples_need_nbytes - devc->samples_got_nbytes;
 			devc->samples_got_nbytes += transfer->actual_length;
-			sr_dbg("[%u] got: %u/%u (%.2f%)", devc->num_transfers_completed, devc->samples_got_nbytes, devc->samples_need_nbytes, 100.f * devc->samples_got_nbytes / devc->samples_need_nbytes);
+			sr_dbg("[%u] Got(%.2f%): %u/%u => speed: %.2fMBps, %.2fMBps(avg) => +%.3f=%.3fms.",
+				devc->num_transfers_completed,
+				100.f * devc->samples_got_nbytes / devc->samples_need_nbytes, devc->samples_got_nbytes, devc->samples_need_nbytes,
+				(double)devc->transfers_reached_nbytes_latest / transfers_reached_duration,
+				(double)devc->transfers_reached_nbytes / (transfers_reached_time_now - devc->transfers_reached_time_start),
+				(double)transfers_reached_duration / SR_KHZ(1),
+				(double)(transfers_reached_time_now - devc->transfers_reached_time_start) / SR_KHZ(1)
+			);
+			devc->transfers_reached_time_latest = transfers_reached_time_now;
 
 			if (transfer->actual_length == 0) {
 				devc->num_transfers_used -= 1;
 				break;
 			}
 
-			{
+			if (1) {
 				uint8_t * d = transfer->buffer;
 				size_t len = transfer->actual_length;
 				// sr_dbg("HEAD: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
@@ -89,20 +106,22 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 			}
 
 			if (devc->samples_got_nbytes < devc->samples_need_nbytes) {
-				// transfer->length = bytes_to_transfer;
 				transfer->actual_length = 0;
+				transfer->timeout = (TRANSFERS_DURATION_TOLERANCE + 1) * devc->per_transfer_duration * (devc->num_transfers_used + 1);
 				ret = libusb_submit_transfer(transfer);
 				if (ret) {
 					sr_warn("Failed to submit transfer: %s", libusb_error_name(ret));
 					devc->num_transfers_used -= 1;
 				} else {
-					sr_dbg("submit transfer: %p", transfer);
+					sr_spew("Resubmit transfer: %p", transfer);
 				}
 			} else {
-				devc->num_transfers_used -= 1;
+				devc->num_transfers_used = 0;
 			}
 		} break;
 
+		case LIBUSB_TRANSFER_OVERFLOW:
+		case LIBUSB_TRANSFER_STALL:
 		case LIBUSB_TRANSFER_NO_DEVICE: {
 			devc->num_transfers_used = 0;
 		} break;
@@ -112,15 +131,19 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 		} break;
 	}
 
-	devc->num_transfers_completed += 1;
+	if (devc->num_transfers_completed && (double)transfers_reached_duration / SR_KHZ(1) > (TRANSFERS_DURATION_TOLERANCE + 1) * devc->per_transfer_duration) {
+		sr_err("Timeout %.3fms!!! Reach duration limit: %.3f(%u+%.1f%) except first one.",
+			(double)transfers_reached_duration / SR_KHZ(1),
+			(TRANSFERS_DURATION_TOLERANCE + 1) * devc->per_transfer_duration, devc->per_transfer_duration, TRANSFERS_DURATION_TOLERANCE * 100
+		);
+		devc->num_transfers_used = 0;
+	}
 
 	if (devc->num_transfers_used == 0) {
-		sr_dbg("free all transfers");
-
-		sr_dbg("Bulk in %u/%u bytes", devc->samples_got_nbytes, devc->samples_need_nbytes);
-		
-		sr_dev_acquisition_stop(sdi);
+		sipeed_slogic_acquisition_stop(sdi);
 	}
+
+	devc->num_transfers_completed += 1;
 };
 
 static int handle_events(int fd, int revents, void *cb_data)
@@ -138,19 +161,23 @@ static int handle_events(int fd, int revents, void *cb_data)
 	di = sdi->driver;
 	drvc = di->context;
 
-	sr_spew("handle_events enter");
+	//sr_spew("handle_events enter");
 
 	if (devc->acq_aborted) {
 		for (size_t i = 0; i < NUM_MAX_TRANSFERS; ++i) {
 			struct libusb_transfer *transfer = devc->transfers[i];
 			if (transfer) {
 				libusb_cancel_transfer(transfer);
+				libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &(struct timeval){0, 0});
 				g_free(transfer->buffer);
 				libusb_free_transfer(transfer);
 			}
 			devc->transfers[i] = NULL;
 		}
 
+		sr_dbg("Freed all transfers.");
+		sr_info("Bulk in %u/%u bytes with %u transfers.", devc->samples_got_nbytes, devc->samples_need_nbytes, devc->num_transfers_completed);
+
 		sr_session_source_remove(sdi->session, -1 * (size_t)drvc->sr_ctx->libusb_ctx);
 		std_session_send_df_end(sdi);
 	}
@@ -183,7 +210,7 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 		sr_err("Unhandled `CMD_RST`");
 		return ret;
 	}
-	// clear_ep(EP_IN, usb->devhdl);
+	// clear_ep(devc->model->ep_in, usb->devhdl);
 
 	devc->samples_got_nbytes = 0;
 	devc->samples_need_nbytes = devc->cur_limit_samples * devc->cur_samplechannel / 8;
@@ -196,7 +223,6 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 
 	devc->per_transfer_duration = 500;
 	devc->per_transfer_nbytes = devc->cur_samplerate / SR_KHZ(1) * devc->cur_samplechannel / 8 * devc->per_transfer_duration /* ms */;
-	devc->per_transfer_nbytes = (devc->per_transfer_nbytes + 1023) & ~1023;
 
 	do {
 		struct libusb_transfer *transfer = libusb_alloc_transfer(0);
@@ -205,7 +231,7 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 			return SR_ERR_IO;
 		}
 		do {
-			devc->per_transfer_nbytes = (devc->per_transfer_nbytes + 1023) & ~1023;
+			devc->per_transfer_nbytes = (devc->per_transfer_nbytes + (2*16*1024-1)) & ~(2*16*1024-1);
 			devc->per_transfer_duration = devc->per_transfer_nbytes / (devc->cur_samplerate / SR_KHZ(1) * devc->cur_samplechannel / 8);
 			sr_dbg("Plan to receive %u bytes per %ums...", devc->per_transfer_nbytes, devc->per_transfer_duration);
 			
@@ -218,7 +244,7 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 
 			libusb_fill_bulk_transfer(transfer, usb->devhdl, devc->model->ep_in,
 										dev_buf, devc->per_transfer_nbytes, NULL,
-										NULL, devc->per_transfer_duration);
+										NULL, (TRANSFERS_DURATION_TOLERANCE + 1) * devc->per_transfer_duration);
 
 			ret = libusb_submit_transfer(transfer);
 			libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &(struct timeval){0, 0});
@@ -236,6 +262,9 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 				ret = libusb_cancel_transfer(transfer);
 				libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &(struct timeval){0, 0});
 				g_free(transfer->buffer);
+
+				devc->per_transfer_nbytes >>= 1;
+				devc->per_transfer_duration = devc->per_transfer_nbytes / (devc->cur_samplerate / SR_KHZ(1) * devc->cur_samplechannel / 8);
 				break;
 			}
 		} while (devc->per_transfer_nbytes > 128*1024); // 128kiB > 500ms * 1MHZ * 2ch
@@ -248,10 +277,11 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	devc->num_transfers_used = 0;
 	devc->num_transfers_completed = 0;
 	memset(devc->transfers, 0, sizeof(devc->transfers));
+	devc->transfers_reached_nbytes = 0;
 
 	sr_session_source_add(sdi->session, -1 * (size_t)drvc->sr_ctx->libusb_ctx, 0, devc->per_transfer_duration / 2, handle_events, (void *)sdi);
 
-	while (devc->num_transfers_used < NUM_MAX_TRANSFERS)
+	for (size_t reveiving_nbytes = 0; devc->num_transfers_used < NUM_MAX_TRANSFERS && reveiving_nbytes < devc->samples_need_nbytes; reveiving_nbytes += devc->per_transfer_nbytes)
 	{
 		uint8_t *dev_buf = g_malloc(devc->per_transfer_nbytes);
 		if (!dev_buf) {
@@ -266,9 +296,9 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 			break;
 		}
 
-		libusb_fill_bulk_transfer(transfer, usb->devhdl, EP_IN | LIBUSB_ENDPOINT_IN,
+		libusb_fill_bulk_transfer(transfer, usb->devhdl, devc->model->ep_in,
 									dev_buf, devc->per_transfer_nbytes, receive_transfer,
-									sdi, devc->per_transfer_duration);
+									sdi, (TRANSFERS_DURATION_TOLERANCE + 1) * devc->per_transfer_duration * (devc->num_transfers_used + 1));
 		transfer->actual_length = 0;
 
 		ret = libusb_submit_transfer(transfer);
@@ -286,6 +316,9 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	std_session_send_df_header(sdi);
 	std_session_send_df_frame_begin(sdi);
 
+	devc->transfers_reached_time_start = g_get_monotonic_time();
+	devc->transfers_reached_time_latest = devc->transfers_reached_time_start;
+
 	uint8_t cmd_run[] = {0x01, 0x00, 0x00, 0x00};
 	ret = slogic_basic_16_u3_reg_write(sdi, 0x0004, ARRAY_AND_SIZE(cmd_run));
 	if (ret < 0) {
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
index c9c9a34fe..cdcc16c50 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
@@ -28,9 +28,8 @@
 
 #define LOG_PREFIX "sipeed-slogic-analyzer"
 
-#define EP_IN 0x02
-#define SIZE_MAX_EP_HS 512
 #define NUM_MAX_TRANSFERS 64
+#define TRANSFERS_DURATION_TOLERANCE 0.05f
 
 struct slogic_model {
 	char *name;
@@ -68,6 +67,11 @@ struct dev_context {
 		size_t num_transfers_completed;
 		size_t num_transfers_used;
 		struct libusb_transfer *transfers[NUM_MAX_TRANSFERS];
+
+		uint64_t transfers_reached_nbytes; /* real received bytes in all */
+		uint64_t transfers_reached_nbytes_latest; /* real received bytes this transfer */
+		int64_t transfers_reached_time_start;
+		int64_t transfers_reached_time_latest;
 	}; // usb
 
 	int acq_aborted;

From d39a4e3ad6e80f08febc16d29efd2b3440bdf1f5 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Fri, 14 Mar 2025 17:46:58 +0800
Subject: [PATCH 09/36] sipeed-slogic-analyzer: feat: attempt to use function
 pointers to maintain compatibility with Lite 8

---
 src/hardware/sipeed-slogic-analyzer/api.c     | 255 +++++++++++++-----
 .../sipeed-slogic-analyzer/protocol.c         |  10 +-
 .../sipeed-slogic-analyzer/protocol.h         |  89 +-----
 3 files changed, 205 insertions(+), 149 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
index d779fe690..ca27437f6 100644
--- a/src/hardware/sipeed-slogic-analyzer/api.c
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -36,26 +36,41 @@ static const uint32_t devopts[] = {
 	SR_CONF_TRIGGER_MATCH | SR_CONF_GET | SR_CONF_LIST,
 };
 
-enum {
-	SLogic_LITE_8 = 0,
-	SLogic_BASIC_16_U3,
-};
+
+static int slogic_lite_8_remote_run(const struct sr_dev_inst *sdi);
+static int slogic_lite_8_remote_stop(const struct sr_dev_inst *sdi);
+static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi);
+static int slogic_basic_16_remote_stop(const struct sr_dev_inst *sdi);
 
 static const struct slogic_model support_models[] = {
-	[SLogic_LITE_8] = {
+	{
 		.name = "Slogic Lite 8",
+		.pid = 0x0300,
 		.ep_in = 0x02 | LIBUSB_ENDPOINT_IN,
 		.max_samplerate = SR_MHZ(160),
 		.max_samplechannel = 8,
 		.max_bandwidth = SR_MHZ(320),
+		.operation = {
+			.remote_run = slogic_lite_8_remote_run,
+			.remote_stop = slogic_lite_8_remote_stop,
+		},
 	},
-	[SLogic_BASIC_16_U3] = {
+	{
 		.name = "Slogic Basic 16 U3",
+		.pid = 0x3031,
 		.ep_in = 0x02 | LIBUSB_ENDPOINT_IN,
 		.max_samplerate = SR_MHZ(1600),
 		.max_samplechannel = 16,
 		.max_bandwidth = SR_MHZ(3200),
+		.operation = {
+			.remote_run = slogic_basic_16_remote_run,
+			.remote_stop = slogic_basic_16_remote_stop,
+		},
 	},
+	{
+		.name = NULL,
+		.pid = 0x0000,
+	}
 };
 
 static const uint64_t samplerates[] = {
@@ -112,6 +127,7 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 	struct drv_context *drvc;
 	struct dev_context *devc;
 
+	struct slogic_model *model;
 	struct sr_config *option;
 	struct libusb_device_descriptor des;
 	GSList *devices;
@@ -139,73 +155,75 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 		switch (option->key) {
 		case SR_CONF_CONN:
 			conn = g_variant_get_string(option->data, NULL);
-			sr_info("use conn: %s", conn);
+			sr_info("Use conn: %s", conn);
+			sr_err("Not supported now!");
+			return NULL;
 			break;
 		default:
 			sr_warn("Unhandled option key: %u", option->key);
 		}
 	}
-	
-	if(!conn) {
-		conn = "359f.3031";
-	}
-
-	/* Find all slogic compatible devices. */
-	conn_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, conn);
-	for(l = conn_devices; l; l = l->next) {
-		usb = l->data;
-		ret = sr_usb_open(drvc->sr_ctx->libusb_ctx, usb);
-		if (SR_OK != ret) continue;
-		libusb_get_device_descriptor(
-			libusb_get_device(usb->devhdl), &des);
-		libusb_get_string_descriptor_ascii(usb->devhdl,
-				des.iManufacturer, cbuf, sizeof(cbuf));
-		iManufacturer = g_strdup(cbuf);
-		libusb_get_string_descriptor_ascii(usb->devhdl,
-				des.iProduct, cbuf, sizeof(cbuf));
-		iProduct = g_strdup(cbuf);
-		libusb_get_string_descriptor_ascii(usb->devhdl,
-				des.iSerialNumber, cbuf, sizeof(cbuf));
-		iSerialNumber = g_strdup(cbuf);
-		usb_get_port_path(libusb_get_device(usb->devhdl),
-				cbuf, sizeof(cbuf));
-		iPortPath = g_strdup(cbuf);
-
-		sdi = sr_dev_inst_user_new(iManufacturer, iProduct, NULL);
-		sdi->serial_num = iSerialNumber;
-		sdi->connection_id = iPortPath;
-		sdi->status = SR_ST_INACTIVE;
-		sdi->conn = usb;
-		sdi->inst_type = SR_INST_USB;
-
-		devc = g_malloc0(sizeof(struct dev_context));
-		sdi->priv = devc;
-
-		{
-			devc->model = &support_models[SLogic_BASIC_16_U3];
 
-			devc->limit_samplechannel = devc->model->max_samplechannel;
-			devc->limit_samplerate = devc->model->max_bandwidth / devc->model->max_samplechannel;
-
-			devc->cur_samplechannel = devc->limit_samplechannel;
-			devc->cur_samplerate = devc->limit_samplerate;
+	for (model = &support_models[0]; model->name; model++) {
+		conn = g_strdup_printf("%04x.%04x", USB_VID_SIPEED, model->pid);
+		/* Find all slogic compatible devices. */
+		conn_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, conn);
+		for(l = conn_devices; l; l = l->next) {
+			usb = l->data;
+			ret = sr_usb_open(drvc->sr_ctx->libusb_ctx, usb);
+			if (SR_OK != ret) continue;
+			libusb_get_device_descriptor(
+				libusb_get_device(usb->devhdl), &des);
+			libusb_get_string_descriptor_ascii(usb->devhdl,
+					des.iManufacturer, cbuf, sizeof(cbuf));
+			iManufacturer = g_strdup(cbuf);
+			libusb_get_string_descriptor_ascii(usb->devhdl,
+					des.iProduct, cbuf, sizeof(cbuf));
+			iProduct = g_strdup(cbuf);
+			libusb_get_string_descriptor_ascii(usb->devhdl,
+					des.iSerialNumber, cbuf, sizeof(cbuf));
+			iSerialNumber = g_strdup(cbuf);
+			usb_get_port_path(libusb_get_device(usb->devhdl),
+					cbuf, sizeof(cbuf));
+			iPortPath = g_strdup(cbuf);
+
+			sdi = sr_dev_inst_user_new(iManufacturer, iProduct, NULL);
+			sdi->serial_num = iSerialNumber;
+			sdi->connection_id = iPortPath;
+			sdi->status = SR_ST_INACTIVE;
+			sdi->conn = usb;
+			sdi->inst_type = SR_INST_USB;
+
+			devc = g_malloc0(sizeof(struct dev_context));
+			sdi->priv = devc;
+
+			{
+				devc->model = model;
+
+				devc->limit_samplechannel = devc->model->max_samplechannel;
+				devc->limit_samplerate = devc->model->max_bandwidth / devc->model->max_samplechannel;
+
+				devc->cur_samplechannel = devc->limit_samplechannel;
+				devc->cur_samplerate = devc->limit_samplerate;
+
+				devc->digital_group = sr_channel_group_new(sdi, "LA", NULL);
+				for (i = 0; i < devc->model->max_samplechannel; i++) {
+					channel_name = g_strdup_printf("D%u", i);
+					ch = sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_name);
+					g_free(channel_name);
+					devc->digital_group->channels = g_slist_append(
+						devc->digital_group->channels, ch);
+				}
 
-			devc->digital_group = sr_channel_group_new(sdi, "LA", NULL);
-			for (i = 0; i < 16; i++) {
-				channel_name = g_strdup_printf("D%u", i);
-				ch = sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_name);
-				g_free(channel_name);
-				devc->digital_group->channels = g_slist_append(
-					devc->digital_group->channels, ch);
+				devc->speed = libusb_get_device_speed(libusb_get_device(usb->devhdl));
 			}
 
-			devc->speed = libusb_get_device_speed(libusb_get_device(usb->devhdl));
+			sr_usb_close(usb);
+			devices = g_slist_append(devices, sdi);
 		}
-
-		sr_usb_close(usb);
-		devices = g_slist_append(devices, sdi);
+		// g_slist_free_full(conn_devices, (GDestroyNotify)sr_usb_dev_inst_free);
+		g_free(conn);
 	}
-	// g_slist_free_full(conn_devices, (GDestroyNotify)sr_usb_dev_inst_free);
 
 	return std_scan_complete(di, devices);
 }
@@ -420,3 +438,116 @@ static struct sr_dev_driver sipeed_slogic_analyzer_driver_info = {
 	.context = NULL,
 };
 SR_REGISTER_DEV_DRIVER(sipeed_slogic_analyzer_driver_info);
+
+
+static int slogic_usb_control_write(const struct sr_dev_inst *sdi, uint8_t request, uint16_t value, uint16_t index, uint8_t *data, size_t len, int timeout);
+static int slogic_usb_control_read(const struct sr_dev_inst *sdi, uint8_t request, uint16_t value, uint16_t index, uint8_t *data, size_t len, int timeout);
+
+/* Slogic Lite 8 start */
+#pragma pack(push, 1)
+struct cmd_start_acquisition {
+  union {
+    struct {
+      uint8_t sample_rate_l;
+      uint8_t sample_rate_h;
+    };
+    uint16_t sample_rate;
+  };
+	uint8_t sample_channel;
+};
+#pragma pack(pop)
+
+#define CMD_START	0xb1
+#define CMD_STOP	0xb3
+
+static int slogic_lite_8_remote_run(const struct sr_dev_inst *sdi) {
+	struct dev_context *devc = sdi->priv;
+	const struct cmd_start_acquisition cmd_run = {
+		.sample_rate = devc->cur_samplerate / SR_MHZ(1),
+		.sample_channel = devc->cur_samplechannel,
+	};
+	return slogic_usb_control_write(sdi, CMD_START, 0x0000, 0x0000, (uint8_t *)&cmd_run, sizeof(cmd_run), 500);
+}
+
+static int slogic_lite_8_remote_stop(const struct sr_dev_inst *sdi) {
+	struct dev_context *devc = sdi->priv;
+	struct sr_usb_dev_inst *usb = sdi->conn;
+	// int ret = slogic_usb_control_write(sdi, CMD_STOP, 0x0000, 0x0000, NULL, 0, 500);
+	clear_ep(devc->model->ep_in, usb->devhdl);
+	return 0;
+}
+/* Slogic Lite 8 end */
+
+
+
+/* Slogic Basic 16 start */
+#define SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ 	0x00
+#define SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE 	0x01
+
+static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi) {
+	const uint8_t cmd_run[] = {0x01, 0x00, 0x00, 0x00};
+	return slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, 0x0004, 0x0000, ARRAY_AND_SIZE(cmd_run), 500);
+}
+
+static int slogic_basic_16_remote_stop(const struct sr_dev_inst *sdi) {
+	const uint8_t cmd_rst[] = {0x02, 0x00, 0x00, 0x00};
+	return slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, 0x0004, 0x0000, ARRAY_AND_SIZE(cmd_rst), 500);
+}
+/* Slogic Basic 16 end */
+
+static int slogic_usb_control_write(const struct sr_dev_inst *sdi, uint8_t request, uint16_t value, uint16_t index, uint8_t *data, size_t len, int timeout)
+{
+	int ret;
+	struct dev_context *devc;
+	struct sr_usb_dev_inst *usb;
+
+	devc = sdi->priv;
+	usb  = sdi->conn;
+
+	sr_spew("%s req:%u value:%u index:%u %p:%u in %dms.", __func__, request, value, index, data, len, timeout);
+	if (!data && len) {
+		sr_warn("%s Nothing to write although len(%u)>0!", __func__, len);
+		len = 0;
+	}
+
+	if ((ret = libusb_control_transfer(
+		usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT,
+		request,
+		value, index,
+		(unsigned char *)data, len,
+		timeout
+	)) < 0) {
+		sr_err("%s failed(libusb: %s)!", __func__, libusb_error_name(ret));
+		return SR_ERR_NA;
+	}
+	return ret;
+}
+
+
+static int slogic_usb_control_read(const struct sr_dev_inst *sdi, uint8_t request, uint16_t value, uint16_t index, uint8_t *data, size_t len, int timeout)
+{
+	int ret;
+	struct dev_context *devc;
+	struct sr_usb_dev_inst *usb;
+
+	devc = sdi->priv;
+	usb  = sdi->conn;
+
+	sr_spew("%s req:%u value:%u index:%u %p:%u in %dms.", __func__, request, value, index, data, len, timeout);
+	if (!data && len) {
+		sr_err("%s Can't read to NULL while len(%u)>0!", __func__, len);
+		return SR_ERR_ARG;
+	}
+
+	if ((ret = libusb_control_transfer(
+		usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN,
+		request,
+		value, index,
+		(unsigned char *)data, len,
+		timeout
+	)) < 0) {
+		sr_err("%s failed(libusb: %s)!", __func__, libusb_error_name(ret));
+		return SR_ERR_NA;
+	}
+	return ret;
+}
\ No newline at end of file
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index a0561007a..9330f4507 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -204,10 +204,8 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	drvc = di->context;
 	usb  = sdi->conn;
 
-	uint8_t cmd_rst[] = {0x02, 0x00, 0x00, 0x00};
-	ret = slogic_basic_16_u3_reg_write(sdi, 0x0004, ARRAY_AND_SIZE(cmd_rst));
-	if (ret < 0) {
-		sr_err("Unhandled `CMD_RST`");
+	if ((ret = devc->model->operation.remote_stop(sdi)) < 0) {
+		sr_err("Unhandled `CMD_STOP`");
 		return ret;
 	}
 	// clear_ep(devc->model->ep_in, usb->devhdl);
@@ -319,9 +317,7 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	devc->transfers_reached_time_start = g_get_monotonic_time();
 	devc->transfers_reached_time_latest = devc->transfers_reached_time_start;
 
-	uint8_t cmd_run[] = {0x01, 0x00, 0x00, 0x00};
-	ret = slogic_basic_16_u3_reg_write(sdi, 0x0004, ARRAY_AND_SIZE(cmd_run));
-	if (ret < 0) {
+	if ((ret = devc->model->operation.remote_run(sdi)) < 0) {
 		sr_err("Unhandled `CMD_RUN`");
 		return ret;
 	}
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
index cdcc16c50..d61c67a15 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
@@ -28,15 +28,21 @@
 
 #define LOG_PREFIX "sipeed-slogic-analyzer"
 
+#define USB_VID_SIPEED UINT16_C(0x359f)
 #define NUM_MAX_TRANSFERS 64
 #define TRANSFERS_DURATION_TOLERANCE 0.05f
 
 struct slogic_model {
 	char *name;
+	uint16_t pid;
 	uint8_t ep_in;
 	uint64_t max_samplerate; // limit by hardware
 	uint64_t max_samplechannel; // limit by hardware
 	uint64_t max_bandwidth; // limit by hardware
+	struct slogic_model_operation {
+		int (*remote_run)(const struct sr_dev_inst *sdi);
+		int (*remote_stop)(const struct sr_dev_inst *sdi);
+	} operation;
 };
 
 struct dev_context {
@@ -84,95 +90,18 @@ struct dev_context {
 	double voltage_threshold[2];
 };
 
-#pragma pack(push, 1)
-struct cmd_start_acquisition {
-  union {
-    struct {
-      uint8_t sample_rate_l;
-      uint8_t sample_rate_h;
-    };
-    uint16_t sample_rate;
-  };
-	uint8_t sample_channel;
-};
-#pragma pack(pop)
-
-/* Protocol commands */
-#define CMD_START	0xb1
-#define CMD_STOP	0xb3
-
 SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi);
 SR_PRIV int sipeed_slogic_acquisition_stop(struct sr_dev_inst *sdi);
 
 static inline void clear_ep(uint8_t ep, libusb_device_handle *usbh) {
-	sr_dbg("Clearring EP: %u", ep);
-	uint8_t tmp[512];
+	sr_dbg("Clearring EP: 0x%02x", ep);
+	uint8_t tmp[1024];
 	int actual_length = 0;
 	do {
 		libusb_bulk_transfer(usbh, ep | LIBUSB_ENDPOINT_IN,
 				tmp, sizeof(tmp), &actual_length, 100);
 	} while (actual_length);
-	sr_dbg("Cleared EP: %u", ep);
-}
-
-#define CONTROL_IN_REQ_REG_READ 	0x00
-#define CONTROL_OUT_REQ_REG_WRITE 	0x01
-
-static inline int slogic_basic_16_u3_reg_write(const struct sr_dev_inst *sdi, uint16_t value, uint8_t *data, size_t len)
-{
-	int ret;
-	struct dev_context *devc;
-	struct sr_usb_dev_inst *usb;
-
-	devc = sdi->priv;
-	usb  = sdi->conn;
-
-	sr_spew("%s %u %p:%u.", __func__, value, data, len);
-	if (!data || !len) {
-		sr_err("%s failed(Nothing to write)!", __func__);
-		return SR_ERR_ARG;
-	}
-
-	if ((ret = libusb_control_transfer(
-		usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT,
-		CONTROL_OUT_REQ_REG_WRITE,
-		value, 0x0000,
-		(unsigned char *)data, len,
-		500
-	)) < 0) {
-		sr_err("%s failed(libusb: %s)!", __func__, libusb_error_name(ret));
-		return SR_ERR_NA;
-	}
-	return ret;
-}
-
-
-static inline int slogic_basic_16_u3_reg_read(const struct sr_dev_inst *sdi, uint16_t value, uint8_t *data, size_t len)
-{
-	int ret;
-	struct dev_context *devc;
-	struct sr_usb_dev_inst *usb;
-
-	devc = sdi->priv;
-	usb  = sdi->conn;
-
-	sr_spew("%s %u %p:%u.", __func__, value, data, len);
-	if (!data || !len) {
-		sr_err("%s failed(Nothing to read)!", __func__);
-		return SR_ERR_ARG;
-	}
-
-	if ((ret = libusb_control_transfer(
-		usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN,
-		CONTROL_IN_REQ_REG_READ,
-		value, 0x0000,
-		(unsigned char *)data, len,
-		500
-	)) < 0) {
-		sr_err("%s failed(libusb: %s)!", __func__, libusb_error_name(ret));
-		return SR_ERR_NA;
-	}
-	return ret;
+	sr_dbg("Cleared EP: 0x%02x", ep);
 }
 
 #endif

From 1fa13c1ec3fd6215749213faae5429a0aceffec6 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Fri, 14 Mar 2025 17:59:26 +0800
Subject: [PATCH 10/36] sipeed-slogic-analyzer: fix: slogic lite 8 use ep(0x81)

---
 src/hardware/sipeed-slogic-analyzer/api.c      | 13 ++++---------
 src/hardware/sipeed-slogic-analyzer/protocol.c |  6 ++----
 src/hardware/sipeed-slogic-analyzer/protocol.h |  9 ++++++---
 3 files changed, 12 insertions(+), 16 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
index ca27437f6..4568b3b0d 100644
--- a/src/hardware/sipeed-slogic-analyzer/api.c
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -46,7 +46,7 @@ static const struct slogic_model support_models[] = {
 	{
 		.name = "Slogic Lite 8",
 		.pid = 0x0300,
-		.ep_in = 0x02 | LIBUSB_ENDPOINT_IN,
+		.ep_in = 0x01 | LIBUSB_ENDPOINT_IN,
 		.max_samplerate = SR_MHZ(160),
 		.max_samplechannel = 8,
 		.max_bandwidth = SR_MHZ(320),
@@ -236,9 +236,6 @@ static int dev_open(struct sr_dev_inst *sdi)
 	struct sr_dev_driver *di;
 	struct drv_context *drvc;
 
-
-	if (!sdi) return SR_ERR_DEV_CLOSED;
-	/* TODO: get handle from sdi->conn and open it. */
 	usb  = sdi->conn;
 	devc = sdi->priv;
 	di	 = sdi->driver;
@@ -276,7 +273,6 @@ static int dev_close(struct sr_dev_inst *sdi)
 	struct sr_dev_driver *di;
 	struct drv_context *drvc;
 
-	/* TODO: get handle from sdi->conn and close it. */
 	usb  = sdi->conn;
 	devc = sdi->priv;
 	di	 = sdi->driver;
@@ -398,7 +394,6 @@ static int config_list(uint32_t key, GVariant **data,
 
 	ret = SR_OK;
 	switch (key) {
-	/* TODO */
 	case SR_CONF_SCAN_OPTIONS:
 	case SR_CONF_DEVICE_OPTIONS:
 		ret = STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
@@ -472,9 +467,9 @@ static int slogic_lite_8_remote_run(const struct sr_dev_inst *sdi) {
 static int slogic_lite_8_remote_stop(const struct sr_dev_inst *sdi) {
 	struct dev_context *devc = sdi->priv;
 	struct sr_usb_dev_inst *usb = sdi->conn;
-	// int ret = slogic_usb_control_write(sdi, CMD_STOP, 0x0000, 0x0000, NULL, 0, 500);
-	clear_ep(devc->model->ep_in, usb->devhdl);
-	return 0;
+	int ret = slogic_usb_control_write(sdi, CMD_STOP, 0x0000, 0x0000, NULL, 0, 500);
+	clear_ep(sdi);
+	return ret;
 }
 /* Slogic Lite 8 end */
 
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index 9330f4507..979693999 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -81,6 +81,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 				break;
 			}
 
+			/* TODO: move out submit to ensure continuous transfers */
 			if (1) {
 				uint8_t * d = transfer->buffer;
 				size_t len = transfer->actual_length;
@@ -189,9 +190,6 @@ static int handle_events(int fd, int revents, void *cb_data)
 
 SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 {
-	/* TODO: configure hardware, reset acquisition state, set up
-	 * callbacks and send header packet. */
-
 	struct sr_dev_driver *di;
 	struct dev_context *devc;
 	struct drv_context *drvc;
@@ -208,7 +206,7 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 		sr_err("Unhandled `CMD_STOP`");
 		return ret;
 	}
-	// clear_ep(devc->model->ep_in, usb->devhdl);
+	// clear_ep(sdi);
 
 	devc->samples_got_nbytes = 0;
 	devc->samples_need_nbytes = devc->cur_limit_samples * devc->cur_samplechannel / 8;
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
index d61c67a15..d537d178b 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
@@ -93,12 +93,15 @@ struct dev_context {
 SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi);
 SR_PRIV int sipeed_slogic_acquisition_stop(struct sr_dev_inst *sdi);
 
-static inline void clear_ep(uint8_t ep, libusb_device_handle *usbh) {
-	sr_dbg("Clearring EP: 0x%02x", ep);
+static inline void clear_ep(const struct sr_dev_inst *sdi) {
+	struct dev_context *devc = sdi->priv;
+	struct sr_usb_dev_inst *usb = sdi->conn;
+	uint8_t ep = devc->model->ep_in;
+
 	uint8_t tmp[1024];
 	int actual_length = 0;
 	do {
-		libusb_bulk_transfer(usbh, ep | LIBUSB_ENDPOINT_IN,
+		libusb_bulk_transfer(usb->devhdl, ep,
 				tmp, sizeof(tmp), &actual_length, 100);
 	} while (actual_length);
 	sr_dbg("Cleared EP: 0x%02x", ep);

From 33b5d8ac8c2c277596561bbf8d5f056d5553ea02 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Fri, 14 Mar 2025 18:17:08 +0800
Subject: [PATCH 11/36] sipeed-slogic-analyzer: fix: stop while has no
 transfers submitted

---
 src/hardware/sipeed-slogic-analyzer/protocol.c | 5 +++++
 src/hardware/sipeed-slogic-analyzer/protocol.h | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index 979693999..2ae07cc06 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -315,6 +315,11 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	devc->transfers_reached_time_start = g_get_monotonic_time();
 	devc->transfers_reached_time_latest = devc->transfers_reached_time_start;
 
+	if (!devc->num_transfers_used) {
+		sipeed_slogic_acquisition_stop(sdi);
+		return SR_OK;
+	}
+
 	if ((ret = devc->model->operation.remote_run(sdi)) < 0) {
 		sr_err("Unhandled `CMD_RUN`");
 		return ret;
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
index d537d178b..e640f1c3d 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
@@ -39,7 +39,7 @@ struct slogic_model {
 	uint64_t max_samplerate; // limit by hardware
 	uint64_t max_samplechannel; // limit by hardware
 	uint64_t max_bandwidth; // limit by hardware
-	struct slogic_model_operation {
+	struct {
 		int (*remote_run)(const struct sr_dev_inst *sdi);
 		int (*remote_stop)(const struct sr_dev_inst *sdi);
 	} operation;

From f366f325bbeda3b917124f539660dcafd41cd1f7 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Fri, 14 Mar 2025 20:19:55 +0800
Subject: [PATCH 12/36] sipeed-slogic-analyzer: test: add submit_raw_data

---
 src/hardware/sipeed-slogic-analyzer/api.c     | 84 +++++++++++++++++++
 .../sipeed-slogic-analyzer/protocol.c         | 35 +-------
 .../sipeed-slogic-analyzer/protocol.h         |  1 +
 3 files changed, 86 insertions(+), 34 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
index 4568b3b0d..7f81632e5 100644
--- a/src/hardware/sipeed-slogic-analyzer/api.c
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -39,8 +39,10 @@ static const uint32_t devopts[] = {
 
 static int slogic_lite_8_remote_run(const struct sr_dev_inst *sdi);
 static int slogic_lite_8_remote_stop(const struct sr_dev_inst *sdi);
+static void slogic_lite_8_submit_raw_data(void *data, size_t len, const struct sr_dev_inst *sdi);
 static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi);
 static int slogic_basic_16_remote_stop(const struct sr_dev_inst *sdi);
+static void slogic_basic_16_submit_raw_data(void *data, size_t len, const struct sr_dev_inst *sdi);
 
 static const struct slogic_model support_models[] = {
 	{
@@ -54,6 +56,7 @@ static const struct slogic_model support_models[] = {
 			.remote_run = slogic_lite_8_remote_run,
 			.remote_stop = slogic_lite_8_remote_stop,
 		},
+		.submit_raw_data = slogic_lite_8_submit_raw_data,
 	},
 	{
 		.name = "Slogic Basic 16 U3",
@@ -66,6 +69,7 @@ static const struct slogic_model support_models[] = {
 			.remote_run = slogic_basic_16_remote_run,
 			.remote_stop = slogic_basic_16_remote_stop,
 		},
+		.submit_raw_data = slogic_basic_16_submit_raw_data,
 	},
 	{
 		.name = NULL,
@@ -471,6 +475,41 @@ static int slogic_lite_8_remote_stop(const struct sr_dev_inst *sdi) {
 	clear_ep(sdi);
 	return ret;
 }
+
+static void slogic_lite_8_submit_raw_data(void *data, size_t len, const struct sr_dev_inst *sdi) {
+	struct dev_context *devc = sdi->priv;
+
+	size_t length = len * (8/devc->cur_samplechannel);
+	uint8_t *ptr = g_malloc(length);
+
+	for(size_t i=0; i<len; i+=devc->cur_samplechannel) {
+		for(size_t j=0; j<8; j++) {
+			ptr[i*(8/devc->cur_samplechannel)+j] = (((uint8_t *)data)[i+j/(8/devc->cur_samplechannel)] >> (j%(8/devc->cur_samplechannel) * devc->cur_samplechannel)) & ((1<<devc->cur_samplechannel)-1);
+			// switch (devc->cur_samplechannel) {
+			// case 8:
+			// 	ptr[i*1+j] = (((uint8_t *)data)[i+j/1] >> (j%1 * 8)) & 0xff;
+			// break;
+			// case 4:
+			// 	ptr[i*2+j] = (((uint8_t *)data)[i+j/2] >> (j%2 * 4)) & 0xf;
+			// break;
+			// case 2:
+			// 	ptr[i*4+j] = (((uint8_t *)data)[i+j/4] >> (j%4 * 2)) & 0x3;
+			// break;
+			// }
+		}
+	}
+
+	sr_session_send(sdi, &(struct sr_datafeed_packet) {
+		.type = SR_DF_LOGIC,
+		.payload = &(struct sr_datafeed_logic) {
+			.length = length,
+			.unitsize = 1,
+			.data = ptr,
+		}
+	});
+
+	g_free(ptr);
+}
 /* Slogic Lite 8 end */
 
 
@@ -488,6 +527,51 @@ static int slogic_basic_16_remote_stop(const struct sr_dev_inst *sdi) {
 	const uint8_t cmd_rst[] = {0x02, 0x00, 0x00, 0x00};
 	return slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, 0x0004, 0x0000, ARRAY_AND_SIZE(cmd_rst), 500);
 }
+
+static void slogic_basic_16_submit_raw_data(void *data, size_t len, const struct sr_dev_inst *sdi) {
+	struct dev_context *devc = sdi->priv;
+
+	size_t length = len * ((devc->cur_samplechannel>=8)?:(8/devc->cur_samplechannel));
+	uint8_t *ptr = g_malloc(length);
+
+	for(size_t i=0; i<len; i+=devc->cur_samplechannel) {
+		for(size_t j=0; j<8; j++) {
+			#define B(n) (((((uint8_t *)data)[i+(n)] >> 7-j) & 0x1) << ((n)%8))
+			switch (devc->cur_samplechannel) {
+			case 16:
+				ptr[i+j*2+0] =
+					B(0)|B(1)|B(2)|B(3)|B(4)|B(5)|B(6)|B(7);
+				ptr[i+j*2+1] =
+					B(8)|B(9)|B(10)|B(11)|B(12)|B(13)|B(14)|B(15);
+			break;
+			case 8:
+				ptr[i+j] =
+					B(0)|B(1)|B(2)|B(3)|B(4)|B(5)|B(6)|B(7);
+			break;
+			case 4:
+				ptr[i*2+j] =
+					B(0)|B(1)|B(2)|B(3);
+			break;
+			case 2:
+				ptr[i*4+j] =
+					B(0)|B(1);
+			break;
+			}
+			#undef B
+		}
+	}
+
+	sr_session_send(sdi, &(struct sr_datafeed_packet) {
+		.type = SR_DF_LOGIC,
+		.payload = &(struct sr_datafeed_logic) {
+			.length = length,
+			.unitsize = (devc->cur_samplechannel + 7)/8,
+			.data = ptr,
+		}
+	});
+
+	g_free(ptr);
+}
 /* Slogic Basic 16 end */
 
 static int slogic_usb_control_write(const struct sr_dev_inst *sdi, uint8_t request, uint16_t value, uint16_t index, uint8_t *data, size_t len, int timeout)
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index 2ae07cc06..927affd97 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -20,23 +20,6 @@
 #include <config.h>
 #include "protocol.h"
 
-static int handle_events(int fd, int revents, void *cb_data);
-
-static void submit_data(void *data, size_t len, const struct sr_dev_inst *sdi) {
-	struct sr_datafeed_logic logic = {
-		.length = len,
-		.unitsize = (((struct dev_context *)(sdi->priv))->cur_samplechannel + 7)/8,
-		.data = data,
-	};
-
-	struct sr_datafeed_packet packet = {
-		.type = SR_DF_LOGIC,
-		.payload = &logic
-	};
-
-	sr_session_send(sdi, &packet);
-}
-
 static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 
 	int ret;
@@ -87,23 +70,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 				size_t len = transfer->actual_length;
 				// sr_dbg("HEAD: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
 				// 	d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
-
-				uint8_t *ptr = g_malloc(len);
-
-				for(size_t i=0; i<len; i+=16) {
-					for(size_t j=0; j< 8; j++) {
-						#define B(n) (((d[i+(n)] >> 7-j) & 0x1) << ((n)%8))
-						ptr[i+j*2+0] =
-							B(0)|B(1)|B(2)|B(3)|B(4)|B(5)|B(6)|B(7);
-						ptr[i+j*2+1] =
-							B(8)|B(9)|B(10)|B(11)|B(12)|B(13)|B(14)|B(15);
-						#undef B
-					}
-				}
-
-				submit_data(ptr, len, sdi);
-
-				g_free(ptr);
+				devc->model->submit_raw_data(d, len, sdi);
 			}
 
 			if (devc->samples_got_nbytes < devc->samples_need_nbytes) {
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
index e640f1c3d..5e2f7d930 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
@@ -43,6 +43,7 @@ struct slogic_model {
 		int (*remote_run)(const struct sr_dev_inst *sdi);
 		int (*remote_stop)(const struct sr_dev_inst *sdi);
 	} operation;
+	void (*submit_raw_data)(void *data, size_t len, const struct sr_dev_inst *sdi);
 };
 
 struct dev_context {

From 03a88ee897caf203fc9a1427bccc1295ebd1b4ec Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Fri, 14 Mar 2025 20:31:32 +0800
Subject: [PATCH 13/36] sipeed-slogic-analyzer: fix: skip sending real stop
 command for slogic lite 8

---
 src/hardware/sipeed-slogic-analyzer/api.c      | 7 +++++--
 src/hardware/sipeed-slogic-analyzer/protocol.c | 8 ++++----
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
index 7f81632e5..2861be9f7 100644
--- a/src/hardware/sipeed-slogic-analyzer/api.c
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -471,9 +471,12 @@ static int slogic_lite_8_remote_run(const struct sr_dev_inst *sdi) {
 static int slogic_lite_8_remote_stop(const struct sr_dev_inst *sdi) {
 	struct dev_context *devc = sdi->priv;
 	struct sr_usb_dev_inst *usb = sdi->conn;
-	int ret = slogic_usb_control_write(sdi, CMD_STOP, 0x0000, 0x0000, NULL, 0, 500);
 	clear_ep(sdi);
-	return ret;
+	return SR_OK;
+	/* not stable, but can be ignored */
+	// int ret = slogic_usb_control_write(sdi, CMD_STOP, 0x0000, 0x0000, NULL, 0, 500);
+	// clear_ep(sdi);
+	// return ret;
 }
 
 static void slogic_lite_8_submit_raw_data(void *data, size_t len, const struct sr_dev_inst *sdi) {
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index 927affd97..e39b0531c 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -78,7 +78,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 				transfer->timeout = (TRANSFERS_DURATION_TOLERANCE + 1) * devc->per_transfer_duration * (devc->num_transfers_used + 1);
 				ret = libusb_submit_transfer(transfer);
 				if (ret) {
-					sr_warn("Failed to submit transfer: %s", libusb_error_name(ret));
+					sr_dbg("Failed to submit transfer: %s", libusb_error_name(ret));
 					devc->num_transfers_used -= 1;
 				} else {
 					sr_spew("Resubmit transfer: %p", transfer);
@@ -248,13 +248,13 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	{
 		uint8_t *dev_buf = g_malloc(devc->per_transfer_nbytes);
 		if (!dev_buf) {
-			sr_warn("Failed to allocate memory[%d]", devc->num_transfers_used);
+			sr_dbg("Failed to allocate memory[%d]", devc->num_transfers_used);
 			break;
 		}
 
 		struct libusb_transfer *transfer = libusb_alloc_transfer(0);
 		if (!transfer) {
-			sr_warn("Failed to allocate transfer[%d]", devc->num_transfers_used);
+			sr_dbg("Failed to allocate transfer[%d]", devc->num_transfers_used);
 			g_free(dev_buf);
 			break;
 		}
@@ -266,7 +266,7 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 
 		ret = libusb_submit_transfer(transfer);
 		if (ret) {
-			sr_warn("Failed to submit transfer[%d]: %s.", devc->num_transfers_used, libusb_error_name(ret));
+			sr_dbg("Failed to submit transfer[%d]: %s.", devc->num_transfers_used, libusb_error_name(ret));
 			g_free(transfer->buffer);
 			libusb_free_transfer(transfer);
 			break;

From 1438036e08cbcc4657e8b7bafa0f35176c247877 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Sat, 15 Mar 2025 17:57:26 +0800
Subject: [PATCH 14/36] sipeed-slogic-analyzer: feat: use pattern mode to test
 to get the max speed of usb

---
 src/hardware/sipeed-slogic-analyzer/api.c     | 20 +++++++++++++++++++
 .../sipeed-slogic-analyzer/protocol.c         |  4 ++--
 .../sipeed-slogic-analyzer/protocol.h         |  6 ++++++
 3 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
index 2861be9f7..597f47734 100644
--- a/src/hardware/sipeed-slogic-analyzer/api.c
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -33,6 +33,7 @@ static const uint32_t devopts[] = {
 	SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
 	SR_CONF_SAMPLERATE    | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
 	SR_CONF_BUFFERSIZE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
+	SR_CONF_PATTERN_MODE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
 	SR_CONF_TRIGGER_MATCH | SR_CONF_GET | SR_CONF_LIST,
 };
 
@@ -113,6 +114,13 @@ static const uint64_t buffersizes[] = {
 	2, 4, 8, 16
 };
 
+static const char *patterns[] = {
+#define GEN_PATTERN(P) [P] = #P
+	GEN_PATTERN(PATTERN_MODE_NOMAL),
+	GEN_PATTERN(PATTERN_MODE_TEST_MAX_SPEED),
+#undef GEN_PATTERN
+};
+
 static const int32_t trigger_matches[] = {
 	SR_TRIGGER_ZERO,
 	SR_TRIGGER_ONE,
@@ -209,6 +217,7 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
 
 				devc->cur_samplechannel = devc->limit_samplechannel;
 				devc->cur_samplerate = devc->limit_samplerate;
+				devc->cur_pattern_mode_idx = PATTERN_MODE_NOMAL;
 
 				devc->digital_group = sr_channel_group_new(sdi, "LA", NULL);
 				for (i = 0; i < devc->model->max_samplechannel; i++) {
@@ -319,6 +328,9 @@ static int config_get(uint32_t key, GVariant **data,
 	case SR_CONF_BUFFERSIZE:
 		*data = g_variant_new_uint64(devc->cur_samplechannel);
 		break;
+	case SR_CONF_PATTERN_MODE:
+		*data = g_variant_new_string(patterns[devc->cur_pattern_mode_idx]);
+		break;
 	case SR_CONF_LIMIT_SAMPLES:
 		*data = g_variant_new_uint64(devc->cur_limit_samples);
 		break;
@@ -376,6 +388,11 @@ static int config_set(uint32_t key, GVariant *data,
 			}
 		}
 		break;
+	case SR_CONF_PATTERN_MODE:
+		devc->cur_pattern_mode_idx = std_str_idx(data, ARRAY_AND_SIZE(patterns));
+		if (devc->cur_pattern_mode_idx < 0)
+			devc->cur_pattern_mode_idx = 0;
+		break;
 	case SR_CONF_LIMIT_SAMPLES:
 		devc->cur_limit_samples = g_variant_get_uint64(data);
 		break;
@@ -408,6 +425,9 @@ static int config_list(uint32_t key, GVariant **data,
 	case SR_CONF_BUFFERSIZE:
 		*data = std_gvar_array_u64(buffersizes, 1+std_u64_idx(g_variant_new_uint64(devc->limit_samplechannel), ARRAY_AND_SIZE(buffersizes)));
 		break;
+	case SR_CONF_PATTERN_MODE:
+		*data = g_variant_new_strv(ARRAY_AND_SIZE(patterns));
+		break;
 	case SR_CONF_TRIGGER_MATCH:
 		*data = std_gvar_array_i32(ARRAY_AND_SIZE(trigger_matches));
 		break;
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index e39b0531c..968f1062d 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -65,7 +65,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 			}
 
 			/* TODO: move out submit to ensure continuous transfers */
-			if (1) {
+			if (devc->cur_pattern_mode_idx != PATTERN_MODE_TEST_MAX_SPEED) {
 				uint8_t * d = transfer->buffer;
 				size_t len = transfer->actual_length;
 				// sr_dbg("HEAD: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
@@ -242,7 +242,7 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	memset(devc->transfers, 0, sizeof(devc->transfers));
 	devc->transfers_reached_nbytes = 0;
 
-	sr_session_source_add(sdi->session, -1 * (size_t)drvc->sr_ctx->libusb_ctx, 0, devc->per_transfer_duration / 2, handle_events, (void *)sdi);
+	sr_session_source_add(sdi->session, -1 * (size_t)drvc->sr_ctx->libusb_ctx, 0, (devc->per_transfer_duration / 2)?:1, handle_events, (void *)sdi);
 
 	for (size_t reveiving_nbytes = 0; devc->num_transfers_used < NUM_MAX_TRANSFERS && reveiving_nbytes < devc->samples_need_nbytes; reveiving_nbytes += devc->per_transfer_nbytes)
 	{
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
index 5e2f7d930..5e34b946c 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
@@ -32,6 +32,11 @@
 #define NUM_MAX_TRANSFERS 64
 #define TRANSFERS_DURATION_TOLERANCE 0.05f
 
+enum {
+	PATTERN_MODE_NOMAL,
+	PATTERN_MODE_TEST_MAX_SPEED,
+};
+
 struct slogic_model {
 	char *name;
 	uint16_t pid;
@@ -60,6 +65,7 @@ struct dev_context {
 		uint64_t cur_limit_samples;
 		uint64_t cur_samplerate;
 		uint64_t cur_samplechannel;
+		int64_t cur_pattern_mode_idx;
 	}; // configuration
 
 	struct {

From 8dc86c7b1fa4d9c7c5c84c16fe028ca696fea1e7 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Sat, 15 Mar 2025 18:49:50 +0800
Subject: [PATCH 15/36] sipeed-slogic-analyzer: fix: wait one more duration for
 transfers preparation

---
 src/hardware/sipeed-slogic-analyzer/protocol.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index 968f1062d..054fb4869 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -75,7 +75,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 
 			if (devc->samples_got_nbytes < devc->samples_need_nbytes) {
 				transfer->actual_length = 0;
-				transfer->timeout = (TRANSFERS_DURATION_TOLERANCE + 1) * devc->per_transfer_duration * (devc->num_transfers_used + 1);
+				transfer->timeout = (TRANSFERS_DURATION_TOLERANCE + 1) * devc->per_transfer_duration * (devc->num_transfers_used + 2);
 				ret = libusb_submit_transfer(transfer);
 				if (ret) {
 					sr_dbg("Failed to submit transfer: %s", libusb_error_name(ret));
@@ -261,7 +261,7 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 
 		libusb_fill_bulk_transfer(transfer, usb->devhdl, devc->model->ep_in,
 									dev_buf, devc->per_transfer_nbytes, receive_transfer,
-									sdi, (TRANSFERS_DURATION_TOLERANCE + 1) * devc->per_transfer_duration * (devc->num_transfers_used + 1));
+									sdi, (TRANSFERS_DURATION_TOLERANCE + 1) * devc->per_transfer_duration * (devc->num_transfers_used + 2));
 		transfer->actual_length = 0;
 
 		ret = libusb_submit_transfer(transfer);

From 7c5ac175f4e2fbec36372ff1c468e73189eef987 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Sun, 16 Mar 2025 19:19:56 +0800
Subject: [PATCH 16/36] sipeed-slogic-analyzer: fix: libusb_handle_events at
 right time,  use `%%` and start from 125ms

---
 .../sipeed-slogic-analyzer/protocol.c         | 39 +++++++++++--------
 1 file changed, 23 insertions(+), 16 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index 054fb4869..1166658ad 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -49,7 +49,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 			if (transfer->actual_length > devc->samples_need_nbytes - devc->samples_got_nbytes)
 				transfer->actual_length = devc->samples_need_nbytes - devc->samples_got_nbytes;
 			devc->samples_got_nbytes += transfer->actual_length;
-			sr_dbg("[%u] Got(%.2f%): %u/%u => speed: %.2fMBps, %.2fMBps(avg) => +%.3f=%.3fms.",
+			sr_dbg("[%u] Got(%.2f%%): %u/%u => speed: %.2fMBps, %.2fMBps(avg) => +%.3f=%.3fms.",
 				devc->num_transfers_completed,
 				100.f * devc->samples_got_nbytes / devc->samples_need_nbytes, devc->samples_got_nbytes, devc->samples_need_nbytes,
 				(double)devc->transfers_reached_nbytes_latest / transfers_reached_duration,
@@ -73,18 +73,17 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 				devc->model->submit_raw_data(d, len, sdi);
 			}
 
-			if (devc->samples_got_nbytes < devc->samples_need_nbytes) {
+			devc->num_transfers_used -= 1;
+			if (devc->samples_got_nbytes + devc->num_transfers_used * devc->per_transfer_nbytes < devc->samples_need_nbytes) {
 				transfer->actual_length = 0;
 				transfer->timeout = (TRANSFERS_DURATION_TOLERANCE + 1) * devc->per_transfer_duration * (devc->num_transfers_used + 2);
 				ret = libusb_submit_transfer(transfer);
 				if (ret) {
 					sr_dbg("Failed to submit transfer: %s", libusb_error_name(ret));
-					devc->num_transfers_used -= 1;
 				} else {
 					sr_spew("Resubmit transfer: %p", transfer);
+					devc->num_transfers_used += 1;
 				}
-			} else {
-				devc->num_transfers_used = 0;
 			}
 		} break;
 
@@ -100,7 +99,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 	}
 
 	if (devc->num_transfers_completed && (double)transfers_reached_duration / SR_KHZ(1) > (TRANSFERS_DURATION_TOLERANCE + 1) * devc->per_transfer_duration) {
-		sr_err("Timeout %.3fms!!! Reach duration limit: %.3f(%u+%.1f%) except first one.",
+		sr_err("Timeout %.3fms!!! Reach duration limit: %.3f(%u+%.1f%%) except first one.",
 			(double)transfers_reached_duration / SR_KHZ(1),
 			(TRANSFERS_DURATION_TOLERANCE + 1) * devc->per_transfer_duration, devc->per_transfer_duration, TRANSFERS_DURATION_TOLERANCE * 100
 		);
@@ -136,7 +135,12 @@ static int handle_events(int fd, int revents, void *cb_data)
 			struct libusb_transfer *transfer = devc->transfers[i];
 			if (transfer) {
 				libusb_cancel_transfer(transfer);
-				libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &(struct timeval){0, 0});
+			}
+		}
+		for (size_t i = 0; i < NUM_MAX_TRANSFERS; ++i) {
+			libusb_handle_events_timeout_completed(drvc->sr_ctx->libusb_ctx, &(struct timeval){0, 0}, NULL);
+			struct libusb_transfer *transfer = devc->transfers[i];
+			if (transfer) {
 				g_free(transfer->buffer);
 				libusb_free_transfer(transfer);
 			}
@@ -150,7 +154,7 @@ static int handle_events(int fd, int revents, void *cb_data)
 		std_session_send_df_end(sdi);
 	}
 
-	libusb_handle_events_timeout_completed(drvc->sr_ctx->libusb_ctx, &(struct timeval){0, 0}, &devc->acq_aborted);
+	libusb_handle_events_timeout_completed(drvc->sr_ctx->libusb_ctx, &(struct timeval){0, 0}, NULL);
 
 	return TRUE;
 }
@@ -184,8 +188,8 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 			1000 * devc->cur_limit_samples / devc->cur_samplerate
 	);
 
-	devc->per_transfer_duration = 500;
-	devc->per_transfer_nbytes = devc->cur_samplerate / SR_KHZ(1) * devc->cur_samplechannel / 8 * devc->per_transfer_duration /* ms */;
+	devc->per_transfer_duration = 125;
+	devc->per_transfer_nbytes = devc->per_transfer_duration * devc->cur_samplerate * devc->cur_samplechannel / 8 / SR_KHZ(1) /* ms */;
 
 	do {
 		struct libusb_transfer *transfer = libusb_alloc_transfer(0);
@@ -195,7 +199,7 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 		}
 		do {
 			devc->per_transfer_nbytes = (devc->per_transfer_nbytes + (2*16*1024-1)) & ~(2*16*1024-1);
-			devc->per_transfer_duration = devc->per_transfer_nbytes / (devc->cur_samplerate / SR_KHZ(1) * devc->cur_samplechannel / 8);
+			devc->per_transfer_duration = devc->per_transfer_nbytes * SR_KHZ(1) * 8 / (devc->cur_samplerate * devc->cur_samplechannel);
 			sr_dbg("Plan to receive %u bytes per %ums...", devc->per_transfer_nbytes, devc->per_transfer_duration);
 			
 			uint8_t *dev_buf = g_malloc(devc->per_transfer_nbytes);
@@ -207,10 +211,9 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 
 			libusb_fill_bulk_transfer(transfer, usb->devhdl, devc->model->ep_in,
 										dev_buf, devc->per_transfer_nbytes, NULL,
-										NULL, (TRANSFERS_DURATION_TOLERANCE + 1) * devc->per_transfer_duration);
+										NULL, 0);
 
 			ret = libusb_submit_transfer(transfer);
-			libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &(struct timeval){0, 0});
 			if (ret) {
 				g_free(transfer->buffer);
 				if (ret == LIBUSB_ERROR_NO_MEM) {
@@ -219,18 +222,22 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 					continue;
 				} else {
 					sr_err("Failed to submit transfer: %s!", libusb_error_name(ret));
+					libusb_free_transfer(transfer);
 					return SR_ERR_IO;
 				}
 			} else {
 				ret = libusb_cancel_transfer(transfer);
-				libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &(struct timeval){0, 0});
+				if (ret) {
+                    sr_dbg("Failed to cancel transfer: %s!", libusb_error_name(ret));
+                }
+                libusb_handle_events_timeout_completed(drvc->sr_ctx->libusb_ctx, &(struct timeval){3, 0}, NULL);
 				g_free(transfer->buffer);
 
 				devc->per_transfer_nbytes >>= 1;
 				devc->per_transfer_duration = devc->per_transfer_nbytes / (devc->cur_samplerate / SR_KHZ(1) * devc->cur_samplechannel / 8);
 				break;
 			}
-		} while (devc->per_transfer_nbytes > 128*1024); // 128kiB > 500ms * 1MHZ * 2ch
+		} while (devc->per_transfer_nbytes > 32*1024); // 32kiB > 125ms * 1MHZ * 2ch
 		libusb_free_transfer(transfer);
 		sr_info("Nice plan! :) => %u bytes per %ums.", devc->per_transfer_nbytes, devc->per_transfer_duration);
 	} while (0);
@@ -244,7 +251,7 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 
 	sr_session_source_add(sdi->session, -1 * (size_t)drvc->sr_ctx->libusb_ctx, 0, (devc->per_transfer_duration / 2)?:1, handle_events, (void *)sdi);
 
-	for (size_t reveiving_nbytes = 0; devc->num_transfers_used < NUM_MAX_TRANSFERS && reveiving_nbytes < devc->samples_need_nbytes; reveiving_nbytes += devc->per_transfer_nbytes)
+	while (devc->num_transfers_used < NUM_MAX_TRANSFERS && devc->samples_got_nbytes + devc->num_transfers_used * devc->per_transfer_nbytes < devc->samples_need_nbytes)
 	{
 		uint8_t *dev_buf = g_malloc(devc->per_transfer_nbytes);
 		if (!dev_buf) {

From ab035a82768a6abcf88aa1b200f130fd20a03fa1 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Sun, 16 Mar 2025 19:41:38 +0800
Subject: [PATCH 17/36] sipeed-slogic-analyzer: fix: transfers not consumed
 from the end, so just use NUM_MAX_TRANSFERS instead of num_transfers_used

---
 src/hardware/sipeed-slogic-analyzer/protocol.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index 1166658ad..6384ca85f 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -39,7 +39,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 	if (devc->acq_aborted == 1)
 		return;
 
-	sr_spew("Transfer[%d] status: %d(%s)", std_u64_idx(g_variant_new_uint64((uint64_t)transfer), (uint64_t*)devc->transfers, devc->num_transfers_used),
+	sr_spew("Transfer[%d] status: %d(%s)", std_u64_idx(g_variant_new_uint64((uint64_t)transfer), (uint64_t*)devc->transfers, NUM_MAX_TRANSFERS),
 		transfer->status, libusb_error_name(transfer->status));
 	switch (transfer->status) {
 		case LIBUSB_TRANSFER_COMPLETED: 

From 49fb27db0ffb743a22c8b1ab01ef30f61ef3ba3a Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Mon, 17 Mar 2025 15:57:49 +0800
Subject: [PATCH 18/36] sipeed-slogic-analyzer: chore: add udev rules for
 slogic

---
 contrib/60-libsigrok.rules | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/contrib/60-libsigrok.rules b/contrib/60-libsigrok.rules
index 716178039..56e05a704 100644
--- a/contrib/60-libsigrok.rules
+++ b/contrib/60-libsigrok.rules
@@ -307,6 +307,13 @@ ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="608e", ENV{ID_SIGROK}="1"
 # sigrok usb-c-grok
 ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="608f", ENV{ID_SIGROK}="1"
 
+
+# Sipeed(359f) Slogic series
+# 0300: Slogic Lite 8
+# 3031: Slogic Basic 16 U3
+ATTRS{idVendor}=="359f", ATTRS{idProduct}=="0300", ENV{ID_SIGROK}="1"
+ATTRS{idVendor}=="359f", ATTRS{idProduct}=="3031", ENV{ID_SIGROK}="1"
+
 # SiLabs CP210x (USB CDC) UART bridge, used (among others) in:
 # CEM DT-8852
 # Manson HCS-3202

From d610504929bd94880e1fb0b5822436db631475c8 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Mon, 17 Mar 2025 16:05:50 +0800
Subject: [PATCH 19/36] sipeed-slogic-analyzer: fix: add libusb dependency

---
 configure.ac | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 7e6999c08..7ad053f10 100644
--- a/configure.ac
+++ b/configure.ac
@@ -385,7 +385,7 @@ SR_DRIVER([serial DMM], [serial-dmm], [serial_comm])
 SR_DRIVER([serial LCR], [serial-lcr], [serial_comm])
 SR_DRIVER([SIGLENT SDL10x0], [siglent-sdl10x0])
 SR_DRIVER([Siglent SDS], [siglent-sds])
-SR_DRIVER([Sipeed Slogic Analyzer], [sipeed-slogic-analyzer])
+SR_DRIVER([Sipeed Slogic Analyzer], [sipeed-slogic-analyzer], [libusb])
 SR_DRIVER([Sysclk LWLA], [sysclk-lwla], [libusb])
 SR_DRIVER([Sysclk SLA5032], [sysclk-sla5032], [libusb])
 SR_DRIVER([Teleinfo], [teleinfo], [serial_comm])

From 42fc14f3d24791fe2a31c80e63d107b60f595822 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Mon, 17 Mar 2025 17:57:50 +0800
Subject: [PATCH 20/36] sipeed-slogic-analyzer: feat: support sample rate and
 channel configuration

---
 src/hardware/sipeed-slogic-analyzer/api.c | 99 ++++++++++++++++++++++-
 1 file changed, 97 insertions(+), 2 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
index 597f47734..398019525 100644
--- a/src/hardware/sipeed-slogic-analyzer/api.c
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -541,14 +541,105 @@ static void slogic_lite_8_submit_raw_data(void *data, size_t len, const struct s
 #define SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ 	0x00
 #define SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE 	0x01
 
+#define SLOGIC_BASIC_16_R32_CTRL 	0x0004
+#define SLOGIC_BASIC_16_R32_FLAG 	0x0008
+#define SLOGIC_BASIC_16_R32_AUX 	0x000c
+
 static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi) {
+	struct dev_context *devc = sdi->priv;
+	const uint8_t cmd_derst[] = {0x00, 0x00, 0x00, 0x00};
 	const uint8_t cmd_run[] = {0x01, 0x00, 0x00, 0x00};
-	return slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, 0x0004, 0x0000, ARRAY_AND_SIZE(cmd_run), 500);
+	uint8_t cmd_aux_channel[8] = {0x01, 0x00, 0x00, 0x00}; // configure channel
+	uint8_t cmd_aux_samplerate[12] = {0x02, 0x00, 0x00, 0x00}; // configure samplerate
+
+	slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_CTRL, 0x0000, ARRAY_AND_SIZE(cmd_derst), 500);
+
+	{
+		uint8_t *cmd_aux = cmd_aux_channel;
+		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
+		do {
+			slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
+			sr_dbg("read aux channel.");
+		} while (!(cmd_aux[2] & 0x01));
+		sr_dbg("channel length: %u.", (*(uint16_t*)cmd_aux)>>8);
+		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);
+
+		// sr_dbg("aux: %u %u %u %u %08x.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], *(uint32_t*)(cmd_aux+4));
+
+		*(uint32_t*)(cmd_aux+4) = (1 << devc->cur_samplechannel) - 1;
+
+		// sr_dbg("aux: %u %u %u %u %08x.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], *(uint32_t*)(cmd_aux+4));
+		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);
+
+		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);
+		sr_dbg("aux: %u %u %u %u %08x.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], *(uint32_t*)(cmd_aux+4));
+
+		if ((1 << devc->cur_samplechannel) - 1 != *(uint32_t*)(cmd_aux+4)) {
+			sr_dbg("Failed to configure sample channel.");
+		} else {
+			sr_dbg("Succeed to configure sample channel.");
+		}
+	}
+
+
+	{
+		uint8_t *cmd_aux = cmd_aux_samplerate;
+		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
+		do {
+			slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
+			sr_dbg("read aux samplerate.");
+		} while (!(cmd_aux[2] & 0x01));
+		sr_dbg("samplerate length: %u.", (*(uint16_t*)cmd_aux)>>8);
+		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);
+
+		// sr_dbg("aux: %u %u %u %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], *(uint64_t*)(cmd_aux+4));
+
+		*(uint64_t*)(cmd_aux+4) = devc->cur_samplerate;
+
+		// sr_dbg("aux: %u %u %u %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], *(uint64_t*)(cmd_aux+4));
+		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);
+
+		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);
+		sr_dbg("aux: %u %u %u %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], *(uint64_t*)(cmd_aux+4));
+
+		if (devc->cur_samplerate != *(uint64_t*)(cmd_aux+4)) {
+			sr_dbg("Failed to configure samplerate.");
+		} else {
+			sr_dbg("Succeed to configure samplerate.");
+		}
+	}
+
+	return slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_CTRL, 0x0000, ARRAY_AND_SIZE(cmd_run), 500);
 }
 
 static int slogic_basic_16_remote_stop(const struct sr_dev_inst *sdi) {
 	const uint8_t cmd_rst[] = {0x02, 0x00, 0x00, 0x00};
-	return slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, 0x0004, 0x0000, ARRAY_AND_SIZE(cmd_rst), 500);
+	return slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_CTRL, 0x0000, ARRAY_AND_SIZE(cmd_rst), 500);
+}
+// reverse bits（MSB <-> LSB）
+static uint8_t reverse_bits(uint8_t x) {
+    x = ((x & 0x55) << 1) | ((x >> 1) & 0x55); // 交换相邻的1位
+    x = ((x & 0x33) << 2) | ((x >> 2) & 0x33); // 交换相邻的2位
+    x = ((x & 0x0F) << 4) | ((x >> 4) & 0x0F); // 交换相邻的4位
+    return x;
+}
+
+static void transpose_8x8_swar(uint8_t A[8], int n, uint8_t B[8]) {
+    // 将 8x8 矩阵的每一行加载到 64 位寄存器中
+    uint64_t src = 0;
+    for (int i = 0; i < n; i++) {
+        src |= (uint64_t)reverse_bits(A[i]) << (8 * i);
+    }
+
+    // SWAR 分阶段转置
+    src = (src & 0xAA55AA55AA55AA55) | ((src & 0x00AA00AA00AA00AA) << 7) | ((src >> 7) & 0x00AA00AA00AA00AA);
+    src = (src & 0xCCCC3333CCCC3333) | ((src & 0x0000CCCC0000CCCC) << 14) | ((src >> 14) & 0x0000CCCC0000CCCC);
+    src = (src & 0xF0F0F0F00F0F0F0F) | ((src & 0x00000000F0F0F0F0) << 28) | ((src >> 28) & 0x00000000F0F0F0F0);
+
+    // 将转置后的结果存储到 B 数组中
+    for (int i = 0; i < 8; i++) {
+        B[i] = (src >> (8 * i)) & 0xFF;
+    }
 }
 
 static void slogic_basic_16_submit_raw_data(void *data, size_t len, const struct sr_dev_inst *sdi) {
@@ -558,6 +649,10 @@ static void slogic_basic_16_submit_raw_data(void *data, size_t len, const struct
 	uint8_t *ptr = g_malloc(length);
 
 	for(size_t i=0; i<len; i+=devc->cur_samplechannel) {
+		if (devc->cur_samplechannel <= 8) {
+			transpose_8x8_swar(data + i, devc->cur_samplechannel, ptr + i / devc->cur_samplechannel * 8);
+			continue;
+		}
 		for(size_t j=0; j<8; j++) {
 			#define B(n) (((((uint8_t *)data)[i+(n)] >> 7-j) & 0x1) << ((n)%8))
 			switch (devc->cur_samplechannel) {

From 7477b5deba312a11436923713052c3c9dfa1e3da Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Wed, 19 Mar 2025 14:49:22 +0800
Subject: [PATCH 21/36] sipeed-slogic-analyzer: feat: update protocol
 configuration and debug info and make start_time accurate

---
 src/hardware/sipeed-slogic-analyzer/api.c     | 20 +++++++++----------
 .../sipeed-slogic-analyzer/protocol.c         |  6 +++---
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
index 398019525..0fbe4bdf5 100644
--- a/src/hardware/sipeed-slogic-analyzer/api.c
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -559,20 +559,20 @@ static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi) {
 		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
 		do {
 			slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
-			sr_dbg("read aux channel.");
+			sr_dbg("read aux channel: %08x.", ((uint32_t*)cmd_aux)[0]);
 		} while (!(cmd_aux[2] & 0x01));
 		sr_dbg("channel length: %u.", (*(uint16_t*)cmd_aux)>>8);
 		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);
 
-		// sr_dbg("aux: %u %u %u %u %08x.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], *(uint32_t*)(cmd_aux+4));
+		// sr_dbg("aux: %u %u %u %u %08x.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint32_t*)(cmd_aux+4))[0]);
 
 		*(uint32_t*)(cmd_aux+4) = (1 << devc->cur_samplechannel) - 1;
 
-		// sr_dbg("aux: %u %u %u %u %08x.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], *(uint32_t*)(cmd_aux+4));
+		// sr_dbg("aux: %u %u %u %u %08x.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint32_t*)(cmd_aux+4))[0]);
 		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);
 
 		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);
-		sr_dbg("aux: %u %u %u %u %08x.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], *(uint32_t*)(cmd_aux+4));
+		sr_dbg("aux: %u %u %u %u %08x.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint32_t*)(cmd_aux+4))[0]);
 
 		if ((1 << devc->cur_samplechannel) - 1 != *(uint32_t*)(cmd_aux+4)) {
 			sr_dbg("Failed to configure sample channel.");
@@ -587,22 +587,22 @@ static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi) {
 		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
 		do {
 			slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
-			sr_dbg("read aux samplerate.");
+			sr_dbg("read aux samplerate: %08x.", ((uint32_t*)cmd_aux)[0]);
 		} while (!(cmd_aux[2] & 0x01));
 		sr_dbg("samplerate length: %u.", (*(uint16_t*)cmd_aux)>>8);
 		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);
 
-		// sr_dbg("aux: %u %u %u %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], *(uint64_t*)(cmd_aux+4));
+		sr_dbg("aux: %u %u %u %u %x %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint16_t*)(cmd_aux+4))[0], ((uint16_t*)(cmd_aux+4))[1], ((uint32_t*)(cmd_aux+4))[1]);
 
-		*(uint64_t*)(cmd_aux+4) = devc->cur_samplerate;
+		// ((uint32_t*)(cmd_aux+4))[0] = devc->cur_samplerate;
 
-		// sr_dbg("aux: %u %u %u %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], *(uint64_t*)(cmd_aux+4));
+		sr_dbg("aux: %u %u %u %u %x %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint16_t*)(cmd_aux+4))[0], ((uint16_t*)(cmd_aux+4))[1], ((uint32_t*)(cmd_aux+4))[1]);
 		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);
 
 		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);
-		sr_dbg("aux: %u %u %u %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], *(uint64_t*)(cmd_aux+4));
+		sr_dbg("aux: %u %u %u %u %x %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint16_t*)(cmd_aux+4))[0], ((uint16_t*)(cmd_aux+4))[1], ((uint32_t*)(cmd_aux+4))[1]);
 
-		if (devc->cur_samplerate != *(uint64_t*)(cmd_aux+4)) {
+		if (1 /* devc->cur_samplerate != ((uint32_t*)(cmd_aux+4))[0] */) {
 			sr_dbg("Failed to configure samplerate.");
 		} else {
 			sr_dbg("Succeed to configure samplerate.");
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index 6384ca85f..68f932458 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -286,9 +286,6 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	std_session_send_df_header(sdi);
 	std_session_send_df_frame_begin(sdi);
 
-	devc->transfers_reached_time_start = g_get_monotonic_time();
-	devc->transfers_reached_time_latest = devc->transfers_reached_time_start;
-
 	if (!devc->num_transfers_used) {
 		sipeed_slogic_acquisition_stop(sdi);
 		return SR_OK;
@@ -299,6 +296,9 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 		return ret;
 	}
 
+	devc->transfers_reached_time_start = g_get_monotonic_time();
+	devc->transfers_reached_time_latest = devc->transfers_reached_time_start;
+
 	return SR_OK;
 }
 

From f77972bbdc76a51adde747a57e1b9639c818226e Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Wed, 19 Mar 2025 16:57:13 +0800
Subject: [PATCH 22/36] sipeed-slogic-analyzer: feat: separate
 sr_session_send(sdi, &packet) from receive_transfer handler to ensure usb
 work continuously

---
 .../sipeed-slogic-analyzer/protocol.c         | 57 ++++++++++++++++++-
 .../sipeed-slogic-analyzer/protocol.h         |  2 +
 2 files changed, 56 insertions(+), 3 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index 68f932458..96f44e9ab 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -66,11 +66,21 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 
 			/* TODO: move out submit to ensure continuous transfers */
 			if (devc->cur_pattern_mode_idx != PATTERN_MODE_TEST_MAX_SPEED) {
-				uint8_t * d = transfer->buffer;
+				uint8_t *d = transfer->buffer;
 				size_t len = transfer->actual_length;
 				// sr_dbg("HEAD: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
 				// 	d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
-				devc->model->submit_raw_data(d, len, sdi);
+				// devc->model->submit_raw_data(d, len, sdi);
+
+				uint8_t *ptr = g_malloc(devc->per_transfer_nbytes);
+				if (!ptr) {
+					sr_err("Failed to allocate memory: %u bytes!", devc->per_transfer_nbytes);
+					sipeed_slogic_acquisition_stop(sdi);
+					break;
+				}
+				transfer->buffer = ptr;
+				GArray *array = g_array_new_take(d, len, FALSE, 1);
+				g_async_queue_push(devc->raw_data_queue, array);
 			}
 
 			devc->num_transfers_used -= 1;
@@ -151,7 +161,6 @@ static int handle_events(int fd, int revents, void *cb_data)
 		sr_info("Bulk in %u/%u bytes with %u transfers.", devc->samples_got_nbytes, devc->samples_need_nbytes, devc->num_transfers_completed);
 
 		sr_session_source_remove(sdi->session, -1 * (size_t)drvc->sr_ctx->libusb_ctx);
-		std_session_send_df_end(sdi);
 	}
 
 	libusb_handle_events_timeout_completed(drvc->sr_ctx->libusb_ctx, &(struct timeval){0, 0}, NULL);
@@ -159,6 +168,45 @@ static int handle_events(int fd, int revents, void *cb_data)
 	return TRUE;
 }
 
+static int handle_data_events(int fd, int revents, void *cb_data)
+{
+	struct sr_dev_inst *sdi;
+	struct sr_dev_driver *di;
+	struct dev_context *devc;
+	struct drv_context *drvc;
+
+	(void)fd;
+	(void)revents;
+
+	sdi = cb_data;
+	devc = sdi->priv;
+	di = sdi->driver;
+	drvc = di->context;
+
+	// sr_spew("handle_data_events enter");
+
+	do {
+		if (g_async_queue_length(devc->raw_data_queue) == 0)
+			break;
+		GArray *array = g_async_queue_try_pop(devc->raw_data_queue);
+		if (array != NULL) {
+			devc->model->submit_raw_data(array->data, array->len, sdi);
+			g_array_unref(array);
+		}
+	} while (devc->acq_aborted);
+
+	if (devc->acq_aborted) {
+		std_session_send_df_end(sdi);
+
+		sr_session_source_remove(sdi->session, -1 * (size_t)devc->raw_data_queue);
+
+		g_async_queue_unref(devc->raw_data_queue);
+		devc->raw_data_queue = NULL;
+	}
+
+	return TRUE;
+}
+
 SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 {
 	struct sr_dev_driver *di;
@@ -248,7 +296,9 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	devc->num_transfers_completed = 0;
 	memset(devc->transfers, 0, sizeof(devc->transfers));
 	devc->transfers_reached_nbytes = 0;
+	devc->raw_data_queue = g_async_queue_new();
 
+	sr_session_source_add(sdi->session, -1 * (size_t)devc->raw_data_queue, 0, devc->per_transfer_duration, handle_data_events, (void *)sdi);
 	sr_session_source_add(sdi->session, -1 * (size_t)drvc->sr_ctx->libusb_ctx, 0, (devc->per_transfer_duration / 2)?:1, handle_events, (void *)sdi);
 
 	while (devc->num_transfers_used < NUM_MAX_TRANSFERS && devc->samples_got_nbytes + devc->num_transfers_used * devc->per_transfer_nbytes < devc->samples_need_nbytes)
@@ -293,6 +343,7 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 
 	if ((ret = devc->model->operation.remote_run(sdi)) < 0) {
 		sr_err("Unhandled `CMD_RUN`");
+		sipeed_slogic_acquisition_stop(sdi);
 		return ret;
 	}
 
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
index 5e34b946c..6077824a9 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
@@ -85,6 +85,8 @@ struct dev_context {
 		uint64_t transfers_reached_nbytes_latest; /* real received bytes this transfer */
 		int64_t transfers_reached_time_start;
 		int64_t transfers_reached_time_latest;
+
+		GAsyncQueue *raw_data_queue;
 	}; // usb
 
 	int acq_aborted;

From 7f2cdda9cee90c1cfd6e31023bd750162fcf7b8a Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Wed, 19 Mar 2025 18:24:38 +0800
Subject: [PATCH 23/36] sipeed-slogic-analyzer: fix: more lenient latency
 tolerance

---
 src/hardware/sipeed-slogic-analyzer/protocol.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
index 6077824a9..3c887201c 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
@@ -30,7 +30,7 @@
 
 #define USB_VID_SIPEED UINT16_C(0x359f)
 #define NUM_MAX_TRANSFERS 64
-#define TRANSFERS_DURATION_TOLERANCE 0.05f
+#define TRANSFERS_DURATION_TOLERANCE 0.50f
 
 enum {
 	PATTERN_MODE_NOMAL,

From a152a1ee9dea2afa168b8bdc35f084ef86d17310 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Thu, 20 Mar 2025 10:25:18 +0800
Subject: [PATCH 24/36] sipeed-slogic-analyzer: fix: has g_byte_array_new_take
 support since 2.32, but g_array_new_take from 2.76

---
 src/hardware/sipeed-slogic-analyzer/protocol.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index 96f44e9ab..e45a444b7 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -79,7 +79,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 					break;
 				}
 				transfer->buffer = ptr;
-				GArray *array = g_array_new_take(d, len, FALSE, 1);
+				GByteArray *array = g_byte_array_new_take(d, len);
 				g_async_queue_push(devc->raw_data_queue, array);
 			}
 
@@ -188,10 +188,10 @@ static int handle_data_events(int fd, int revents, void *cb_data)
 	do {
 		if (g_async_queue_length(devc->raw_data_queue) == 0)
 			break;
-		GArray *array = g_async_queue_try_pop(devc->raw_data_queue);
+		GByteArray *array = g_async_queue_try_pop(devc->raw_data_queue);
 		if (array != NULL) {
 			devc->model->submit_raw_data(array->data, array->len, sdi);
-			g_array_unref(array);
+			g_byte_array_unref(array);
 		}
 	} while (devc->acq_aborted);
 

From 31e59e9a90fbb4ffce0c910c78736bba4d887309 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Thu, 20 Mar 2025 10:37:13 +0800
Subject: [PATCH 25/36] sipeed-slogic-analyzer: fix: limit retry times to not
 block in retrys forever

---
 src/hardware/sipeed-slogic-analyzer/api.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
index 0fbe4bdf5..3c4fcaa1e 100644
--- a/src/hardware/sipeed-slogic-analyzer/api.c
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -555,11 +555,15 @@ static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi) {
 	slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_CTRL, 0x0000, ARRAY_AND_SIZE(cmd_derst), 500);
 
 	{
+		size_t retry = 0;
 		uint8_t *cmd_aux = cmd_aux_channel;
 		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
 		do {
 			slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
-			sr_dbg("read aux channel: %08x.", ((uint32_t*)cmd_aux)[0]);
+			sr_dbg("[%u]read aux channel: %08x.", retry, ((uint32_t*)cmd_aux)[0]);
+			retry += 1;
+			if (retry > 5)
+				return SR_ERR_TIMEOUT;
 		} while (!(cmd_aux[2] & 0x01));
 		sr_dbg("channel length: %u.", (*(uint16_t*)cmd_aux)>>8);
 		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);
@@ -583,11 +587,15 @@ static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi) {
 
 
 	{
+		size_t retry = 0;
 		uint8_t *cmd_aux = cmd_aux_samplerate;
 		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
 		do {
 			slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
-			sr_dbg("read aux samplerate: %08x.", ((uint32_t*)cmd_aux)[0]);
+			sr_dbg("[%u]read aux samplerate: %08x.", retry, ((uint32_t*)cmd_aux)[0]);
+			retry += 1;
+			if (retry > 5)
+				return SR_ERR_TIMEOUT;
 		} while (!(cmd_aux[2] & 0x01));
 		sr_dbg("samplerate length: %u.", (*(uint16_t*)cmd_aux)>>8);
 		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);

From 619eb2d8066ff8ea324eb9c75f598aace48af401 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Thu, 20 Mar 2025 14:49:32 +0800
Subject: [PATCH 26/36] sipeed-slogic-analyzer: feat: switch back to 5%
 tolerance and use a continuous count to determine real timeout

---
 src/hardware/sipeed-slogic-analyzer/protocol.c | 17 ++++++++++++-----
 src/hardware/sipeed-slogic-analyzer/protocol.h |  3 ++-
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index e45a444b7..6f01219db 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -109,11 +109,18 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 	}
 
 	if (devc->num_transfers_completed && (double)transfers_reached_duration / SR_KHZ(1) > (TRANSFERS_DURATION_TOLERANCE + 1) * devc->per_transfer_duration) {
-		sr_err("Timeout %.3fms!!! Reach duration limit: %.3f(%u+%.1f%%) except first one.",
-			(double)transfers_reached_duration / SR_KHZ(1),
-			(TRANSFERS_DURATION_TOLERANCE + 1) * devc->per_transfer_duration, devc->per_transfer_duration, TRANSFERS_DURATION_TOLERANCE * 100
-		);
-		devc->num_transfers_used = 0;
+		devc->timeout_count += 1;
+		if (devc->timeout_count > devc->num_transfers_used) {
+			sr_err("Timeout %.3fms!!! Reach duration limit: %.3f(%u+%.1f%%), %.3f > %.3f(%u+%.1f%%)(total) except first one.",
+				(double)transfers_reached_duration / SR_KHZ(1),
+				(TRANSFERS_DURATION_TOLERANCE + 1) * devc->per_transfer_duration, devc->per_transfer_duration, TRANSFERS_DURATION_TOLERANCE * 100,
+				(double)(transfers_reached_time_now - devc->transfers_reached_time_start) / SR_KHZ(1),
+				(TRANSFERS_DURATION_TOLERANCE + 1) * devc->per_transfer_duration * (devc->num_transfers_completed + 1), devc->per_transfer_duration * (devc->num_transfers_completed + 1), TRANSFERS_DURATION_TOLERANCE * 100
+			);
+			devc->num_transfers_used = 0;
+		}
+	} else {
+		devc->timeout_count = 0;
 	}
 
 	if (devc->num_transfers_used == 0) {
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
index 3c887201c..f53483ada 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
@@ -30,7 +30,7 @@
 
 #define USB_VID_SIPEED UINT16_C(0x359f)
 #define NUM_MAX_TRANSFERS 64
-#define TRANSFERS_DURATION_TOLERANCE 0.50f
+#define TRANSFERS_DURATION_TOLERANCE 0.05f
 
 enum {
 	PATTERN_MODE_NOMAL,
@@ -87,6 +87,7 @@ struct dev_context {
 		int64_t transfers_reached_time_latest;
 
 		GAsyncQueue *raw_data_queue;
+		uint64_t timeout_count;
 	}; // usb
 
 	int acq_aborted;

From ecbcf2703ff58ce00c7b6f77f9bf24dea01133c2 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Thu, 20 Mar 2025 15:31:26 +0800
Subject: [PATCH 27/36] sipeed-slogic-analyzer: refactor: simplify and reuse
 data packet format

---
 src/hardware/sipeed-slogic-analyzer/api.c | 104 +++++-----------------
 1 file changed, 20 insertions(+), 84 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
index 3c4fcaa1e..66712401b 100644
--- a/src/hardware/sipeed-slogic-analyzer/api.c
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -503,22 +503,14 @@ static void slogic_lite_8_submit_raw_data(void *data, size_t len, const struct s
 	struct dev_context *devc = sdi->priv;
 
 	size_t length = len * (8/devc->cur_samplechannel);
-	uint8_t *ptr = g_malloc(length);
-
-	for(size_t i=0; i<len; i+=devc->cur_samplechannel) {
-		for(size_t j=0; j<8; j++) {
-			ptr[i*(8/devc->cur_samplechannel)+j] = (((uint8_t *)data)[i+j/(8/devc->cur_samplechannel)] >> (j%(8/devc->cur_samplechannel) * devc->cur_samplechannel)) & ((1<<devc->cur_samplechannel)-1);
-			// switch (devc->cur_samplechannel) {
-			// case 8:
-			// 	ptr[i*1+j] = (((uint8_t *)data)[i+j/1] >> (j%1 * 8)) & 0xff;
-			// break;
-			// case 4:
-			// 	ptr[i*2+j] = (((uint8_t *)data)[i+j/2] >> (j%2 * 4)) & 0xf;
-			// break;
-			// case 2:
-			// 	ptr[i*4+j] = (((uint8_t *)data)[i+j/4] >> (j%4 * 2)) & 0x3;
-			// break;
-			// }
+	uint8_t *ptr = data;
+
+	if (devc->cur_samplechannel < 8) {
+		ptr = g_malloc(length);
+		for(size_t i=0; i<len; i+=devc->cur_samplechannel) {
+			for(size_t j=0; j<8; j++) {
+				ptr[i*(8/devc->cur_samplechannel)+j] = (((uint8_t *)data)[i+j/(8/devc->cur_samplechannel)] >> (j%(8/devc->cur_samplechannel) * devc->cur_samplechannel)) & ((1<<devc->cur_samplechannel)-1);
+			}
 		}
 	}
 
@@ -531,7 +523,8 @@ static void slogic_lite_8_submit_raw_data(void *data, size_t len, const struct s
 		}
 	});
 
-	g_free(ptr);
+	if (devc->cur_samplechannel < 8)
+		g_free(ptr);
 }
 /* Slogic Lite 8 end */
 
@@ -624,79 +617,22 @@ static int slogic_basic_16_remote_stop(const struct sr_dev_inst *sdi) {
 	const uint8_t cmd_rst[] = {0x02, 0x00, 0x00, 0x00};
 	return slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_CTRL, 0x0000, ARRAY_AND_SIZE(cmd_rst), 500);
 }
-// reverse bits（MSB <-> LSB）
-static uint8_t reverse_bits(uint8_t x) {
-    x = ((x & 0x55) << 1) | ((x >> 1) & 0x55); // 交换相邻的1位
-    x = ((x & 0x33) << 2) | ((x >> 2) & 0x33); // 交换相邻的2位
-    x = ((x & 0x0F) << 4) | ((x >> 4) & 0x0F); // 交换相邻的4位
-    return x;
-}
-
-static void transpose_8x8_swar(uint8_t A[8], int n, uint8_t B[8]) {
-    // 将 8x8 矩阵的每一行加载到 64 位寄存器中
-    uint64_t src = 0;
-    for (int i = 0; i < n; i++) {
-        src |= (uint64_t)reverse_bits(A[i]) << (8 * i);
-    }
-
-    // SWAR 分阶段转置
-    src = (src & 0xAA55AA55AA55AA55) | ((src & 0x00AA00AA00AA00AA) << 7) | ((src >> 7) & 0x00AA00AA00AA00AA);
-    src = (src & 0xCCCC3333CCCC3333) | ((src & 0x0000CCCC0000CCCC) << 14) | ((src >> 14) & 0x0000CCCC0000CCCC);
-    src = (src & 0xF0F0F0F00F0F0F0F) | ((src & 0x00000000F0F0F0F0) << 28) | ((src >> 28) & 0x00000000F0F0F0F0);
-
-    // 将转置后的结果存储到 B 数组中
-    for (int i = 0; i < 8; i++) {
-        B[i] = (src >> (8 * i)) & 0xFF;
-    }
-}
 
 static void slogic_basic_16_submit_raw_data(void *data, size_t len, const struct sr_dev_inst *sdi) {
 	struct dev_context *devc = sdi->priv;
 
-	size_t length = len * ((devc->cur_samplechannel>=8)?:(8/devc->cur_samplechannel));
-	uint8_t *ptr = g_malloc(length);
-
-	for(size_t i=0; i<len; i+=devc->cur_samplechannel) {
-		if (devc->cur_samplechannel <= 8) {
-			transpose_8x8_swar(data + i, devc->cur_samplechannel, ptr + i / devc->cur_samplechannel * 8);
-			continue;
-		}
-		for(size_t j=0; j<8; j++) {
-			#define B(n) (((((uint8_t *)data)[i+(n)] >> 7-j) & 0x1) << ((n)%8))
-			switch (devc->cur_samplechannel) {
-			case 16:
-				ptr[i+j*2+0] =
-					B(0)|B(1)|B(2)|B(3)|B(4)|B(5)|B(6)|B(7);
-				ptr[i+j*2+1] =
-					B(8)|B(9)|B(10)|B(11)|B(12)|B(13)|B(14)|B(15);
-			break;
-			case 8:
-				ptr[i+j] =
-					B(0)|B(1)|B(2)|B(3)|B(4)|B(5)|B(6)|B(7);
-			break;
-			case 4:
-				ptr[i*2+j] =
-					B(0)|B(1)|B(2)|B(3);
-			break;
-			case 2:
-				ptr[i*4+j] =
-					B(0)|B(1);
-			break;
+	if (devc->cur_samplechannel < 8) {
+		slogic_lite_8_submit_raw_data(data, len, sdi);
+	} else {
+		sr_session_send(sdi, &(struct sr_datafeed_packet) {
+			.type = SR_DF_LOGIC,
+			.payload = &(struct sr_datafeed_logic) {
+				.length = len,
+				.unitsize = (devc->cur_samplechannel + 7)/8,
+				.data = data,
 			}
-			#undef B
-		}
+		});
 	}
-
-	sr_session_send(sdi, &(struct sr_datafeed_packet) {
-		.type = SR_DF_LOGIC,
-		.payload = &(struct sr_datafeed_logic) {
-			.length = length,
-			.unitsize = (devc->cur_samplechannel + 7)/8,
-			.data = ptr,
-		}
-	});
-
-	g_free(ptr);
 }
 /* Slogic Basic 16 end */
 

From c45edeaa699555fdee0bdd9831970a1ce6771058 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Thu, 20 Mar 2025 15:54:13 +0800
Subject: [PATCH 28/36] sipeed-slogic-analyzer: perf: use GThread for
 raw_data_handle to not distrub handle_events

---
 .../sipeed-slogic-analyzer/protocol.c         | 47 ++++++++++---------
 .../sipeed-slogic-analyzer/protocol.h         |  1 +
 2 files changed, 25 insertions(+), 23 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index 6f01219db..3814b4143 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -147,6 +147,10 @@ static int handle_events(int fd, int revents, void *cb_data)
 
 	//sr_spew("handle_events enter");
 
+	if (!devc->raw_data_handle_thread) {
+		sipeed_slogic_acquisition_stop(sdi);
+	}
+
 	if (devc->acq_aborted) {
 		for (size_t i = 0; i < NUM_MAX_TRANSFERS; ++i) {
 			struct libusb_transfer *transfer = devc->transfers[i];
@@ -168,6 +172,7 @@ static int handle_events(int fd, int revents, void *cb_data)
 		sr_info("Bulk in %u/%u bytes with %u transfers.", devc->samples_got_nbytes, devc->samples_need_nbytes, devc->num_transfers_completed);
 
 		sr_session_source_remove(sdi->session, -1 * (size_t)drvc->sr_ctx->libusb_ctx);
+		g_thread_join(devc->raw_data_handle_thread);
 	}
 
 	libusb_handle_events_timeout_completed(drvc->sr_ctx->libusb_ctx, &(struct timeval){0, 0}, NULL);
@@ -175,43 +180,39 @@ static int handle_events(int fd, int revents, void *cb_data)
 	return TRUE;
 }
 
-static int handle_data_events(int fd, int revents, void *cb_data)
+static gpointer raw_data_handle_thread_func(gpointer user_data)
 {
 	struct sr_dev_inst *sdi;
 	struct sr_dev_driver *di;
 	struct dev_context *devc;
 	struct drv_context *drvc;
 
-	(void)fd;
-	(void)revents;
-
-	sdi = cb_data;
+	sdi = user_data;
 	devc = sdi->priv;
 	di = sdi->driver;
 	drvc = di->context;
 
-	// sr_spew("handle_data_events enter");
+	while (1) {
+		do {
+			if (g_async_queue_length(devc->raw_data_queue) == 0)
+				break;
+			GByteArray *array = g_async_queue_try_pop(devc->raw_data_queue);
+			if (array != NULL) {
+				devc->model->submit_raw_data(array->data, array->len, sdi);
+				g_byte_array_unref(array);
+			}
+		} while (devc->acq_aborted);
 
-	do {
-		if (g_async_queue_length(devc->raw_data_queue) == 0)
+		if (devc->acq_aborted && g_async_queue_length(devc->raw_data_queue) == 0) {
+			std_session_send_df_end(sdi);
+
+			g_async_queue_unref(devc->raw_data_queue);
+			devc->raw_data_queue = NULL;
 			break;
-		GByteArray *array = g_async_queue_try_pop(devc->raw_data_queue);
-		if (array != NULL) {
-			devc->model->submit_raw_data(array->data, array->len, sdi);
-			g_byte_array_unref(array);
 		}
-	} while (devc->acq_aborted);
-
-	if (devc->acq_aborted) {
-		std_session_send_df_end(sdi);
-
-		sr_session_source_remove(sdi->session, -1 * (size_t)devc->raw_data_queue);
-
-		g_async_queue_unref(devc->raw_data_queue);
-		devc->raw_data_queue = NULL;
 	}
 
-	return TRUE;
+	return NULL;
 }
 
 SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
@@ -304,8 +305,8 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	memset(devc->transfers, 0, sizeof(devc->transfers));
 	devc->transfers_reached_nbytes = 0;
 	devc->raw_data_queue = g_async_queue_new();
+	devc->raw_data_handle_thread = g_thread_new("raw_data_handle_thread", raw_data_handle_thread_func, sdi);
 
-	sr_session_source_add(sdi->session, -1 * (size_t)devc->raw_data_queue, 0, devc->per_transfer_duration, handle_data_events, (void *)sdi);
 	sr_session_source_add(sdi->session, -1 * (size_t)drvc->sr_ctx->libusb_ctx, 0, (devc->per_transfer_duration / 2)?:1, handle_events, (void *)sdi);
 
 	while (devc->num_transfers_used < NUM_MAX_TRANSFERS && devc->samples_got_nbytes + devc->num_transfers_used * devc->per_transfer_nbytes < devc->samples_need_nbytes)
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
index f53483ada..8baa0ea29 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
@@ -86,6 +86,7 @@ struct dev_context {
 		int64_t transfers_reached_time_start;
 		int64_t transfers_reached_time_latest;
 
+		GThread *raw_data_handle_thread;
 		GAsyncQueue *raw_data_queue;
 		uint64_t timeout_count;
 	}; // usb

From ea2569eef143436e872e7a225478dac35a51ba8c Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Fri, 21 Mar 2025 10:54:35 +0800
Subject: [PATCH 29/36] sipeed-slogic-analyzer: fix: aux length starts from
 bit9 and try to split control write in 4 bytes

---
 src/hardware/sipeed-slogic-analyzer/api.c | 68 +++++++++++++----------
 1 file changed, 40 insertions(+), 28 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
index 66712401b..64c473e23 100644
--- a/src/hardware/sipeed-slogic-analyzer/api.c
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -542,14 +542,14 @@ static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi) {
 	struct dev_context *devc = sdi->priv;
 	const uint8_t cmd_derst[] = {0x00, 0x00, 0x00, 0x00};
 	const uint8_t cmd_run[] = {0x01, 0x00, 0x00, 0x00};
-	uint8_t cmd_aux_channel[8] = {0x01, 0x00, 0x00, 0x00}; // configure channel
-	uint8_t cmd_aux_samplerate[12] = {0x02, 0x00, 0x00, 0x00}; // configure samplerate
+	uint8_t cmd_aux[64] = {0}; // configure aux
 
 	slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_CTRL, 0x0000, ARRAY_AND_SIZE(cmd_derst), 500);
 
 	{
 		size_t retry = 0;
-		uint8_t *cmd_aux = cmd_aux_channel;
+		memset(cmd_aux, 0, sizeof(cmd_aux));
+		*(uint32_t*)(cmd_aux) = 0x00000001;
 		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
 		do {
 			slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
@@ -558,17 +558,17 @@ static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi) {
 			if (retry > 5)
 				return SR_ERR_TIMEOUT;
 		} while (!(cmd_aux[2] & 0x01));
-		sr_dbg("channel length: %u.", (*(uint16_t*)cmd_aux)>>8);
-		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);
+		sr_dbg("channel length: %u.", (*(uint16_t*)cmd_aux)>>9);
+		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
 
-		// sr_dbg("aux: %u %u %u %u %08x.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint32_t*)(cmd_aux+4))[0]);
+		sr_dbg("aux: %u %u %u %u %08x.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint32_t*)(cmd_aux+4))[0]);
 
 		*(uint32_t*)(cmd_aux+4) = (1 << devc->cur_samplechannel) - 1;
 
-		// sr_dbg("aux: %u %u %u %u %08x.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint32_t*)(cmd_aux+4))[0]);
-		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);
+		sr_dbg("aux: %u %u %u %u %08x.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint32_t*)(cmd_aux+4))[0]);
+		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
 
-		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);
+		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
 		sr_dbg("aux: %u %u %u %u %08x.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint32_t*)(cmd_aux+4))[0]);
 
 		if ((1 << devc->cur_samplechannel) - 1 != *(uint32_t*)(cmd_aux+4)) {
@@ -581,7 +581,8 @@ static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi) {
 
 	{
 		size_t retry = 0;
-		uint8_t *cmd_aux = cmd_aux_samplerate;
+		memset(cmd_aux, 0, sizeof(cmd_aux));
+		*(uint32_t*)(cmd_aux) = 0x00000002;
 		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
 		do {
 			slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
@@ -590,17 +591,19 @@ static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi) {
 			if (retry > 5)
 				return SR_ERR_TIMEOUT;
 		} while (!(cmd_aux[2] & 0x01));
-		sr_dbg("samplerate length: %u.", (*(uint16_t*)cmd_aux)>>8);
-		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);
+		sr_dbg("samplerate length: %u.", (*(uint16_t*)cmd_aux)>>9);
+		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
 
 		sr_dbg("aux: %u %u %u %u %x %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint16_t*)(cmd_aux+4))[0], ((uint16_t*)(cmd_aux+4))[1], ((uint32_t*)(cmd_aux+4))[1]);
 
 		// ((uint32_t*)(cmd_aux+4))[0] = devc->cur_samplerate;
+		((uint16_t*)(cmd_aux+4))[0] = 0x1;
+		((uint32_t*)(cmd_aux+4))[1] = 0x0;
 
 		sr_dbg("aux: %u %u %u %u %x %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint16_t*)(cmd_aux+4))[0], ((uint16_t*)(cmd_aux+4))[1], ((uint32_t*)(cmd_aux+4))[1]);
-		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);
+		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
 
-		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4 + (*(uint16_t*)cmd_aux)>>8, 500);
+		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
 		sr_dbg("aux: %u %u %u %u %x %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint16_t*)(cmd_aux+4))[0], ((uint16_t*)(cmd_aux+4))[1], ((uint32_t*)(cmd_aux+4))[1]);
 
 		if (1 /* devc->cur_samplerate != ((uint32_t*)(cmd_aux+4))[0] */) {
@@ -645,22 +648,31 @@ static int slogic_usb_control_write(const struct sr_dev_inst *sdi, uint8_t reque
 	devc = sdi->priv;
 	usb  = sdi->conn;
 
-	sr_spew("%s req:%u value:%u index:%u %p:%u in %dms.", __func__, request, value, index, data, len, timeout);
+	sr_spew("%s: req:%u value:%u index:%u %p:%u in %dms.", __func__, request, value, index, data, len, timeout);
 	if (!data && len) {
-		sr_warn("%s Nothing to write although len(%u)>0!", __func__, len);
+		sr_warn("%s: Nothing to write although len(%u)>0!", __func__, len);
 		len = 0;
+	} else if (len & 0x3) {
+		size_t len_aligndup = (len + 0x3)&(~0x3);
+		sr_warn("%s: Align up to %u(from %u)!", __func__, len_aligndup, len);
+		len = len_aligndup;
 	}
 
-	if ((ret = libusb_control_transfer(
-		usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT,
-		request,
-		value, index,
-		(unsigned char *)data, len,
-		timeout
-	)) < 0) {
-		sr_err("%s failed(libusb: %s)!", __func__, libusb_error_name(ret));
-		return SR_ERR_NA;
+	ret = 0;
+	for (size_t i = 0; i < len; i+=4) {
+		ret += libusb_control_transfer(
+			usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT,
+			request,
+			value + i, index,
+			(unsigned char *)data + i, 4,
+			timeout
+		);
+		if (ret < 0) {
+			sr_err("%s: failed(libusb: %s)!", __func__, libusb_error_name(ret));
+			return SR_ERR_NA;
+		}
 	}
+
 	return ret;
 }
 
@@ -674,9 +686,9 @@ static int slogic_usb_control_read(const struct sr_dev_inst *sdi, uint8_t reques
 	devc = sdi->priv;
 	usb  = sdi->conn;
 
-	sr_spew("%s req:%u value:%u index:%u %p:%u in %dms.", __func__, request, value, index, data, len, timeout);
+	sr_spew("%s: req:%u value:%u index:%u %p:%u in %dms.", __func__, request, value, index, data, len, timeout);
 	if (!data && len) {
-		sr_err("%s Can't read to NULL while len(%u)>0!", __func__, len);
+		sr_err("%s: Can't read to NULL while len(%u)>0!", __func__, len);
 		return SR_ERR_ARG;
 	}
 
@@ -687,7 +699,7 @@ static int slogic_usb_control_read(const struct sr_dev_inst *sdi, uint8_t reques
 		(unsigned char *)data, len,
 		timeout
 	)) < 0) {
-		sr_err("%s failed(libusb: %s)!", __func__, libusb_error_name(ret));
+		sr_err("%s: failed(libusb: %s)!", __func__, libusb_error_name(ret));
 		return SR_ERR_NA;
 	}
 	return ret;

From 18c212b717f8accd1802f1adec2561abd84e6c48 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Tue, 25 Mar 2025 18:49:28 +0800
Subject: [PATCH 30/36] sipeed-slogic-analyzer: feat: add samplerate
 configuration support

---
 src/hardware/sipeed-slogic-analyzer/api.c | 62 +++++++++++++++--------
 1 file changed, 41 insertions(+), 21 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
index 64c473e23..18ee1eb10 100644
--- a/src/hardware/sipeed-slogic-analyzer/api.c
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -97,6 +97,7 @@ static const uint64_t samplerates[] = {
 	/* x 4ch */
 	SR_MHZ(80),
 	/* x 2ch */
+	SR_MHZ(125),
 	SR_MHZ(160),
 
 	/* Slogic Basic 16 U3 */
@@ -592,24 +593,34 @@ static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi) {
 				return SR_ERR_TIMEOUT;
 		} while (!(cmd_aux[2] & 0x01));
 		sr_dbg("samplerate length: %u.", (*(uint16_t*)cmd_aux)>>9);
-		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
 
-		sr_dbg("aux: %u %u %u %u %x %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint16_t*)(cmd_aux+4))[0], ((uint16_t*)(cmd_aux+4))[1], ((uint32_t*)(cmd_aux+4))[1]);
+		while (((uint16_t*)(cmd_aux+4))[0] <= 1) {
+			slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
 
-		// ((uint32_t*)(cmd_aux+4))[0] = devc->cur_samplerate;
-		((uint16_t*)(cmd_aux+4))[0] = 0x1;
-		((uint32_t*)(cmd_aux+4))[1] = 0x0;
+			sr_dbg("aux: %u %u %u %u %x %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint16_t*)(cmd_aux+4))[0], ((uint16_t*)(cmd_aux+4))[1], ((uint32_t*)(cmd_aux+4))[1]);
 
-		sr_dbg("aux: %u %u %u %u %x %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint16_t*)(cmd_aux+4))[0], ((uint16_t*)(cmd_aux+4))[1], ((uint32_t*)(cmd_aux+4))[1]);
-		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
 
-		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
-		sr_dbg("aux: %u %u %u %u %x %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint16_t*)(cmd_aux+4))[0], ((uint16_t*)(cmd_aux+4))[1], ((uint32_t*)(cmd_aux+4))[1]);
+			uint64_t base = SR_MHZ(1) * ((uint16_t*)(cmd_aux+4))[1];
+			if (base % devc->cur_samplerate) {
+				sr_dbg("Failed to configure samplerate from base[%u] %u.", ((uint16_t*)(cmd_aux+4))[0], base);
+				((uint16_t*)(cmd_aux+4))[0] += 1;
+				continue;
+			}
+			uint32_t div = base / devc->cur_samplerate;
+			((uint32_t*)(cmd_aux+4))[1] = div;
 
-		if (1 /* devc->cur_samplerate != ((uint32_t*)(cmd_aux+4))[0] */) {
-			sr_dbg("Failed to configure samplerate.");
-		} else {
+			sr_dbg("aux: %u %u %u %u %x %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint16_t*)(cmd_aux+4))[0], ((uint16_t*)(cmd_aux+4))[1], ((uint32_t*)(cmd_aux+4))[1]);
+			slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
+
+			slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
+			sr_dbg("aux: %u %u %u %u %x %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint16_t*)(cmd_aux+4))[0], ((uint16_t*)(cmd_aux+4))[1], ((uint32_t*)(cmd_aux+4))[1]);
+			break;
+		}
+
+		if (((uint16_t*)(cmd_aux+4))[0] <= 1) {
 			sr_dbg("Succeed to configure samplerate.");
+		} else {
+			sr_dbg("Failed to configure samplerate.");
 		}
 	}
 
@@ -690,17 +701,26 @@ static int slogic_usb_control_read(const struct sr_dev_inst *sdi, uint8_t reques
 	if (!data && len) {
 		sr_err("%s: Can't read to NULL while len(%u)>0!", __func__, len);
 		return SR_ERR_ARG;
+	} else if (len & 0x3) {
+		size_t len_aligndup = (len + 0x3)&(~0x3);
+		sr_warn("%s: Align up to %u(from %u)!", __func__, len_aligndup, len);
+		len = len_aligndup;
 	}
 
-	if ((ret = libusb_control_transfer(
-		usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN,
-		request,
-		value, index,
-		(unsigned char *)data, len,
-		timeout
-	)) < 0) {
-		sr_err("%s: failed(libusb: %s)!", __func__, libusb_error_name(ret));
-		return SR_ERR_NA;
+	ret = 0;
+	for (size_t i = 0; i < len; i+=4) {
+		ret += libusb_control_transfer(
+			usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN,
+			request,
+			value + i, index,
+			(unsigned char *)data + i, 4,
+			timeout
+		);
+		if (ret < 0) {
+			sr_err("%s: failed(libusb: %s)!", __func__, libusb_error_name(ret));
+			return SR_ERR_NA;
+		}
 	}
+
 	return ret;
 }
\ No newline at end of file

From ff19b5c6e74e1676976cec826830837b436b2027 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Wed, 26 Mar 2025 10:20:11 +0800
Subject: [PATCH 31/36] sipeed-slogic-analyzer: fix: select updated samplerate
 base

---
 src/hardware/sipeed-slogic-analyzer/api.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
index 18ee1eb10..4c40adb43 100644
--- a/src/hardware/sipeed-slogic-analyzer/api.c
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -604,6 +604,7 @@ static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi) {
 			if (base % devc->cur_samplerate) {
 				sr_dbg("Failed to configure samplerate from base[%u] %u.", ((uint16_t*)(cmd_aux+4))[0], base);
 				((uint16_t*)(cmd_aux+4))[0] += 1;
+				slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, 4, 500);
 				continue;
 			}
 			uint32_t div = base / devc->cur_samplerate;

From faf90cdc0753fc11232814ad45d61841f3336a7c Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Wed, 2 Apr 2025 16:00:22 +0800
Subject: [PATCH 32/36] sipeed-slogic-analyzer: fix: use 4MiB size transfers
 default to clear previously generated EP data

---
 src/hardware/sipeed-slogic-analyzer/protocol.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
index 8baa0ea29..bd546c57e 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
@@ -109,12 +109,14 @@ static inline void clear_ep(const struct sr_dev_inst *sdi) {
 	struct sr_usb_dev_inst *usb = sdi->conn;
 	uint8_t ep = devc->model->ep_in;
 
-	uint8_t tmp[1024];
+	size_t tmp_size = 4 * 1024 * 1024;
+	uint8_t *tmp = malloc(tmp_size);
 	int actual_length = 0;
 	do {
 		libusb_bulk_transfer(usb->devhdl, ep,
-				tmp, sizeof(tmp), &actual_length, 100);
+				tmp, tmp_size, &actual_length, 100);
 	} while (actual_length);
+	free(tmp);
 	sr_dbg("Cleared EP: 0x%02x", ep);
 }
 

From 327f6aab1a715a55046eab21f976c222a7d26503 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Thu, 3 Apr 2025 09:48:15 +0800
Subject: [PATCH 33/36] sipeed-slogic-analyzer: refactor: consolidate data
 submission logic by using `slogic_submit_raw_data`

Replace multiple data submission implementations with the common
`slogic_submit_raw_data` function to maintain consistency and reduce
code duplication.
---
 src/hardware/sipeed-slogic-analyzer/api.c | 82 +++++++++--------------
 1 file changed, 33 insertions(+), 49 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
index 4c40adb43..bd2643d5e 100644
--- a/src/hardware/sipeed-slogic-analyzer/api.c
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -38,12 +38,11 @@ static const uint32_t devopts[] = {
 };
 
 
+static void slogic_submit_raw_data(void *data, size_t len, const struct sr_dev_inst *sdi);
 static int slogic_lite_8_remote_run(const struct sr_dev_inst *sdi);
 static int slogic_lite_8_remote_stop(const struct sr_dev_inst *sdi);
-static void slogic_lite_8_submit_raw_data(void *data, size_t len, const struct sr_dev_inst *sdi);
 static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi);
 static int slogic_basic_16_remote_stop(const struct sr_dev_inst *sdi);
-static void slogic_basic_16_submit_raw_data(void *data, size_t len, const struct sr_dev_inst *sdi);
 
 static const struct slogic_model support_models[] = {
 	{
@@ -57,7 +56,7 @@ static const struct slogic_model support_models[] = {
 			.remote_run = slogic_lite_8_remote_run,
 			.remote_stop = slogic_lite_8_remote_stop,
 		},
-		.submit_raw_data = slogic_lite_8_submit_raw_data,
+		.submit_raw_data = slogic_submit_raw_data,
 	},
 	{
 		.name = "Slogic Basic 16 U3",
@@ -70,7 +69,7 @@ static const struct slogic_model support_models[] = {
 			.remote_run = slogic_basic_16_remote_run,
 			.remote_stop = slogic_basic_16_remote_stop,
 		},
-		.submit_raw_data = slogic_basic_16_submit_raw_data,
+		.submit_raw_data = slogic_submit_raw_data,
 	},
 	{
 		.name = NULL,
@@ -463,6 +462,36 @@ SR_REGISTER_DEV_DRIVER(sipeed_slogic_analyzer_driver_info);
 static int slogic_usb_control_write(const struct sr_dev_inst *sdi, uint8_t request, uint16_t value, uint16_t index, uint8_t *data, size_t len, int timeout);
 static int slogic_usb_control_read(const struct sr_dev_inst *sdi, uint8_t request, uint16_t value, uint16_t index, uint8_t *data, size_t len, int timeout);
 
+static void slogic_submit_raw_data(void *data, size_t len, const struct sr_dev_inst *sdi) {
+	struct dev_context *devc = sdi->priv;
+
+	uint8_t *ptr = data;
+	uint64_t nCh = devc->cur_samplechannel;
+
+	if (nCh < 8) {
+		size_t nsp_in_bytes = 8 / nCh; // NOW must be 2 and 4
+		ptr = g_malloc(len * nsp_in_bytes);
+		for(size_t i=0; i<len; i+=nCh) {
+			for(size_t j=0; j<8; j++) {
+				ptr[i*nsp_in_bytes+j] = (((uint8_t *)data)[i+j/nsp_in_bytes] >> (j%nsp_in_bytes*nCh)) & ((1<<nCh)-1);
+			}
+		}
+		len *= nsp_in_bytes; // need reshape
+	}
+
+	sr_session_send(sdi, &(struct sr_datafeed_packet) {
+		.type = SR_DF_LOGIC,
+		.payload = &(struct sr_datafeed_logic) {
+			.length = len,
+			.unitsize = (nCh + 7)/8,
+			.data = ptr,
+		}
+	});
+
+	if (nCh < 8)
+		g_free(ptr);
+}
+
 /* Slogic Lite 8 start */
 #pragma pack(push, 1)
 struct cmd_start_acquisition {
@@ -499,34 +528,6 @@ static int slogic_lite_8_remote_stop(const struct sr_dev_inst *sdi) {
 	// clear_ep(sdi);
 	// return ret;
 }
-
-static void slogic_lite_8_submit_raw_data(void *data, size_t len, const struct sr_dev_inst *sdi) {
-	struct dev_context *devc = sdi->priv;
-
-	size_t length = len * (8/devc->cur_samplechannel);
-	uint8_t *ptr = data;
-
-	if (devc->cur_samplechannel < 8) {
-		ptr = g_malloc(length);
-		for(size_t i=0; i<len; i+=devc->cur_samplechannel) {
-			for(size_t j=0; j<8; j++) {
-				ptr[i*(8/devc->cur_samplechannel)+j] = (((uint8_t *)data)[i+j/(8/devc->cur_samplechannel)] >> (j%(8/devc->cur_samplechannel) * devc->cur_samplechannel)) & ((1<<devc->cur_samplechannel)-1);
-			}
-		}
-	}
-
-	sr_session_send(sdi, &(struct sr_datafeed_packet) {
-		.type = SR_DF_LOGIC,
-		.payload = &(struct sr_datafeed_logic) {
-			.length = length,
-			.unitsize = 1,
-			.data = ptr,
-		}
-	});
-
-	if (devc->cur_samplechannel < 8)
-		g_free(ptr);
-}
 /* Slogic Lite 8 end */
 
 
@@ -632,23 +633,6 @@ static int slogic_basic_16_remote_stop(const struct sr_dev_inst *sdi) {
 	const uint8_t cmd_rst[] = {0x02, 0x00, 0x00, 0x00};
 	return slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_CTRL, 0x0000, ARRAY_AND_SIZE(cmd_rst), 500);
 }
-
-static void slogic_basic_16_submit_raw_data(void *data, size_t len, const struct sr_dev_inst *sdi) {
-	struct dev_context *devc = sdi->priv;
-
-	if (devc->cur_samplechannel < 8) {
-		slogic_lite_8_submit_raw_data(data, len, sdi);
-	} else {
-		sr_session_send(sdi, &(struct sr_datafeed_packet) {
-			.type = SR_DF_LOGIC,
-			.payload = &(struct sr_datafeed_logic) {
-				.length = len,
-				.unitsize = (devc->cur_samplechannel + 7)/8,
-				.data = data,
-			}
-		});
-	}
-}
 /* Slogic Basic 16 end */
 
 static int slogic_usb_control_write(const struct sr_dev_inst *sdi, uint8_t request, uint16_t value, uint16_t index, uint8_t *data, size_t len, int timeout)

From 854e9bf3cbcd8b5e7881b11c223282d4fbc77f51 Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Thu, 3 Apr 2025 12:12:35 +0800
Subject: [PATCH 34/36] sipeed-slogic-analyzer: fix: can't stop immediately
 while `g_thread_join` blocking in `handle_events`

---
 .../sipeed-slogic-analyzer/protocol.c         | 85 ++++++++++++-------
 1 file changed, 53 insertions(+), 32 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index 3814b4143..d80ffca9c 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -36,9 +36,6 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 	int64_t transfers_reached_time_now = g_get_monotonic_time();
 	int64_t transfers_reached_duration = transfers_reached_time_now - devc->transfers_reached_time_latest;
 
-	if (devc->acq_aborted == 1)
-		return;
-
 	sr_spew("Transfer[%d] status: %d(%s)", std_u64_idx(g_variant_new_uint64((uint64_t)transfer), (uint64_t*)devc->transfers, NUM_MAX_TRANSFERS),
 		transfer->status, libusb_error_name(transfer->status));
 	switch (transfer->status) {
@@ -75,7 +72,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 				uint8_t *ptr = g_malloc(devc->per_transfer_nbytes);
 				if (!ptr) {
 					sr_err("Failed to allocate memory: %u bytes!", devc->per_transfer_nbytes);
-					sipeed_slogic_acquisition_stop(sdi);
+					devc->acq_aborted = 1;
 					break;
 				}
 				transfer->buffer = ptr;
@@ -124,7 +121,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer) {
 	}
 
 	if (devc->num_transfers_used == 0) {
-		sipeed_slogic_acquisition_stop(sdi);
+		devc->acq_aborted = 1;
 	}
 
 	devc->num_transfers_completed += 1;
@@ -147,32 +144,38 @@ static int handle_events(int fd, int revents, void *cb_data)
 
 	//sr_spew("handle_events enter");
 
-	if (!devc->raw_data_handle_thread) {
-		sipeed_slogic_acquisition_stop(sdi);
-	}
-
 	if (devc->acq_aborted) {
-		for (size_t i = 0; i < NUM_MAX_TRANSFERS; ++i) {
-			struct libusb_transfer *transfer = devc->transfers[i];
-			if (transfer) {
-				libusb_cancel_transfer(transfer);
+		if (devc->num_transfers_used) {
+			for (size_t i = 0; i < NUM_MAX_TRANSFERS; ++i) {
+				struct libusb_transfer *transfer = devc->transfers[i];
+				if (transfer) {
+					libusb_cancel_transfer(transfer);
+				}
 			}
-		}
-		for (size_t i = 0; i < NUM_MAX_TRANSFERS; ++i) {
-			libusb_handle_events_timeout_completed(drvc->sr_ctx->libusb_ctx, &(struct timeval){0, 0}, NULL);
-			struct libusb_transfer *transfer = devc->transfers[i];
-			if (transfer) {
-				g_free(transfer->buffer);
-				libusb_free_transfer(transfer);
+		} else {
+			int freed = 0;
+			for (size_t i = 0; i < NUM_MAX_TRANSFERS; ++i) {
+				struct libusb_transfer *transfer = devc->transfers[i];
+				if (transfer) {
+					freed = 1;
+					g_free(transfer->buffer);
+					libusb_free_transfer(transfer);
+				}
+				devc->transfers[i] = NULL;
+			}
+			if (freed) {
+				sr_dbg("Freed all transfers.");
+				sr_info("Bulk in %u/%u bytes with %u transfers.", devc->samples_got_nbytes, devc->samples_need_nbytes, devc->num_transfers_completed);
 			}
-			devc->transfers[i] = NULL;
 		}
 
-		sr_dbg("Freed all transfers.");
-		sr_info("Bulk in %u/%u bytes with %u transfers.", devc->samples_got_nbytes, devc->samples_need_nbytes, devc->num_transfers_completed);
-
-		sr_session_source_remove(sdi->session, -1 * (size_t)drvc->sr_ctx->libusb_ctx);
-		g_thread_join(devc->raw_data_handle_thread);
+		if (devc->raw_data_queue == NULL) {
+			if (devc->raw_data_handle_thread) {
+				g_thread_join(devc->raw_data_handle_thread);
+				devc->raw_data_handle_thread == NULL;
+			}
+			sr_session_source_remove(sdi->session, -1 * (size_t)drvc->sr_ctx->libusb_ctx);
+		}
 	}
 
 	libusb_handle_events_timeout_completed(drvc->sr_ctx->libusb_ctx, &(struct timeval){0, 0}, NULL);
@@ -198,7 +201,9 @@ static gpointer raw_data_handle_thread_func(gpointer user_data)
 				break;
 			GByteArray *array = g_async_queue_try_pop(devc->raw_data_queue);
 			if (array != NULL) {
-				devc->model->submit_raw_data(array->data, array->len, sdi);
+				if (devc->trigger_fired) {
+					devc->model->submit_raw_data(array->data, array->len, sdi);
+				}
 				g_byte_array_unref(array);
 			}
 		} while (devc->acq_aborted);
@@ -307,7 +312,19 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	devc->raw_data_queue = g_async_queue_new();
 	devc->raw_data_handle_thread = g_thread_new("raw_data_handle_thread", raw_data_handle_thread_func, sdi);
 
-	sr_session_source_add(sdi->session, -1 * (size_t)drvc->sr_ctx->libusb_ctx, 0, (devc->per_transfer_duration / 2)?:1, handle_events, (void *)sdi);
+	if (!devc->raw_data_queue) {
+		sr_err("New g_async_queue failed, can't handle data anymore!");
+		return SR_ERR_MALLOC;
+	}
+
+	if (!devc->raw_data_handle_thread) {
+		sr_err("Create thread raw_data_handle failed, can't handle data anymore!");
+		if (devc->raw_data_queue) {
+			g_async_queue_unref(devc->raw_data_queue);
+			devc->raw_data_queue = NULL;
+		}
+		return SR_ERR_MALLOC;
+	}
 
 	while (devc->num_transfers_used < NUM_MAX_TRANSFERS && devc->samples_got_nbytes + devc->num_transfers_used * devc->per_transfer_nbytes < devc->samples_need_nbytes)
 	{
@@ -341,14 +358,17 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
 	}
 	sr_dbg("Submited %u transfers", devc->num_transfers_used);
 
+	if (!devc->num_transfers_used) {
+		return SR_ERR_IO;
+	}
+
 	std_session_send_df_header(sdi);
 	std_session_send_df_frame_begin(sdi);
 
-	if (!devc->num_transfers_used) {
-		sipeed_slogic_acquisition_stop(sdi);
-		return SR_OK;
-	}
+	sr_session_source_add(sdi->session, -1 * (size_t)drvc->sr_ctx->libusb_ctx, 0, (devc->per_transfer_duration / 2)?:1, handle_events, (void *)sdi);
 
+	// TODO: need trigger working
+	devc->trigger_fired = TRUE;
 	if ((ret = devc->model->operation.remote_run(sdi)) < 0) {
 		sr_err("Unhandled `CMD_RUN`");
 		sipeed_slogic_acquisition_stop(sdi);
@@ -368,6 +388,7 @@ SR_PRIV int sipeed_slogic_acquisition_stop(struct sr_dev_inst *sdi)
 
 	devc = sdi->priv;
 
+	devc->trigger_fired = FALSE;
 	devc->acq_aborted = 1;
 
 	return SR_OK;

From 48af804d110359b750ac65abe2aaa0d55b9f367d Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Wed, 9 Apr 2025 15:32:24 +0800
Subject: [PATCH 35/36] sipeed-slogic-analyzer: Prepare for upstream submission

* Implement USB streaming thread isolation
  - Decouples raw data processing from libusb transfers callback
  - Enables stable 200MHz sampling (16ch) on SlogicBasic16U3 (max bandwidth: up to 430 MiB/s on test)

* Windows-specific enhancements
  - Resolves USB scheduling bottleneck
  - Support stable 40MHz sampling (8ch) on SlogicCombo8
  - Verified on Win10/Win11 platforms (VMs included)

Co-authored-by: Shenzhen Sipeed Team <support@sipeed.com>
Co-authored-by: taorye <hongtao@sipeed.com, taorye@outlook.com>
---
 src/hardware/sipeed-slogic-analyzer/api.c      | 2 +-
 src/hardware/sipeed-slogic-analyzer/protocol.c | 2 +-
 src/hardware/sipeed-slogic-analyzer/protocol.h | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
index bd2643d5e..ea046b31b 100644
--- a/src/hardware/sipeed-slogic-analyzer/api.c
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libsigrok project.
  *
- * Copyright (C) 2023 taorye <taorye@outlook.com>
+ * Copyright (C) 2023-2025 Shenzhen Sipeed Technology Co., Ltd. (深圳市矽速科技有限公司) <support@sipeed.com>
  *
  * 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
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
index d80ffca9c..f8d27ccd6 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libsigrok project.
  *
- * Copyright (C) 2023 taorye <taorye@outlook.com>
+ * Copyright (C) 2023-2025 Shenzhen Sipeed Technology Co., Ltd. (深圳市矽速科技有限公司) <support@sipeed.com>
  *
  * 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
diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
index bd546c57e..ec1d72919 100644
--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
+++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
@@ -1,7 +1,7 @@
 /*
  * This file is part of the libsigrok project.
  *
- * Copyright (C) 2023 taorye <taorye@outlook.com>
+ * Copyright (C) 2023-2025 Shenzhen Sipeed Technology Co., Ltd. (深圳市矽速科技有限公司) <support@sipeed.com>
  *
  * 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

From e4d0509f948e1110f0b6bdb3698987da0da03fdd Mon Sep 17 00:00:00 2001
From: taorye <taorye@outlook.com>
Date: Thu, 10 Apr 2025 09:57:21 +0800
Subject: [PATCH 36/36] sipeed-slogic-analyzer: fix: standardize product name
 to "SLogic16U3"

---
 src/hardware/sipeed-slogic-analyzer/api.c | 80 +++++++++++------------
 1 file changed, 40 insertions(+), 40 deletions(-)

diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
index ea046b31b..3544f8bff 100644
--- a/src/hardware/sipeed-slogic-analyzer/api.c
+++ b/src/hardware/sipeed-slogic-analyzer/api.c
@@ -39,35 +39,35 @@ static const uint32_t devopts[] = {
 
 
 static void slogic_submit_raw_data(void *data, size_t len, const struct sr_dev_inst *sdi);
-static int slogic_lite_8_remote_run(const struct sr_dev_inst *sdi);
-static int slogic_lite_8_remote_stop(const struct sr_dev_inst *sdi);
-static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi);
-static int slogic_basic_16_remote_stop(const struct sr_dev_inst *sdi);
+static int slogic_combo8_remote_run(const struct sr_dev_inst *sdi);
+static int slogic_combo8_remote_stop(const struct sr_dev_inst *sdi);
+static int slogic16U3_remote_run(const struct sr_dev_inst *sdi);
+static int slogic16U3_remote_stop(const struct sr_dev_inst *sdi);
 
 static const struct slogic_model support_models[] = {
 	{
-		.name = "Slogic Lite 8",
+		.name = "Sogic Combo 8",
 		.pid = 0x0300,
 		.ep_in = 0x01 | LIBUSB_ENDPOINT_IN,
 		.max_samplerate = SR_MHZ(160),
 		.max_samplechannel = 8,
 		.max_bandwidth = SR_MHZ(320),
 		.operation = {
-			.remote_run = slogic_lite_8_remote_run,
-			.remote_stop = slogic_lite_8_remote_stop,
+			.remote_run = slogic_combo8_remote_run,
+			.remote_stop = slogic_combo8_remote_stop,
 		},
 		.submit_raw_data = slogic_submit_raw_data,
 	},
 	{
-		.name = "Slogic Basic 16 U3",
+		.name = "SLogic16U3",
 		.pid = 0x3031,
 		.ep_in = 0x02 | LIBUSB_ENDPOINT_IN,
 		.max_samplerate = SR_MHZ(1600),
 		.max_samplechannel = 16,
 		.max_bandwidth = SR_MHZ(3200),
 		.operation = {
-			.remote_run = slogic_basic_16_remote_run,
-			.remote_stop = slogic_basic_16_remote_stop,
+			.remote_run = slogic16U3_remote_run,
+			.remote_stop = slogic16U3_remote_stop,
 		},
 		.submit_raw_data = slogic_submit_raw_data,
 	},
@@ -90,7 +90,7 @@ static const uint64_t samplerates[] = {
 	SR_MHZ(20),
 	SR_MHZ(32),
 
-	/* Slogic Lite 8 */
+	/* SLogic Combo 8 */
 	/* x 8ch */
 	SR_MHZ(40),
 	/* x 4ch */
@@ -99,7 +99,7 @@ static const uint64_t samplerates[] = {
 	SR_MHZ(125),
 	SR_MHZ(160),
 
-	/* Slogic Basic 16 U3 */
+	/* SLogic16U3 */
 	/* x 16ch */
 	SR_MHZ(200),
 	/* x 8ch */
@@ -440,7 +440,7 @@ static int config_list(uint32_t key, GVariant **data,
 
 static struct sr_dev_driver sipeed_slogic_analyzer_driver_info = {
 	.name = "sipeed-slogic-analyzer",
-	.longname = "Sipeed Slogic Analyzer",
+	.longname = "Sipeed SLogic Analyzer",
 	.api_version = 1,
 	.init = std_init,
 	.cleanup = std_cleanup,
@@ -492,7 +492,7 @@ static void slogic_submit_raw_data(void *data, size_t len, const struct sr_dev_i
 		g_free(ptr);
 }
 
-/* Slogic Lite 8 start */
+/* SLogic Combo 8 start */
 #pragma pack(push, 1)
 struct cmd_start_acquisition {
   union {
@@ -509,7 +509,7 @@ struct cmd_start_acquisition {
 #define CMD_START	0xb1
 #define CMD_STOP	0xb3
 
-static int slogic_lite_8_remote_run(const struct sr_dev_inst *sdi) {
+static int slogic_combo8_remote_run(const struct sr_dev_inst *sdi) {
 	struct dev_context *devc = sdi->priv;
 	const struct cmd_start_acquisition cmd_run = {
 		.sample_rate = devc->cur_samplerate / SR_MHZ(1),
@@ -518,7 +518,7 @@ static int slogic_lite_8_remote_run(const struct sr_dev_inst *sdi) {
 	return slogic_usb_control_write(sdi, CMD_START, 0x0000, 0x0000, (uint8_t *)&cmd_run, sizeof(cmd_run), 500);
 }
 
-static int slogic_lite_8_remote_stop(const struct sr_dev_inst *sdi) {
+static int slogic_combo8_remote_stop(const struct sr_dev_inst *sdi) {
 	struct dev_context *devc = sdi->priv;
 	struct sr_usb_dev_inst *usb = sdi->conn;
 	clear_ep(sdi);
@@ -528,49 +528,49 @@ static int slogic_lite_8_remote_stop(const struct sr_dev_inst *sdi) {
 	// clear_ep(sdi);
 	// return ret;
 }
-/* Slogic Lite 8 end */
+/* SLogic Combo 8 end */
 
 
 
-/* Slogic Basic 16 start */
-#define SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ 	0x00
-#define SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE 	0x01
+/* SLogic16U3 start */
+#define SLOGIC16U3_CONTROL_IN_REQ_REG_READ 	0x00
+#define SLOGIC16U3_CONTROL_OUT_REQ_REG_WRITE 	0x01
 
-#define SLOGIC_BASIC_16_R32_CTRL 	0x0004
-#define SLOGIC_BASIC_16_R32_FLAG 	0x0008
-#define SLOGIC_BASIC_16_R32_AUX 	0x000c
+#define SLOGIC16U3_R32_CTRL 	0x0004
+#define SLOGIC16U3_R32_FLAG 	0x0008
+#define SLOGIC16U3_R32_AUX 	0x000c
 
-static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi) {
+static int slogic16U3_remote_run(const struct sr_dev_inst *sdi) {
 	struct dev_context *devc = sdi->priv;
 	const uint8_t cmd_derst[] = {0x00, 0x00, 0x00, 0x00};
 	const uint8_t cmd_run[] = {0x01, 0x00, 0x00, 0x00};
 	uint8_t cmd_aux[64] = {0}; // configure aux
 
-	slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_CTRL, 0x0000, ARRAY_AND_SIZE(cmd_derst), 500);
+	slogic_usb_control_write(sdi, SLOGIC16U3_CONTROL_OUT_REQ_REG_WRITE, SLOGIC16U3_R32_CTRL, 0x0000, ARRAY_AND_SIZE(cmd_derst), 500);
 
 	{
 		size_t retry = 0;
 		memset(cmd_aux, 0, sizeof(cmd_aux));
 		*(uint32_t*)(cmd_aux) = 0x00000001;
-		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
+		slogic_usb_control_write(sdi, SLOGIC16U3_CONTROL_OUT_REQ_REG_WRITE, SLOGIC16U3_R32_AUX, 0x0000, cmd_aux, 4, 500);
 		do {
-			slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
+			slogic_usb_control_read(sdi, SLOGIC16U3_CONTROL_IN_REQ_REG_READ, SLOGIC16U3_R32_AUX, 0x0000, cmd_aux, 4, 500);
 			sr_dbg("[%u]read aux channel: %08x.", retry, ((uint32_t*)cmd_aux)[0]);
 			retry += 1;
 			if (retry > 5)
 				return SR_ERR_TIMEOUT;
 		} while (!(cmd_aux[2] & 0x01));
 		sr_dbg("channel length: %u.", (*(uint16_t*)cmd_aux)>>9);
-		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
+		slogic_usb_control_read(sdi, SLOGIC16U3_CONTROL_IN_REQ_REG_READ, SLOGIC16U3_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
 
 		sr_dbg("aux: %u %u %u %u %08x.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint32_t*)(cmd_aux+4))[0]);
 
 		*(uint32_t*)(cmd_aux+4) = (1 << devc->cur_samplechannel) - 1;
 
 		sr_dbg("aux: %u %u %u %u %08x.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint32_t*)(cmd_aux+4))[0]);
-		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
+		slogic_usb_control_write(sdi, SLOGIC16U3_CONTROL_OUT_REQ_REG_WRITE, SLOGIC16U3_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
 
-		slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
+		slogic_usb_control_read(sdi, SLOGIC16U3_CONTROL_IN_REQ_REG_READ, SLOGIC16U3_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
 		sr_dbg("aux: %u %u %u %u %08x.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint32_t*)(cmd_aux+4))[0]);
 
 		if ((1 << devc->cur_samplechannel) - 1 != *(uint32_t*)(cmd_aux+4)) {
@@ -585,9 +585,9 @@ static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi) {
 		size_t retry = 0;
 		memset(cmd_aux, 0, sizeof(cmd_aux));
 		*(uint32_t*)(cmd_aux) = 0x00000002;
-		slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
+		slogic_usb_control_write(sdi, SLOGIC16U3_CONTROL_OUT_REQ_REG_WRITE, SLOGIC16U3_R32_AUX, 0x0000, cmd_aux, 4, 500);
 		do {
-			slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX, 0x0000, cmd_aux, 4, 500);
+			slogic_usb_control_read(sdi, SLOGIC16U3_CONTROL_IN_REQ_REG_READ, SLOGIC16U3_R32_AUX, 0x0000, cmd_aux, 4, 500);
 			sr_dbg("[%u]read aux samplerate: %08x.", retry, ((uint32_t*)cmd_aux)[0]);
 			retry += 1;
 			if (retry > 5)
@@ -596,7 +596,7 @@ static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi) {
 		sr_dbg("samplerate length: %u.", (*(uint16_t*)cmd_aux)>>9);
 
 		while (((uint16_t*)(cmd_aux+4))[0] <= 1) {
-			slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
+			slogic_usb_control_read(sdi, SLOGIC16U3_CONTROL_IN_REQ_REG_READ, SLOGIC16U3_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
 
 			sr_dbg("aux: %u %u %u %u %x %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint16_t*)(cmd_aux+4))[0], ((uint16_t*)(cmd_aux+4))[1], ((uint32_t*)(cmd_aux+4))[1]);
 
@@ -605,16 +605,16 @@ static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi) {
 			if (base % devc->cur_samplerate) {
 				sr_dbg("Failed to configure samplerate from base[%u] %u.", ((uint16_t*)(cmd_aux+4))[0], base);
 				((uint16_t*)(cmd_aux+4))[0] += 1;
-				slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, 4, 500);
+				slogic_usb_control_write(sdi, SLOGIC16U3_CONTROL_OUT_REQ_REG_WRITE, SLOGIC16U3_R32_AUX + 4, 0x0000, cmd_aux + 4, 4, 500);
 				continue;
 			}
 			uint32_t div = base / devc->cur_samplerate;
 			((uint32_t*)(cmd_aux+4))[1] = div;
 
 			sr_dbg("aux: %u %u %u %u %x %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint16_t*)(cmd_aux+4))[0], ((uint16_t*)(cmd_aux+4))[1], ((uint32_t*)(cmd_aux+4))[1]);
-			slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
+			slogic_usb_control_write(sdi, SLOGIC16U3_CONTROL_OUT_REQ_REG_WRITE, SLOGIC16U3_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
 
-			slogic_usb_control_read(sdi, SLOGIC_BASIC_16_CONTROL_IN_REQ_REG_READ, SLOGIC_BASIC_16_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
+			slogic_usb_control_read(sdi, SLOGIC16U3_CONTROL_IN_REQ_REG_READ, SLOGIC16U3_R32_AUX + 4, 0x0000, cmd_aux + 4, (*(uint16_t*)cmd_aux)>>9, 500);
 			sr_dbg("aux: %u %u %u %u %x %u %u.", cmd_aux[0], cmd_aux[1], cmd_aux[2], cmd_aux[3], ((uint16_t*)(cmd_aux+4))[0], ((uint16_t*)(cmd_aux+4))[1], ((uint32_t*)(cmd_aux+4))[1]);
 			break;
 		}
@@ -626,14 +626,14 @@ static int slogic_basic_16_remote_run(const struct sr_dev_inst *sdi) {
 		}
 	}
 
-	return slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_CTRL, 0x0000, ARRAY_AND_SIZE(cmd_run), 500);
+	return slogic_usb_control_write(sdi, SLOGIC16U3_CONTROL_OUT_REQ_REG_WRITE, SLOGIC16U3_R32_CTRL, 0x0000, ARRAY_AND_SIZE(cmd_run), 500);
 }
 
-static int slogic_basic_16_remote_stop(const struct sr_dev_inst *sdi) {
+static int slogic16U3_remote_stop(const struct sr_dev_inst *sdi) {
 	const uint8_t cmd_rst[] = {0x02, 0x00, 0x00, 0x00};
-	return slogic_usb_control_write(sdi, SLOGIC_BASIC_16_CONTROL_OUT_REQ_REG_WRITE, SLOGIC_BASIC_16_R32_CTRL, 0x0000, ARRAY_AND_SIZE(cmd_rst), 500);
+	return slogic_usb_control_write(sdi, SLOGIC16U3_CONTROL_OUT_REQ_REG_WRITE, SLOGIC16U3_R32_CTRL, 0x0000, ARRAY_AND_SIZE(cmd_rst), 500);
 }
-/* Slogic Basic 16 end */
+/* SLogic16U3 end */
 
 static int slogic_usb_control_write(const struct sr_dev_inst *sdi, uint8_t request, uint16_t value, uint16_t index, uint8_t *data, size_t len, int timeout)
 {
