summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authoryjun2024-01-02 21:50:25 +0800
committeryjun2024-01-02 21:59:39 +0800
commitf7379612724f8f47f6cbed1cbc38e6f496b4c255 (patch)
treedc5e1affad2841b30bad09c599bb293b58ae3e69
downloadaur-f7379612724f8f47f6cbed1cbc38e6f496b4c255.tar.gz
[init]: libsigrok-sipeed-slogic-git 0.2.1.r4225.g395ac73e
-rw-r--r--.SRCINFO27
-rw-r--r--.gitignore4
-rw-r--r--0001-add-sipeed-slogic-analyzer-support.patch1919
-rw-r--r--PKGBUILD57
4 files changed, 2007 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO
new file mode 100644
index 000000000000..c31a647107a3
--- /dev/null
+++ b/.SRCINFO
@@ -0,0 +1,27 @@
+pkgbase = libsigrok-sipeed-slogic-git
+ pkgdesc = Client software that supports various hardware logic analyzers, core library (git version)
+ pkgver = 0.2.1.r3652.g025bd56f
+ pkgrel = 1
+ url = http://www.sigrok.org/wiki/Libsigrok
+ arch = armv6h
+ arch = armv7h
+ arch = i686
+ arch = x86_64
+ license = GPL3
+ makedepends = git
+ makedepends = autoconf-archive
+ makedepends = doxygen
+ depends = libzip
+ depends = libftdi
+ depends = alsa-lib
+ depends = libserialport-git
+ depends = glibmm
+ depends = libieee1284
+ provides = libsigrok
+ conflicts = libsigrok
+ source = git://sigrok.org/libsigrok
+ source = 0001-add-sipeed-slogic-analyzer-support.patch
+ sha512sums = SKIP
+ sha512sums = dd05758731b34ed7dac1b7cafa635427759dcb84e0b850b34e64c3e9bd4e4bb4d9bd9b0b6d90d3efbd5b62e001e392770289858c3cbb160c972f1cbd58c4a2c9
+
+pkgname = libsigrok-sipeed-slogic-git
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000000..03164ec2c19c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+pkg/
+src/
+libsigrok/
+*.pkg.*
diff --git a/0001-add-sipeed-slogic-analyzer-support.patch b/0001-add-sipeed-slogic-analyzer-support.patch
new file mode 100644
index 000000000000..670b6f31c46f
--- /dev/null
+++ b/0001-add-sipeed-slogic-analyzer-support.patch
@@ -0,0 +1,1919 @@
+From 1b73b03afff6bf890dc6373c9f1993bd036ea103 Mon Sep 17 00:00:00 2001
+From: taorye <taorye@outlook.com>
+Date: Sun, 29 Jan 2023 18:19:49 +0800
+Subject: [PATCH 1/8] 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 63b7cacd..797cbb05 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -646,6 +646,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 b482419c..68798da1 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -358,6 +358,7 @@ SR_DRIVER([SCPI PPS], [scpi-pps])
+ SR_DRIVER([serial DMM], [serial-dmm], [serial_comm])
+ SR_DRIVER([serial LCR], [serial-lcr], [serial_comm])
+ 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 00000000..365e8592
+--- /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 00000000..7b01e981
+--- /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 00000000..fab48d9a
+--- /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
+--
+2.43.0
+
+From fb4027c79ab08c9fae7208a5d249cf41af70a9fe Mon Sep 17 00:00:00 2001
+From: taorye <taorye@outlook.com>
+Date: Mon, 20 Feb 2023 09:43:04 +0800
+Subject: [PATCH 2/8] feat: use pattern to control active channels
+
+---
+ src/hardware/sipeed-slogic-analyzer/api.c | 306 +++++++++++++++++-
+ .../sipeed-slogic-analyzer/protocol.h | 14 +
+ 2 files changed, 312 insertions(+), 8 deletions(-)
+
+diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
+index 365e8592..4023d236 100644
+--- a/src/hardware/sipeed-slogic-analyzer/api.c
++++ b/src/hardware/sipeed-slogic-analyzer/api.c
+@@ -20,8 +20,78 @@
+ #include <config.h>
+ #include "protocol.h"
+
++/* Note: No spaces allowed because of sigrok-cli. */
++static const char *logic_pattern_str[] = {
++ "1ch",
++ "2ch",
++ "4ch",
++ "8ch",
++ // "16ch",
++};
++
++static const uint32_t scanopts[] = {
++ SR_CONF_NUM_LOGIC_CHANNELS,
++ SR_CONF_CONN,
++};
++
++static const uint32_t drvopts[] = {
++ SR_CONF_LOGIC_ANALYZER,
++};
++
++static const uint32_t devopts[] = {
++ SR_CONF_CONTINUOUS,
++ SR_CONF_CONN | SR_CONF_GET,
++ 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_LIST,
++ SR_CONF_CAPTURE_RATIO | SR_CONF_GET | SR_CONF_SET,
++};
++
++static const uint32_t devopts_cg_logic[] = {
++ SR_CONF_PATTERN_MODE | SR_CONF_GET | SR_CONF_SET | 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 const uint64_t samplerates[] = {
++ SR_KHZ(20),
++ SR_KHZ(25),
++ SR_KHZ(50),
++ SR_KHZ(100),
++ SR_KHZ(200),
++ SR_KHZ(250),
++ SR_KHZ(500),
++ /* 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(40),
++ /* must less than 47MHZ */
++};
++
+ static struct sr_dev_driver sipeed_slogic_analyzer_driver_info;
+
++#define DBG_VAL(expr) do {\
++ __typeof((expr)) _expr = (expr);\
++ sr_warn("[%u]%s<"#expr"> i:%d\tu:%u\tf:%f\th:%x", __LINE__, __func__, \
++ *(long*)(&_expr), \
++ *(unsigned long*)(&_expr), \
++ *(float*)(&_expr), \
++ *(unsigned long*)(&_expr)); \
++}while(0)
++
+ static GSList *scan(struct sr_dev_driver *di, GSList *options)
+ {
+ struct drv_context *drvc;
+@@ -35,8 +105,77 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
+
+ /* TODO: scan for devices, either based on a SR_CONF_CONN option
+ * or on a USB scan. */
++ const char *conn = NULL;
++ int num_logic_channels = 8;
++ for (GSList *l = options; l; l = l->next) {
++ struct sr_config *src = l->data;DBG_VAL(src->key);
++ switch (src->key) {
++ case SR_CONF_NUM_LOGIC_CHANNELS:
++ num_logic_channels = g_variant_get_int32(src->data);
++ break;
++ case SR_CONF_CONN:
++ conn = g_variant_get_string(src->data, NULL);
++ break;
++ }
++ }
++
++ if(!conn) {
++ conn = "359f.0300";
++ }
+
+- return devices;
++ /* Find all slogic compatible devices. */
++ GSList * conn_devices = sr_usb_find(drvc->sr_ctx->libusb_ctx, conn);
++ for(GSList *l = conn_devices; l; l = l->next) {
++ struct sr_usb_dev_inst *usb = l->data;
++ if (SR_OK != sr_usb_open(drvc->sr_ctx->libusb_ctx, usb))
++ continue;
++
++ unsigned char iManufacturer[64], iProduct[64], iSerialNumber[64];
++ unsigned char connection_id[64];
++ struct libusb_device_descriptor des;
++ libusb_get_device_descriptor(libusb_get_device(usb->devhdl), &des);
++ if (libusb_get_string_descriptor_ascii(usb->devhdl,
++ des.iManufacturer, iManufacturer, sizeof(iManufacturer)) < 0)
++ continue;
++ if (libusb_get_string_descriptor_ascii(usb->devhdl,
++ des.iProduct, iProduct, sizeof(iProduct)) < 0)
++ continue;
++ if (libusb_get_string_descriptor_ascii(usb->devhdl,
++ des.iSerialNumber, iSerialNumber, sizeof(iSerialNumber)) < 0)
++ continue;
++ if (usb_get_port_path(libusb_get_device(usb->devhdl),
++ connection_id, sizeof(connection_id)) < 0)
++ continue;
++ sr_usb_close(usb);
++
++ struct sr_dev_inst *sdi = sr_dev_inst_user_new(iManufacturer, iProduct, NULL);
++ sdi->serial_num = g_strdup(iSerialNumber);
++ sdi->connection_id = g_strdup(connection_id);
++
++ sdi->inst_type = SR_INST_USB;
++ sdi->status = SR_ST_INACTIVE;
++ sdi->conn = usb;
++
++ struct dev_context *devc = g_malloc0(sizeof(struct dev_context));
++ sdi->priv = devc;
++ devc->profile = NULL;
++
++ if (num_logic_channels > 0) {
++ /* Logic channels, all in one channel group. */
++ struct sr_channel_group *cg = sr_channel_group_new(sdi, "Logic", NULL);
++ for (int i = 0; i < num_logic_channels; i++) {
++ char channel_name[16];
++ sprintf(channel_name, "D%d", i);
++ struct sr_channel *ch = sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_name);
++ cg->channels = g_slist_append(cg->channels, ch);
++ }
++ }
++
++ 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)
+@@ -44,8 +183,37 @@ static int dev_open(struct sr_dev_inst *sdi)
+ (void)sdi;
+
+ /* TODO: get handle from sdi->conn and open it. */
++ int ret;
++ struct sr_usb_dev_inst *usb= sdi->conn;
++ struct dev_context *devc= sdi->priv;
++ struct sr_dev_driver *di = sdi->driver;
++ struct drv_context *drvc = di->context;
++
++ ret = sr_usb_open(drvc->sr_ctx->libusb_ctx, usb);DBG_VAL(ret);
++ if (ret != SR_OK)
++ return ret;
++
++ ret = libusb_claim_interface(usb->devhdl, 0);DBG_VAL(ret);
++ 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->logic_pattern = 3; /* 2^3 = 8 default */
++
++ return std_dummy_dev_open(sdi);
+ }
+
+ static int dev_close(struct sr_dev_inst *sdi)
+@@ -53,8 +221,20 @@ static int dev_close(struct sr_dev_inst *sdi)
+ (void)sdi;
+
+ /* TODO: get handle from sdi->conn and close it. */
++ int ret;
++ struct sr_usb_dev_inst *usb = sdi->conn;
++ struct dev_context *devc= sdi->priv;
++
++ ret = libusb_release_interface(usb->devhdl, 0);DBG_VAL(ret);
++ if (ret != LIBUSB_SUCCESS) {
++ sr_err("Unable to release Interface for %s.",
++ libusb_error_name(ret));
++ return SR_ERR;
++ }
+
+- return SR_OK;
++ sr_usb_close(usb);
++
++ return std_dummy_dev_close(sdi);
+ }
+
+ static int config_get(uint32_t key, GVariant **data,
+@@ -66,9 +246,42 @@ static int config_get(uint32_t key, GVariant **data,
+ (void)data;
+ (void)cg;
+
+- ret = SR_OK;
++ struct sr_usb_dev_inst *usb = sdi->conn;
++ struct dev_context *devc= sdi->priv;
++ struct sr_channel *ch;
++ ret = SR_OK;DBG_VAL(key);
+ switch (key) {
+ /* TODO */
++ case SR_CONF_CONN:
++ if (usb->address == 0xff)
++ /* Device still needs to re-enumerate after firmware
++ * upload, so we don't know its (future) address. */
++ return SR_ERR;
++ *data = g_variant_new_printf("%d.%d", usb->bus, usb->address);
++ break;
++ 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;
++ case SR_CONF_PATTERN_MODE:
++ if (!cg)
++ return SR_ERR_CHANNEL_GROUP;
++ /* Any channel in the group will do. */
++ ch = cg->channels->data;
++ if (ch->type == SR_CHANNEL_LOGIC) {
++ int pattern = devc->logic_pattern;
++ *data = g_variant_new_string(logic_pattern_str[pattern]);
++ } else
++ return SR_ERR_BUG;
++ break;
++ case SR_CONF_CAPTURE_RATIO:
++ *data = g_variant_new_uint64(devc->capture_ratio);
++ break;
++ case SR_CONF_VOLTAGE_THRESHOLD:
++ *data = std_gvar_tuple_double(devc->voltage_threshold[0], devc->voltage_threshold[1]);
++ break;
+ default:
+ return SR_ERR_NA;
+ }
+@@ -85,9 +298,60 @@ static int config_set(uint32_t key, GVariant *data,
+ (void)data;
+ (void)cg;
+
+- ret = SR_OK;
++ struct dev_context *devc= sdi->priv;
++ int logic_pattern;
++ ret = SR_OK;DBG_VAL(key);
+ switch (key) {
+ /* TODO */
++ case SR_CONF_SAMPLERATE:
++ if (std_u64_idx(data, ARRAY_AND_SIZE(samplerates)) < 0)
++ return SR_ERR_ARG;
++ devc->cur_samplerate = g_variant_get_uint64(data);
++ break;
++ case SR_CONF_LIMIT_SAMPLES:
++ devc->limit_samples = g_variant_get_uint64(data);
++ break;
++ case SR_CONF_PATTERN_MODE:
++ if (!cg)
++ return SR_ERR_CHANNEL_GROUP;
++ logic_pattern = std_str_idx(data, ARRAY_AND_SIZE(logic_pattern_str));
++ if (logic_pattern < 0)
++ return SR_ERR_ARG;
++ if (((struct sr_channel *)cg->channels->data)->type == SR_CHANNEL_LOGIC) {
++ sr_dbg("Setting logic pattern to %s",
++ logic_pattern_str[logic_pattern]);
++ devc->logic_pattern = logic_pattern;
++ /* Might as well do this now, these are static. */
++ }
++ {
++
++ size_t idx = 0;
++ for (GSList *l = cg->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. */
++ switch (devc->logic_pattern)
++ {
++ case 0/* 2^0 = 1 */:
++ case 1/* 2^1 = 2 */:
++ case 2/* 2^2 = 4 */:
++ case 3/* 2^3 = 8 */:
++ sr_dev_channel_enable(ch, (idx >= (1 << (devc->logic_pattern))) ? FALSE : TRUE);
++ break;
++ default:
++ break;
++ }
++ } else
++ return SR_ERR_BUG;
++ }
++ }
++ break;
++ case SR_CONF_CAPTURE_RATIO:
++ devc->capture_ratio = g_variant_get_uint64(data);
++ break;
++ case SR_CONF_VOLTAGE_THRESHOLD:
++ g_variant_get(data, "(dd)", &devc->voltage_threshold[0], &devc->voltage_threshold[1]);
++ break;
+ default:
+ ret = SR_ERR_NA;
+ }
+@@ -104,9 +368,35 @@ static int config_list(uint32_t key, GVariant **data,
+ (void)data;
+ (void)cg;
+
+- ret = SR_OK;
++ struct sr_channel *ch;
++ ret = SR_OK;DBG_VAL(key);
+ switch (key) {
+ /* TODO */
++ case SR_CONF_SCAN_OPTIONS:
++ case SR_CONF_DEVICE_OPTIONS:
++ if (!cg)
++ return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
++ ch = cg->channels->data;
++ if (ch->type == SR_CHANNEL_LOGIC)
++ *data = std_gvar_array_u32(ARRAY_AND_SIZE(devopts_cg_logic));
++ else
++ return SR_ERR_BUG;
++ 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;
++ case SR_CONF_PATTERN_MODE:
++ if (!cg)
++ return SR_ERR_NA;
++ ch = cg->channels->data;
++ if (ch->type == SR_CHANNEL_LOGIC)
++ *data = g_variant_new_strv(ARRAY_AND_SIZE(logic_pattern_str));
++ else
++ return SR_ERR_BUG;
++ break;
+ default:
+ return SR_ERR_NA;
+ }
+@@ -119,7 +409,7 @@ 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;
++ (void)sdi;DBG_VAL(sdi);
+
+ return SR_OK;
+ }
+@@ -128,7 +418,7 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi)
+ {
+ /* TODO: stop acquisition. */
+
+- (void)sdi;
++ (void)sdi;DBG_VAL(sdi);
+
+ return SR_OK;
+ }
+diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
+index fab48d9a..84e31087 100644
+--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
++++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
+@@ -22,12 +22,26 @@
+
+ #include <stdint.h>
+ #include <glib.h>
++#include <libusb.h>
+ #include <libsigrok/libsigrok.h>
+ #include "libsigrok-internal.h"
+
+ #define LOG_PREFIX "sipeed-slogic-analyzer"
+
++struct slogic_profile {
++ uint16_t vid;
++ uint16_t pid;
++};
++
+ struct dev_context {
++ struct slogic_profile *profile;
++
++ uint64_t cur_samplerate;
++ uint64_t limit_samples;
++ int logic_pattern;
++ double voltage_threshold[2];
++ /* Triggers */
++ uint64_t capture_ratio;
+ };
+
+ SR_PRIV int sipeed_slogic_analyzer_receive_data(int fd, int revents, void *cb_data);
+--
+2.43.0
+
+From 1aa1e9ec026c0394e6be9bb9274bb4bec5dc1f91 Mon Sep 17 00:00:00 2001
+From: taorye <taorye@outlook.com>
+Date: Tue, 21 Feb 2023 12:00:58 +0800
+Subject: [PATCH 3/8] feat: capture data and regroup channels
+
+---
+ src/hardware/sipeed-slogic-analyzer/api.c | 52 +--
+ .../sipeed-slogic-analyzer/protocol.c | 356 +++++++++++++++++-
+ .../sipeed-slogic-analyzer/protocol.h | 76 +++-
+ 3 files changed, 435 insertions(+), 49 deletions(-)
+
+diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
+index 4023d236..4038a6e2 100644
+--- a/src/hardware/sipeed-slogic-analyzer/api.c
++++ b/src/hardware/sipeed-slogic-analyzer/api.c
+@@ -83,15 +83,6 @@ static const uint64_t samplerates[] = {
+
+ static struct sr_dev_driver sipeed_slogic_analyzer_driver_info;
+
+-#define DBG_VAL(expr) do {\
+- __typeof((expr)) _expr = (expr);\
+- sr_warn("[%u]%s<"#expr"> i:%d\tu:%u\tf:%f\th:%x", __LINE__, __func__, \
+- *(long*)(&_expr), \
+- *(unsigned long*)(&_expr), \
+- *(float*)(&_expr), \
+- *(unsigned long*)(&_expr)); \
+-}while(0)
+-
+ static GSList *scan(struct sr_dev_driver *di, GSList *options)
+ {
+ struct drv_context *drvc;
+@@ -212,6 +203,11 @@ static int dev_open(struct sr_dev_inst *sdi)
+ }
+
+ devc->logic_pattern = 3; /* 2^3 = 8 default */
++ devc->cur_samplerate = samplerates[0];
++ devc->limit_samples = 0;
++ devc->num_frames = 0;
++ devc->limit_frames = 1;
++ devc->capture_ratio = 0;
+
+ return std_dummy_dev_open(sdi);
+ }
+@@ -322,25 +318,12 @@ static int config_set(uint32_t key, GVariant *data,
+ logic_pattern_str[logic_pattern]);
+ devc->logic_pattern = logic_pattern;
+ /* Might as well do this now, these are static. */
+- }
+- {
+-
+ size_t idx = 0;
+ for (GSList *l = cg->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. */
+- switch (devc->logic_pattern)
+- {
+- case 0/* 2^0 = 1 */:
+- case 1/* 2^1 = 2 */:
+- case 2/* 2^2 = 4 */:
+- case 3/* 2^3 = 8 */:
+- sr_dev_channel_enable(ch, (idx >= (1 << (devc->logic_pattern))) ? FALSE : TRUE);
+- break;
+- default:
+- break;
+- }
++ sr_dev_channel_enable(ch, (idx >= (1 << (devc->logic_pattern))) ? FALSE : TRUE);
+ } else
+ return SR_ERR_BUG;
+ }
+@@ -404,25 +387,6 @@ static int config_list(uint32_t key, GVariant **data,
+ 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;DBG_VAL(sdi);
+-
+- return SR_OK;
+-}
+-
+-static int dev_acquisition_stop(struct sr_dev_inst *sdi)
+-{
+- /* TODO: stop acquisition. */
+-
+- (void)sdi;DBG_VAL(sdi);
+-
+- return SR_OK;
+-}
+-
+ static struct sr_dev_driver sipeed_slogic_analyzer_driver_info = {
+ .name = "sipeed-slogic-analyzer",
+ .longname = "Sipeed Slogic Analyzer",
+@@ -437,8 +401,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 7b01e981..f232c25f 100644
+--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
++++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
+@@ -20,12 +20,17 @@
+ #include <config.h>
+ #include "protocol.h"
+
++static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer);
++static int command_start_acquisition(const struct sr_dev_inst *sdi);
++
+ 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;
++ struct drv_context *drvc;
+
+ (void)fd;
++ (void)revents;
+
+ sdi = cb_data;
+ if (!sdi)
+@@ -35,9 +40,354 @@ SR_PRIV int sipeed_slogic_analyzer_receive_data(int fd, int revents, void *cb_da
+ if (!devc)
+ return TRUE;
+
+- if (revents == G_IO_IN) {
+- /* TODO */
+- }
++ drvc = sdi->driver->context;
++ if (!drvc)
++ return TRUE;
++
++ struct timeval tv = {
++ .tv_sec = 0,
++ .tv_usec = 0,
++ };
++ libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &tv);
+
+ return TRUE;
+ }
++
++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. */
++
++ (void)sdi;DBG_VAL(sdi);
++ struct dev_context *devc = sdi->priv;
++
++ int timeout = get_timeout(devc);
++ usb_source_add(sdi->session, sdi->session->ctx, timeout, sipeed_slogic_analyzer_receive_data, sdi);
++
++ struct sr_usb_dev_inst *usb = sdi->conn;
++ devc->sent_samples = 0;
++ devc->acq_aborted = FALSE;
++ devc->empty_transfer_count = 0;
++
++ struct sr_trigger *trigger;
++ if ((trigger = sr_session_trigger_get(sdi->session))) {
++ int pre_trigger_samples = 0;
++ if (devc->limit_samples > 0)
++ pre_trigger_samples = (devc->capture_ratio * devc->limit_samples) / 100;
++ devc->stl = soft_trigger_logic_new(sdi, trigger, pre_trigger_samples);
++ if (!devc->stl)
++ return SR_ERR_MALLOC;
++ devc->trigger_fired = FALSE;
++ } else {
++ std_session_send_df_frame_begin(sdi);
++ devc->trigger_fired = TRUE;
++ }
++
++ devc->submitted_transfers = 0;
++ size_t num_transfers = get_number_of_transfers(devc);
++ devc->num_transfers = num_transfers;
++ devc->transfers = g_try_malloc0(sizeof(*devc->transfers) * devc->num_transfers);
++ if (!devc->transfers) {
++ sr_err("USB transfers malloc failed.");
++ return SR_ERR_MALLOC;
++ }
++ size_t size = get_buffer_size(devc);
++ for (int i = 0; i < devc->num_transfers; i++) {
++ uint8_t *buf = g_try_malloc(size * 8); /* max 8xu1 */
++ if (!buf) {
++ sr_err("USB transfer buffer malloc failed.");
++ return SR_ERR_MALLOC;
++ }
++ struct libusb_transfer *transfer = libusb_alloc_transfer(0);
++ libusb_fill_bulk_transfer(transfer, usb->devhdl,
++ 1 | LIBUSB_ENDPOINT_IN, buf, size,
++ receive_transfer, (void *)sdi, timeout);
++ sr_info("submitting transfer: %d", i);
++ int ret = 0;
++ if ((ret = libusb_submit_transfer(transfer)) != 0) {
++ sr_err("Failed to submit transfer: %s.",
++ libusb_error_name(ret));
++ libusb_free_transfer(transfer);
++ g_free(buf);
++ sipeed_slogic_acquisition_stop(sdi);
++ return SR_ERR;
++ }
++ devc->transfers[i] = transfer;
++ devc->submitted_transfers++;
++ }
++
++ std_session_send_df_header(sdi);
++
++ int ret = SR_OK;
++ if ((ret = command_start_acquisition(sdi)) != SR_OK) {
++ sipeed_slogic_acquisition_stop(sdi);
++ return ret;
++ }
++
++ return SR_OK;
++}
++
++SR_PRIV int sipeed_slogic_acquisition_stop(struct sr_dev_inst *sdi)
++{
++ /* TODO: stop acquisition. */
++
++ (void)sdi;DBG_VAL(sdi);
++ struct dev_context *devc = sdi->priv;
++
++ devc->acq_aborted = TRUE;
++ for (int i = devc->num_transfers - 1; i >= 0; i--) {
++ if (devc->transfers[i])
++ libusb_cancel_transfer(devc->transfers[i]);
++ }
++ return SR_OK;
++}
++
++static void finish_acquisition(struct sr_dev_inst *sdi)
++{
++ struct dev_context *devc;
++
++ devc = sdi->priv;
++
++ std_session_send_df_end(sdi);
++
++ usb_source_remove(sdi->session, sdi->session->ctx);
++
++ devc->num_transfers = 0;
++ g_free(devc->transfers);
++
++ if (devc->stl) {
++ soft_trigger_logic_free(devc->stl);
++ devc->stl = NULL;
++ }
++}
++
++static void free_transfer(struct libusb_transfer *transfer)
++{
++ struct sr_dev_inst *sdi;
++ struct dev_context *devc;
++ unsigned int i;
++
++ sdi = transfer->user_data;
++ devc = sdi->priv;
++
++ g_free(transfer->buffer);
++ transfer->buffer = NULL;
++ libusb_free_transfer(transfer);
++
++ for (i = 0; i < devc->num_transfers; i++) {
++ if (devc->transfers[i] == transfer) {
++ devc->transfers[i] = NULL;
++ break;
++ }
++ }
++
++ devc->submitted_transfers--;
++ if (devc->submitted_transfers == 0)
++ finish_acquisition(sdi);
++}
++
++static void resubmit_transfer(struct libusb_transfer *transfer)
++{
++ int ret;
++
++ if ((ret = libusb_submit_transfer(transfer)) == LIBUSB_SUCCESS)
++ return;
++
++ sr_err("%s: %s", __func__, libusb_error_name(ret));
++ free_transfer(transfer);
++}
++
++static void la_send_data_proc(struct sr_dev_inst *sdi,
++ uint8_t *data, size_t length, size_t sample_width)
++{
++ const struct sr_datafeed_logic logic = {
++ .length = length,
++ .unitsize = sample_width,
++ .data = data
++ };
++
++ const 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)
++{
++ struct sr_dev_inst *sdi = transfer->user_data;
++ struct dev_context *devc = sdi->priv;
++ gboolean packet_has_error = FALSE;
++ unsigned int num_samples;
++ int trigger_offset, cur_sample_count, unitsize, processed_samples;
++ int pre_trigger_samples;
++
++ /*
++ * If acquisition has already ended, just free any queued up
++ * transfer that come in.
++ */
++ if (devc->acq_aborted) {
++ free_transfer(transfer);
++ return;
++ }
++
++ sr_dbg("receive_transfer(): status %s received %d bytes.",
++ libusb_error_name(transfer->status), transfer->actual_length);
++
++ /* Save incoming transfer before reusing the transfer struct. */
++ unitsize = 1+(((1<<devc->logic_pattern)-1)>>3);
++ cur_sample_count = transfer->actual_length * 8 / (1<<devc->logic_pattern);
++ processed_samples = 0;
++
++ switch (transfer->status) {
++ case LIBUSB_TRANSFER_NO_DEVICE:
++ sipeed_slogic_acquisition_stop(sdi);
++ free_transfer(transfer);
++ return;
++ case LIBUSB_TRANSFER_COMPLETED:
++ case LIBUSB_TRANSFER_TIMED_OUT: /* We may have received some data though. */
++ break;
++ default:
++ packet_has_error = TRUE;
++ break;
++ }
++
++ if (transfer->actual_length == 0 || packet_has_error) {
++ devc->empty_transfer_count++;
++ if (devc->empty_transfer_count > MAX_EMPTY_TRANSFERS) {
++ /*
++ * The FX2 gave up. End the acquisition, the frontend
++ * will work out that the samplecount is short.
++ */
++ sipeed_slogic_acquisition_stop(sdi);
++ free_transfer(transfer);
++ } else {
++ resubmit_transfer(transfer);
++ }
++ return;
++ } else {
++ devc->empty_transfer_count = 0;
++ }
++
++ uint8_t real_bits = 1<<devc->logic_pattern;
++check_trigger:
++ if (real_bits < 8) {
++ for (int i = cur_sample_count-1; i>=0; i--) {
++ ((uint8_t *)transfer->buffer)[i] =
++ (((uint8_t *)transfer->buffer)[i/real_bits] >> (real_bits-1-i%real_bits))
++ & ((1<<real_bits)-1);
++ }
++ }
++ if (devc->trigger_fired) {
++ if (!devc->limit_samples || devc->sent_samples < devc->limit_samples) {
++ /* Send the incoming transfer to the session bus. */
++ num_samples = cur_sample_count - processed_samples;
++ if (devc->limit_samples && devc->sent_samples + num_samples > devc->limit_samples)
++ num_samples = devc->limit_samples - devc->sent_samples;
++
++ la_send_data_proc(sdi, (uint8_t *)transfer->buffer
++ + processed_samples * unitsize,
++ num_samples * unitsize, unitsize);
++ devc->sent_samples += num_samples;
++ processed_samples += num_samples;
++ }
++ } else {
++ trigger_offset = soft_trigger_logic_check(devc->stl,
++ transfer->buffer + processed_samples * unitsize,
++ transfer->actual_length - processed_samples * unitsize,
++ &pre_trigger_samples);
++ if (trigger_offset > -1) {
++ std_session_send_df_frame_begin(sdi);
++ devc->sent_samples += pre_trigger_samples;
++ num_samples = cur_sample_count - processed_samples - trigger_offset;
++ if (devc->limit_samples &&
++ devc->sent_samples + num_samples > devc->limit_samples)
++ num_samples = devc->limit_samples - devc->sent_samples;
++
++ la_send_data_proc(sdi, (uint8_t *)transfer->buffer
++ + processed_samples * unitsize
++ + trigger_offset * unitsize,
++ num_samples * unitsize, unitsize);
++ devc->sent_samples += num_samples;
++ processed_samples += trigger_offset + num_samples;
++
++ devc->trigger_fired = TRUE;
++ }
++ }
++
++ const int frame_ended = devc->limit_samples && (devc->sent_samples >= devc->limit_samples);
++ const int final_frame = devc->limit_frames && (devc->num_frames >= (devc->limit_frames - 1));
++
++ if (frame_ended) {
++ devc->num_frames++;
++ devc->sent_samples = 0;
++ devc->trigger_fired = FALSE;
++ std_session_send_df_frame_end(sdi);
++
++ /* There may be another trigger in the remaining data, go back and check for it */
++ if (processed_samples < cur_sample_count) {
++ /* Reset the trigger stage */
++ if (devc->stl)
++ devc->stl->cur_stage = 0;
++ else {
++ std_session_send_df_frame_begin(sdi);
++ devc->trigger_fired = TRUE;
++ }
++ if (!final_frame)
++ goto check_trigger;
++ }
++ }
++ if (frame_ended && final_frame) {
++ sipeed_slogic_acquisition_stop(sdi);
++ free_transfer(transfer);
++ } else
++ resubmit_transfer(transfer);
++}
++
++#define USB_TIMEOUT 100
++
++static int command_start_acquisition(const struct sr_dev_inst *sdi)
++{
++ struct dev_context *devc;
++ struct sr_usb_dev_inst *usb;
++ uint64_t samplerate;
++ struct cmd_start_acquisition cmd;
++ int ret;
++
++ devc = sdi->priv;
++ usb = sdi->conn;
++ samplerate = devc->cur_samplerate;
++
++ /* Compute the sample rate. */
++ if (0) {
++ sr_err("Unable to sample at %" PRIu64 "Hz "
++ "when collecting 16-bit samples.", samplerate);
++ return SR_ERR;
++ }
++
++ cmd.sample_rate_h = cmd.sample_rate_l = 0;
++
++ if ((SR_MHZ(160) % samplerate) != 0) {
++ sr_err("Unable to sample at %" PRIu64 "Hz.", samplerate);
++ return SR_ERR;
++ }
++
++ sr_dbg("SLogic samplerate = %d, clocksource = %sMHz.", samplerate, "160");
++
++ samplerate /= SR_KHZ(1);
++ cmd.sample_rate_h = (samplerate >> 8) & 0xff;
++ cmd.sample_rate_l = samplerate & 0xff;
++
++ /* Send the control message. */
++ ret = libusb_control_transfer(usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
++ LIBUSB_ENDPOINT_OUT, CMD_START, 0x0000, 0x0000,
++ (unsigned char *)&cmd, sizeof(cmd), USB_TIMEOUT);
++ if (ret < 0) {
++ sr_err("Unable to send start command: %s.",
++ libusb_error_name(ret));
++ return SR_ERR;
++ }
++
++ return SR_OK;
++}
+diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
+index 84e31087..12f06396 100644
+--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
++++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
+@@ -28,6 +28,18 @@
+
+ #define LOG_PREFIX "sipeed-slogic-analyzer"
+
++#define NUM_SIMUL_TRANSFERS 32
++#define MAX_EMPTY_TRANSFERS (NUM_SIMUL_TRANSFERS * 2)
++
++#define DBG_VAL(expr) do {\
++ __typeof((expr)) _expr = (expr);\
++ sr_warn("[%u]%s<"#expr"> i:%d\tu:%u\tf:%f\th:%x", __LINE__, __func__, \
++ *(long*)(&_expr), \
++ *(unsigned long*)(&_expr), \
++ *(float*)(&_expr), \
++ *(unsigned long*)(&_expr)); \
++}while(0)
++
+ struct slogic_profile {
+ uint16_t vid;
+ uint16_t pid;
+@@ -36,14 +48,74 @@ struct slogic_profile {
+ struct dev_context {
+ struct slogic_profile *profile;
+
+- uint64_t cur_samplerate;
+ uint64_t limit_samples;
+- int logic_pattern;
++ uint64_t limit_frames;
++
++ gboolean acq_aborted;
++ gboolean trigger_fired;
++ struct soft_trigger_logic *stl;
++
++ uint64_t num_frames;
++ uint64_t sent_samples;
++ int submitted_transfers;
++ int empty_transfer_count;
++
++ uint64_t num_transfers;
++ struct libusb_transfer **transfers;
++
++ uint64_t cur_samplerate;
++ int logic_pattern;
+ double voltage_threshold[2];
+ /* Triggers */
+ uint64_t capture_ratio;
+ };
+
++#pragma pack(push, 1)
++struct cmd_start_acquisition {
++ uint8_t sample_rate_l;
++ uint8_t sample_rate_h;
++};
++#pragma pack(pop)
++
++/* Protocol commands */
++#define CMD_START 0xb1
++
+ SR_PRIV int sipeed_slogic_analyzer_receive_data(int fd, int revents, void *cb_data);
++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)
++{
++ size_t channel_counts = 1 << (devc->logic_pattern);
++ return (devc->cur_samplerate * channel_counts)/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 512.
++ */
++ size_t s = 10 * to_bytes_per_ms(devc);
++ size_t pack_size = 512;
++ return (s + (pack_size-1)) & ~(pack_size-1);
++}
++
++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 n = (500 * to_bytes_per_ms(devc) / get_buffer_size(devc));
++ if (n > NUM_SIMUL_TRANSFERS)
++ return NUM_SIMUL_TRANSFERS;
++ return n;
++}
++
++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 + timeout / 4; /* Leave a headroom of 25% percent. */
++}
+
+ #endif
+--
+2.43.0
+
+From e834484756e6e601464da0b9b5532409abb05255 Mon Sep 17 00:00:00 2001
+From: taorye <taorye@outlook.com>
+Date: Wed, 22 Feb 2023 10:14:24 +0800
+Subject: [PATCH 4/8] feat: now support max 160Msps(2ch)
+
+---
+ src/hardware/sipeed-slogic-analyzer/api.c | 16 ++++++------
+ .../sipeed-slogic-analyzer/protocol.c | 25 ++++++++++---------
+ .../sipeed-slogic-analyzer/protocol.h | 1 +
+ 3 files changed, 23 insertions(+), 19 deletions(-)
+
+diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
+index 4038a6e2..a0aefd96 100644
+--- a/src/hardware/sipeed-slogic-analyzer/api.c
++++ b/src/hardware/sipeed-slogic-analyzer/api.c
+@@ -60,13 +60,13 @@ static const int32_t trigger_matches[] = {
+ };
+
+ static const uint64_t samplerates[] = {
+- SR_KHZ(20),
+- SR_KHZ(25),
+- SR_KHZ(50),
+- SR_KHZ(100),
+- SR_KHZ(200),
+- SR_KHZ(250),
+- SR_KHZ(500),
++ // SR_KHZ(20),
++ // SR_KHZ(25),
++ // SR_KHZ(50),
++ // SR_KHZ(100),
++ // SR_KHZ(200),
++ // SR_KHZ(250),
++ // SR_KHZ(500),
+ /* 160M = 2*2*2*2*2*5M */
+ SR_MHZ(1),
+ SR_MHZ(2),
+@@ -79,6 +79,8 @@ static const uint64_t samplerates[] = {
+ SR_MHZ(32),
+ SR_MHZ(40),
+ /* must less than 47MHZ */
++ SR_MHZ(80),
++ SR_MHZ(160),
+ };
+
+ static struct sr_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 f232c25f..434e3bc5 100644
+--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
++++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
+@@ -93,7 +93,7 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
+ }
+ size_t size = get_buffer_size(devc);
+ for (int i = 0; i < devc->num_transfers; i++) {
+- uint8_t *buf = g_try_malloc(size * 8); /* max 8xu1 */
++ uint8_t *buf = g_try_malloc(size * (8+1)); /* max 8xu1 */
+ if (!buf) {
+ sr_err("USB transfer buffer malloc failed.");
+ return SR_ERR_MALLOC;
+@@ -274,9 +274,10 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer)
+ check_trigger:
+ if (real_bits < 8) {
+ for (int i = cur_sample_count-1; i>=0; i--) {
+- ((uint8_t *)transfer->buffer)[i] =
+- (((uint8_t *)transfer->buffer)[i/real_bits] >> (real_bits-1-i%real_bits))
+- & ((1<<real_bits)-1);
++
++ ((uint8_t *)transfer->buffer+get_buffer_size(devc))[i] =
++ (((uint8_t *)transfer->buffer)[i/(8/real_bits)] >> (real_bits*(i%(8/real_bits))))
++ &((1<<real_bits)-1);
+ }
+ }
+ if (devc->trigger_fired) {
+@@ -286,7 +287,7 @@ check_trigger:
+ if (devc->limit_samples && devc->sent_samples + num_samples > devc->limit_samples)
+ num_samples = devc->limit_samples - devc->sent_samples;
+
+- la_send_data_proc(sdi, (uint8_t *)transfer->buffer
++ la_send_data_proc(sdi, (uint8_t *)transfer->buffer + (real_bits<8?get_buffer_size(devc):0)
+ + processed_samples * unitsize,
+ num_samples * unitsize, unitsize);
+ devc->sent_samples += num_samples;
+@@ -305,7 +306,7 @@ check_trigger:
+ devc->sent_samples + num_samples > devc->limit_samples)
+ num_samples = devc->limit_samples - devc->sent_samples;
+
+- la_send_data_proc(sdi, (uint8_t *)transfer->buffer
++ la_send_data_proc(sdi, (uint8_t *)transfer->buffer + (real_bits<8?get_buffer_size(devc):0)
+ + processed_samples * unitsize
+ + trigger_offset * unitsize,
+ num_samples * unitsize, unitsize);
+@@ -351,13 +352,14 @@ static int command_start_acquisition(const struct sr_dev_inst *sdi)
+ {
+ struct dev_context *devc;
+ struct sr_usb_dev_inst *usb;
+- uint64_t samplerate;
++ uint64_t samplerate, samplechannel;
+ struct cmd_start_acquisition cmd;
+ int ret;
+
+ devc = sdi->priv;
+ usb = sdi->conn;
+ samplerate = devc->cur_samplerate;
++ samplechannel = 1<<devc->logic_pattern;
+
+ /* Compute the sample rate. */
+ if (0) {
+@@ -366,18 +368,17 @@ static int command_start_acquisition(const struct sr_dev_inst *sdi)
+ return SR_ERR;
+ }
+
+- cmd.sample_rate_h = cmd.sample_rate_l = 0;
+-
+- if ((SR_MHZ(160) % samplerate) != 0) {
++ if ((SR_MHZ(160) % samplerate) != 0 || samplechannel * samplerate > 40 * 8 * 1000 * 1000) {
+ sr_err("Unable to sample at %" PRIu64 "Hz.", samplerate);
+ return SR_ERR;
+ }
+
+- sr_dbg("SLogic samplerate = %d, clocksource = %sMHz.", samplerate, "160");
++ sr_dbg("SLogic samplerate(%dch) = %d, clocksource = %sMHz.", samplechannel, samplerate, "160");
+
+- samplerate /= SR_KHZ(1);
++ samplerate /= SR_MHZ(1);
+ cmd.sample_rate_h = (samplerate >> 8) & 0xff;
+ cmd.sample_rate_l = samplerate & 0xff;
++ cmd.sample_channel = samplechannel;
+
+ /* Send the control message. */
+ ret = libusb_control_transfer(usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR |
+diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.h b/src/hardware/sipeed-slogic-analyzer/protocol.h
+index 12f06396..92da5f74 100644
+--- a/src/hardware/sipeed-slogic-analyzer/protocol.h
++++ b/src/hardware/sipeed-slogic-analyzer/protocol.h
+@@ -74,6 +74,7 @@ struct dev_context {
+ struct cmd_start_acquisition {
+ uint8_t sample_rate_l;
+ uint8_t sample_rate_h;
++ uint8_t sample_channel;
+ };
+ #pragma pack(pop)
+
+--
+2.43.0
+
+From 114f8a57495227fee56e03ac4917dec4017c05ce Mon Sep 17 00:00:00 2001
+From: taorye <taorye@outlook.com>
+Date: Wed, 26 Jul 2023 18:16:44 +0800
+Subject: [PATCH 5/8] fix: limit samplerate and auto fit channel and ...
+
+enable to reconnect by rescan and add new samplerates
+---
+ src/hardware/sipeed-slogic-analyzer/api.c | 55 +++++++++++++------
+ .../sipeed-slogic-analyzer/protocol.c | 25 +++++++--
+ 2 files changed, 58 insertions(+), 22 deletions(-)
+
+diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
+index a0aefd96..eefb69d1 100644
+--- a/src/hardware/sipeed-slogic-analyzer/api.c
++++ b/src/hardware/sipeed-slogic-analyzer/api.c
+@@ -60,13 +60,6 @@ static const int32_t trigger_matches[] = {
+ };
+
+ static const uint64_t samplerates[] = {
+- // SR_KHZ(20),
+- // SR_KHZ(25),
+- // SR_KHZ(50),
+- // SR_KHZ(100),
+- // SR_KHZ(200),
+- // SR_KHZ(250),
+- // SR_KHZ(500),
+ /* 160M = 2*2*2*2*2*5M */
+ SR_MHZ(1),
+ SR_MHZ(2),
+@@ -78,8 +71,11 @@ static const uint64_t samplerates[] = {
+ SR_MHZ(20),
+ SR_MHZ(32),
+ SR_MHZ(40),
+- /* must less than 47MHZ */
++ /* x 4ch */
++ SR_MHZ(64),
+ SR_MHZ(80),
++ /* x 2ch */
++ SR_MHZ(128),
+ SR_MHZ(160),
+ };
+
+@@ -87,6 +83,7 @@ static struct sr_dev_driver sipeed_slogic_analyzer_driver_info;
+
+ static GSList *scan(struct sr_dev_driver *di, GSList *options)
+ {
++ // sr_dbg("Enter func %s with di: %p, options: %p", __func__, di, options);
+ struct drv_context *drvc;
+ GSList *devices;
+
+@@ -101,7 +98,7 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
+ const char *conn = NULL;
+ int num_logic_channels = 8;
+ for (GSList *l = options; l; l = l->next) {
+- struct sr_config *src = l->data;DBG_VAL(src->key);
++ struct sr_config *src = l->data;
+ switch (src->key) {
+ case SR_CONF_NUM_LOGIC_CHANNELS:
+ num_logic_channels = g_variant_get_int32(src->data);
+@@ -168,11 +165,13 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options)
+ }
+ // g_slist_free_full(conn_devices, (GDestroyNotify)sr_usb_dev_inst_free);
+
++ // sr_dbg("Leave func %s", __func__);
+ return std_scan_complete(di, devices);
+ }
+
+ static int dev_open(struct sr_dev_inst *sdi)
+ {
++ // sr_dbg("Enter func %s with sdi: %p", __func__, sdi);
+ (void)sdi;
+
+ /* TODO: get handle from sdi->conn and open it. */
+@@ -182,11 +181,11 @@ static int dev_open(struct sr_dev_inst *sdi)
+ struct sr_dev_driver *di = sdi->driver;
+ struct drv_context *drvc = di->context;
+
+- ret = sr_usb_open(drvc->sr_ctx->libusb_ctx, usb);DBG_VAL(ret);
++ ret = sr_usb_open(drvc->sr_ctx->libusb_ctx, usb);
+ if (ret != SR_OK)
+ return ret;
+
+- ret = libusb_claim_interface(usb->devhdl, 0);DBG_VAL(ret);
++ ret = libusb_claim_interface(usb->devhdl, 0);
+ if (ret != LIBUSB_SUCCESS) {
+ switch (ret) {
+ case LIBUSB_ERROR_BUSY:
+@@ -211,11 +210,13 @@ static int dev_open(struct sr_dev_inst *sdi)
+ devc->limit_frames = 1;
+ devc->capture_ratio = 0;
+
++ // sr_dbg("Leave func %s", __func__);
+ return std_dummy_dev_open(sdi);
+ }
+
+ static int dev_close(struct sr_dev_inst *sdi)
+ {
++ // sr_dbg("Enter func %s with sdi: %p", __func__, sdi);
+ (void)sdi;
+
+ /* TODO: get handle from sdi->conn and close it. */
+@@ -223,21 +224,23 @@ static int dev_close(struct sr_dev_inst *sdi)
+ struct sr_usb_dev_inst *usb = sdi->conn;
+ struct dev_context *devc= sdi->priv;
+
+- ret = libusb_release_interface(usb->devhdl, 0);DBG_VAL(ret);
++ ret = libusb_release_interface(usb->devhdl, 0);
+ if (ret != LIBUSB_SUCCESS) {
+ sr_err("Unable to release Interface for %s.",
+ libusb_error_name(ret));
+- return SR_ERR;
++ // return SR_ERR;
+ }
+
+ sr_usb_close(usb);
+
++ // sr_dbg("Leave func %s", __func__);
+ 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)
+ {
++ // sr_dbg("Enter func %s with key: %u, data: %p, sdi: %p, cg: %p", __func__, key, data, sdi, cg);
+ int ret;
+
+ (void)sdi;
+@@ -247,7 +250,7 @@ static int config_get(uint32_t key, GVariant **data,
+ struct sr_usb_dev_inst *usb = sdi->conn;
+ struct dev_context *devc= sdi->priv;
+ struct sr_channel *ch;
+- ret = SR_OK;DBG_VAL(key);
++ ret = SR_OK;
+ switch (key) {
+ /* TODO */
+ case SR_CONF_CONN:
+@@ -284,12 +287,14 @@ static int config_get(uint32_t key, GVariant **data,
+ return SR_ERR_NA;
+ }
+
++ // sr_dbg("Leave func %s", __func__);
+ return ret;
+ }
+
+ static int config_set(uint32_t key, GVariant *data,
+ const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
+ {
++ sr_dbg("Enter func %s with key: %u, data: %p, sdi: %p, cg: %p", __func__, key, data, sdi, cg);
+ int ret;
+
+ (void)sdi;
+@@ -298,13 +303,24 @@ static int config_set(uint32_t key, GVariant *data,
+
+ struct dev_context *devc= sdi->priv;
+ int logic_pattern;
+- ret = SR_OK;DBG_VAL(key);
++ ret = SR_OK;
+ switch (key) {
+ /* TODO */
+ case SR_CONF_SAMPLERATE:
+ if (std_u64_idx(data, ARRAY_AND_SIZE(samplerates)) < 0)
+ return SR_ERR_ARG;
+ devc->cur_samplerate = g_variant_get_uint64(data);
++ if (devc->cur_samplerate >= SR_MHZ(128)) {
++ sr_dbg("set 2 ch");
++ sdi->driver->config_set(SR_CONF_PATTERN_MODE,
++ g_variant_new_string(logic_pattern_str[1]),
++ sdi, sdi->channel_groups->data);
++ } else if (devc->cur_samplerate >= SR_MHZ(64)) {
++ sr_dbg("set 4 ch");
++ sdi->driver->config_set(SR_CONF_PATTERN_MODE,
++ g_variant_new_string(logic_pattern_str[2]),
++ sdi, sdi->channel_groups->data);
++ }
+ break;
+ case SR_CONF_LIMIT_SAMPLES:
+ devc->limit_samples = g_variant_get_uint64(data);
+@@ -316,8 +332,7 @@ static int config_set(uint32_t key, GVariant *data,
+ if (logic_pattern < 0)
+ return SR_ERR_ARG;
+ if (((struct sr_channel *)cg->channels->data)->type == SR_CHANNEL_LOGIC) {
+- sr_dbg("Setting logic pattern to %s",
+- logic_pattern_str[logic_pattern]);
++ // sr_dbg("Setting logic pattern to %s", logic_pattern_str[logic_pattern]);
+ devc->logic_pattern = logic_pattern;
+ /* Might as well do this now, these are static. */
+ size_t idx = 0;
+@@ -341,12 +356,14 @@ static int config_set(uint32_t key, GVariant *data,
+ ret = SR_ERR_NA;
+ }
+
++ // sr_dbg("Leave func %s", __func__);
+ return ret;
+ }
+
+ static int config_list(uint32_t key, GVariant **data,
+ const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
+ {
++ // sr_dbg("Enter func %s with key: %x, data: %p, sdi: %p, cg: %p", __func__, key, data, sdi, cg);
+ int ret;
+
+ (void)sdi;
+@@ -354,7 +371,7 @@ static int config_list(uint32_t key, GVariant **data,
+ (void)cg;
+
+ struct sr_channel *ch;
+- ret = SR_OK;DBG_VAL(key);
++ ret = SR_OK;
+ switch (key) {
+ /* TODO */
+ case SR_CONF_SCAN_OPTIONS:
+@@ -370,6 +387,7 @@ static int config_list(uint32_t key, GVariant **data,
+ case SR_CONF_SAMPLERATE:
+ *data = std_gvar_samplerates(ARRAY_AND_SIZE(samplerates));
+ break;
++ // sr_dbg("Leave func %s", __func__);
+ case SR_CONF_TRIGGER_MATCH:
+ *data = std_gvar_array_i32(ARRAY_AND_SIZE(trigger_matches));
+ break;
+@@ -386,6 +404,7 @@ static int config_list(uint32_t key, GVariant **data,
+ return SR_ERR_NA;
+ }
+
++ // sr_dbg("Leave func %s", __func__);
+ return ret;
+ }
+
+diff --git a/src/hardware/sipeed-slogic-analyzer/protocol.c b/src/hardware/sipeed-slogic-analyzer/protocol.c
+index 434e3bc5..759be36b 100644
+--- a/src/hardware/sipeed-slogic-analyzer/protocol.c
++++ b/src/hardware/sipeed-slogic-analyzer/protocol.c
+@@ -25,6 +25,7 @@ static int command_start_acquisition(const struct sr_dev_inst *sdi);
+
+ SR_PRIV int sipeed_slogic_analyzer_receive_data(int fd, int revents, void *cb_data)
+ {
++ // sr_dbg("Enter func %s", __func__);
+ const struct sr_dev_inst *sdi;
+ struct dev_context *devc;
+ struct drv_context *drvc;
+@@ -50,11 +51,13 @@ SR_PRIV int sipeed_slogic_analyzer_receive_data(int fd, int revents, void *cb_da
+ };
+ libusb_handle_events_timeout(drvc->sr_ctx->libusb_ctx, &tv);
+
++ // sr_dbg("Leave func %s", __func__);
+ 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. */
+
+@@ -124,11 +127,13 @@ SR_PRIV int sipeed_slogic_acquisition_start(const struct sr_dev_inst *sdi)
+ return ret;
+ }
+
++ // sr_dbg("Leave func %s", __func__);
+ return SR_OK;
+ }
+
+ SR_PRIV int sipeed_slogic_acquisition_stop(struct sr_dev_inst *sdi)
+ {
++ // sr_dbg("Enter func %s", __func__);
+ /* TODO: stop acquisition. */
+
+ (void)sdi;DBG_VAL(sdi);
+@@ -139,11 +144,13 @@ SR_PRIV int sipeed_slogic_acquisition_stop(struct sr_dev_inst *sdi)
+ if (devc->transfers[i])
+ libusb_cancel_transfer(devc->transfers[i]);
+ }
++ // sr_dbg("Leave func %s", __func__);
+ return SR_OK;
+ }
+
+ static void finish_acquisition(struct sr_dev_inst *sdi)
+ {
++ // sr_dbg("Enter func %s", __func__);
+ struct dev_context *devc;
+
+ devc = sdi->priv;
+@@ -159,10 +166,12 @@ static void finish_acquisition(struct sr_dev_inst *sdi)
+ soft_trigger_logic_free(devc->stl);
+ devc->stl = NULL;
+ }
++ // sr_dbg("Leave func %s", __func__);
+ }
+
+ static void free_transfer(struct libusb_transfer *transfer)
+ {
++ // sr_dbg("Enter func %s", __func__);
+ struct sr_dev_inst *sdi;
+ struct dev_context *devc;
+ unsigned int i;
+@@ -184,10 +193,12 @@ static void free_transfer(struct libusb_transfer *transfer)
+ devc->submitted_transfers--;
+ if (devc->submitted_transfers == 0)
+ finish_acquisition(sdi);
++ // sr_dbg("Leave func %s", __func__);
+ }
+
+ static void resubmit_transfer(struct libusb_transfer *transfer)
+ {
++ // sr_dbg("Enter func %s", __func__);
+ int ret;
+
+ if ((ret = libusb_submit_transfer(transfer)) == LIBUSB_SUCCESS)
+@@ -195,11 +206,13 @@ static void resubmit_transfer(struct libusb_transfer *transfer)
+
+ sr_err("%s: %s", __func__, libusb_error_name(ret));
+ free_transfer(transfer);
++ // sr_dbg("Leave func %s", __func__);
+ }
+
+ static void la_send_data_proc(struct sr_dev_inst *sdi,
+ uint8_t *data, size_t length, size_t sample_width)
+ {
++ // sr_dbg("Enter func %s", __func__);
+ const struct sr_datafeed_logic logic = {
+ .length = length,
+ .unitsize = sample_width,
+@@ -212,10 +225,12 @@ static void la_send_data_proc(struct sr_dev_inst *sdi,
+ };
+
+ sr_session_send(sdi, &packet);
++ // sr_dbg("Leave func %s", __func__);
+ }
+
+ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer)
+ {
++ // sr_dbg("Enter func %s", __func__);
+ struct sr_dev_inst *sdi = transfer->user_data;
+ struct dev_context *devc = sdi->priv;
+ gboolean packet_has_error = FALSE;
+@@ -232,8 +247,7 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer)
+ return;
+ }
+
+- sr_dbg("receive_transfer(): status %s received %d bytes.",
+- libusb_error_name(transfer->status), transfer->actual_length);
++ // sr_dbg("receive_transfer(): status %s received %d bytes.", libusb_error_name(transfer->status), transfer->actual_length);
+
+ /* Save incoming transfer before reusing the transfer struct. */
+ unitsize = 1+(((1<<devc->logic_pattern)-1)>>3);
+@@ -344,12 +358,14 @@ check_trigger:
+ free_transfer(transfer);
+ } else
+ resubmit_transfer(transfer);
++ // sr_dbg("Leave func %s", __func__);
+ }
+
+ #define USB_TIMEOUT 100
+
+ static int command_start_acquisition(const struct sr_dev_inst *sdi)
+ {
++ // sr_dbg("Enter func %s", __func__);
+ struct dev_context *devc;
+ struct sr_usb_dev_inst *usb;
+ uint64_t samplerate, samplechannel;
+@@ -368,9 +384,9 @@ static int command_start_acquisition(const struct sr_dev_inst *sdi)
+ return SR_ERR;
+ }
+
+- if ((SR_MHZ(160) % samplerate) != 0 || samplechannel * samplerate > 40 * 8 * 1000 * 1000) {
++ if (samplerate > SR_MHZ(160) || samplechannel * samplerate > SR_MHZ(40 * 8)) {
+ sr_err("Unable to sample at %" PRIu64 "Hz.", samplerate);
+- return SR_ERR;
++ // return SR_ERR;
+ }
+
+ sr_dbg("SLogic samplerate(%dch) = %d, clocksource = %sMHz.", samplechannel, samplerate, "160");
+@@ -390,5 +406,6 @@ static int command_start_acquisition(const struct sr_dev_inst *sdi)
+ return SR_ERR;
+ }
+
++ // sr_dbg("Leave func %s", __func__);
+ return SR_OK;
+ }
+--
+2.43.0
+
+From dc604b7fcabec9ff158bb0de1dec7a7bdc76a7ff Mon Sep 17 00:00:00 2001
+From: Martin Herren <martin.herren@ecorobotix.com>
+Date: Wed, 4 Oct 2023 19:45:03 +0200
+Subject: [PATCH 6/8] [Sipeed SLogic Lite8] Add dependency to libusb
+
+---
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/configure.ac b/configure.ac
+index 68798da1..19f11576 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -358,7 +358,7 @@ SR_DRIVER([SCPI PPS], [scpi-pps])
+ SR_DRIVER([serial DMM], [serial-dmm], [serial_comm])
+ SR_DRIVER([serial LCR], [serial-lcr], [serial_comm])
+ 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])
+--
+2.43.0
+
+From 24978df3a369380466fcb20ced79fae074909e55 Mon Sep 17 00:00:00 2001
+From: Martin Herren <martin.herren@ecorobotix.com>
+Date: Wed, 4 Oct 2023 19:45:34 +0200
+Subject: [PATCH 7/8] [Sipeed SLogic Lite8] Add udev rule
+
+---
+ contrib/60-libsigrok.rules | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/contrib/60-libsigrok.rules b/contrib/60-libsigrok.rules
+index 398ee404..bf812a3b 100644
+--- a/contrib/60-libsigrok.rules
++++ b/contrib/60-libsigrok.rules
+@@ -354,4 +354,7 @@ ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="7016", ENV{ID_SIGROK}="1"
+ ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="7025", ENV{ID_SIGROK}="1"
+ ATTRS{idVendor}=="0c12", ATTRS{idProduct}=="7100", ENV{ID_SIGROK}="1"
+
++# Sipeed SLogic Lite 8
++ATTRS{idVendor}=="359f", ATTRS{idProduct}=="0300", ENV{ID_SIGROK}="1"
++
+ LABEL="libsigrok_rules_end"
+--
+2.43.0
+
+From fe587691af2f86089385a0b145cb2bf2f2e30f5e Mon Sep 17 00:00:00 2001
+From: Martin Herren <martin.herren@ecorobotix.com>
+Date: Wed, 4 Oct 2023 20:12:18 +0200
+Subject: [PATCH 8/8] [Sipeed SLogic Lite8] Fix setting back to 8 channels when
+ selecting 40 MS/s and less from a higher sample rate
+
+---
+ src/hardware/sipeed-slogic-analyzer/api.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/src/hardware/sipeed-slogic-analyzer/api.c b/src/hardware/sipeed-slogic-analyzer/api.c
+index eefb69d1..6f44dadf 100644
+--- a/src/hardware/sipeed-slogic-analyzer/api.c
++++ b/src/hardware/sipeed-slogic-analyzer/api.c
+@@ -320,6 +320,11 @@ static int config_set(uint32_t key, GVariant *data,
+ sdi->driver->config_set(SR_CONF_PATTERN_MODE,
+ g_variant_new_string(logic_pattern_str[2]),
+ sdi, sdi->channel_groups->data);
++ } else {
++ sr_dbg("set 8 ch");
++ sdi->driver->config_set(SR_CONF_PATTERN_MODE,
++ g_variant_new_string(logic_pattern_str[3]),
++ sdi, sdi->channel_groups->data);
+ }
+ break;
+ case SR_CONF_LIMIT_SAMPLES:
+--
+2.43.0
+
diff --git a/PKGBUILD b/PKGBUILD
new file mode 100644
index 000000000000..6b339fcf113a
--- /dev/null
+++ b/PKGBUILD
@@ -0,0 +1,57 @@
+# original PKGBUILD: https://aur.archlinux.org/packages/libsigrok-git
+# Maintainer: yjun <jerrysteve1101 at gmail dot com>
+
+# Sipeed Slogic Analyzer support:
+1. mainline pull request: [sipeed slogic new hardware support #212](https://github.com/sigrokproject/libsigrok/pull/212)
+2. MartinHerren\'s branch: https://github.com/MartinHerren/libsigrok/commits/slogiclite8/
+
+pkgname="libsigrok-sipeed-slogic-git"
+_gitname="libsigrok"
+pkgver=0.2.1.r4311.gda175133
+pkgrel=1
+pkgdesc="Client software that supports various hardware logic analyzers, core library with Sipeed Slogic Analyzer support patches (git version)"
+arch=('armv6h' 'armv7h' 'i686' 'x86_64')
+url="http://www.sigrok.org/wiki/Libsigrok"
+license=('GPL3')
+depends=('libzip' 'libftdi' 'alsa-lib' 'libserialport-git' 'glibmm' 'libieee1284')
+makedepends=('git' 'autoconf-archive' 'doxygen')
+conflicts=("${_gitname}")
+provides=("${_gitname}")
+source=("git://sigrok.org/${_gitname}"
+ 0001-add-sipeed-slogic-analyzer-support.patch
+)
+sha512sums=('SKIP'
+ 'dd05758731b34ed7dac1b7cafa635427759dcb84e0b850b34e64c3e9bd4e4bb4d9bd9b0b6d90d3efbd5b62e001e392770289858c3cbb160c972f1cbd58c4a2c9')
+
+pkgver() {
+ cd "${srcdir}/${_gitname}"
+ git describe --exclude 'libsigrok-unreleased' --long | sed 's/^libsigrok-//;s/\([^-]*-g\)/r\1/;s/-/./g'
+}
+
+prepare() {
+ cd "${srcdir}/${_gitname}"
+ patch -p 1 < ${srcdir}/0001-add-sipeed-slogic-analyzer-support.patch
+}
+
+build() {
+ rm -rf "${srcdir}/build"
+ mkdir -p "${srcdir}/build"
+ cd "${srcdir}/${_gitname}"
+ ./autogen.sh
+
+ cd "${srcdir}/build"
+ echo "CONFIGURE"
+ ../${_gitname}/configure --prefix=/usr --disable-java --disable-ruby
+
+ make
+}
+
+package() {
+ cd "${srcdir}/build"
+
+ make DESTDIR="${pkgdir}" PREFIX=/usr install
+
+ cd ../"${_gitname}"
+ install -Dm 644 'contrib/60-libsigrok.rules' "${pkgdir}/usr/lib/udev/rules.d/60-libsigrok.rules"
+ install -Dm 644 'contrib/61-libsigrok-uaccess.rules' "${pkgdir}/usr/lib/udev/rules.d/61-libsigrok-uaccess.rules"
+}