diff --git a/scopehal/SCPITMCTransport.cpp b/scopehal/SCPITMCTransport.cpp index 0f2ade19..fb2a4ce1 100644 --- a/scopehal/SCPITMCTransport.cpp +++ b/scopehal/SCPITMCTransport.cpp @@ -49,52 +49,31 @@ using namespace std; SCPITMCTransport::SCPITMCTransport(const string& args) : m_devicePath(args) - , m_staging_buf_size(0) - , m_staging_buf(nullptr) - , m_data_in_staging_buf(0) - , m_data_offset(0) - , m_data_depleted(false) - , m_fix_buggy_driver(false) - , m_transfer_size(48) + , m_buf(nullptr) + , m_max_read_size(2032) { - // TODO: add configuration options: - // - set the maximum request size of usbtmc read requests (currently 2032) - // - set timeout value (when using kernel that has usbtmc v2 version) - // - set size of staging buffer (or get rid of it entirely?) + // [:] - // FIXME: currently not used - m_timeout = 1000; + char *dev = strdup(m_devicePath.c_str()); - LogDebug("Connecting to SCPI oscilloscope over USBTMC through %s\n", m_devicePath.c_str()); - - char devicePath[128] = ""; - char transferBufferSize[128] = ""; - char *ptr; - if(2 == sscanf(m_devicePath.c_str(), "%127[^:]:%127s", devicePath, transferBufferSize)) - { - // set size for a buggy tmc firmware - // FIXME: Workaround for Siglent SDS1x04X-E. Max request size is 48 byte. Bug in firmware 8.2.6.1.37R9 ? - m_fix_buggy_driver = true; - m_transfer_size = strtol(transferBufferSize, &ptr, 10); - if(m_transfer_size == 0) - { - LogNotice("USBTMC wrong size value %s\n", transferBufferSize); - return; - } - LogNotice("Set USBTMC transfer size %d bytes. Workaround for buggy firmware.\n", m_transfer_size); + char *colon = strchr(dev, ':'); + if (colon) { + m_max_read_size = atoi(colon + 1); + *colon = '\0'; } - m_handle = open(devicePath, O_RDWR); + LogDebug("Connecting to SCPI oscilloscope over USBTMC through %s, max read size %d\n", dev, (int)m_max_read_size); + + m_handle = open(dev, O_RDWR); if (m_handle <= 0) { - LogError("Couldn't open %s\n", devicePath); + LogError("Couldn't open %s\n", dev); return; } - // Right now, I'm using an internal staging buffer because this code has been copied from the lxi transport driver. - // It's not strictly needed... - m_staging_buf_size = 150000000; - m_staging_buf = new unsigned char[m_staging_buf_size]; + free(dev); + + m_buf = new unsigned char[m_max_read_size+1]; } SCPITMCTransport::~SCPITMCTransport() @@ -102,7 +81,7 @@ SCPITMCTransport::~SCPITMCTransport() if (IsConnected()) close(m_handle); - delete[] m_staging_buf; + delete[] m_buf; } bool SCPITMCTransport::IsConnected() @@ -129,13 +108,7 @@ bool SCPITMCTransport::SendCommand(const string& cmd) return false; LogTrace("Sending %s\n", cmd.c_str()); - int result = write(m_handle, cmd.c_str(), cmd.length()); - - m_data_in_staging_buf = 0; - m_data_offset = 0; - m_data_depleted = false; - return (result == (int)cmd.length()); } @@ -143,21 +116,28 @@ string SCPITMCTransport::ReadReply(bool endOnSemicolon, [[maybe_unused]] functio { string ret; - if (!m_staging_buf || !IsConnected()) + if (!m_buf || !IsConnected()) return ret; - //FIXME: there *has* to be a more efficient way to do this... - char tmp = ' '; - while(true) - { - if (m_data_depleted) + bool done = false; + while (!done) { + int r = read(m_handle, (char *)m_buf, m_max_read_size); + if (r <= 0) { + LogError("Read error\n"); break; - ReadRawData(1, (unsigned char *)&tmp); - if( (tmp == '\n') || ( (tmp == ';') && endOnSemicolon ) ) - break; - else - ret += tmp; + } + m_buf[r] = '\0'; + for (int i=0; i /*progress*/) { - // Data in the staging buffer is assumed to always be a consequence of a SendCommand request. - // Since we fetch all the reply data in one go, once all this data has been fetched, we mark - // the staging buffer as depleted and don't issue a new read until a new SendCommand - // is issued. - - if (!m_staging_buf || !IsConnected()) - return 0; - - if (!m_data_depleted) - { - if (m_data_in_staging_buf == 0) - { - -#if 0 - // This is what we'd use if we could be sure that the installed Linux kernel had - // usbtmc driver v2. - m_data_in_staging_buf = read(m_handle, (char *)m_staging_buf, m_staging_buf_size); -#else - // Split up one potentially large read into a bunch of smaller ones. - // The performance impact of this is pretty small. - const int max_bytes_per_req = 2032; - int i = 0; - int bytes_fetched, bytes_requested; - - do - { - if(m_fix_buggy_driver == false) - { - bytes_requested = (max_bytes_per_req < len) ? max_bytes_per_req : len; - bytes_fetched = read(m_handle, (char *)m_staging_buf + i, m_staging_buf_size); - } - else - { - // limit each request to m_transfer_size - bytes_requested = m_transfer_size; - bytes_fetched = read(m_handle, (char *)m_staging_buf + i, m_transfer_size); - } - i += bytes_fetched; - } while(bytes_fetched == bytes_requested); - - m_data_in_staging_buf = i; -#endif - - if (m_data_in_staging_buf <= 0) - m_data_in_staging_buf = 0; - m_data_offset = 0; - } - - unsigned int data_left = m_data_in_staging_buf - m_data_offset; - if (data_left > 0) - { - int nr_bytes = len > data_left ? data_left : len; - - memcpy(buf, m_staging_buf + m_data_offset, nr_bytes); - - m_data_offset += nr_bytes; + size_t done = 0; + while (done < len) { + size_t todo = len - done; + if (todo > m_max_read_size) + todo = m_max_read_size; + int r = read(m_handle, buf + done, todo); + if (r <= 0) { + LogError("Read error\n"); + break; } - - if (m_data_offset == m_data_in_staging_buf) - m_data_depleted = true; - } - else - { - // When this happens, the SCPIDevice is fetching more data from device than what - // could be expected from the SendCommand that was issued. - LogDebug("ReadRawData: data depleted.\n"); - return 0; + done += r; } return len; diff --git a/scopehal/SCPITMCTransport.h b/scopehal/SCPITMCTransport.h index 4faaf34e..10d030e5 100644 --- a/scopehal/SCPITMCTransport.h +++ b/scopehal/SCPITMCTransport.h @@ -72,15 +72,8 @@ class SCPITMCTransport : public SCPITransport std::string m_devicePath; int m_handle; - int m_timeout; - - int m_staging_buf_size; - unsigned char *m_staging_buf; - int m_data_in_staging_buf; - int m_data_offset; - bool m_data_depleted; - bool m_fix_buggy_driver; - int m_transfer_size; + unsigned char *m_buf; + size_t m_max_read_size; }; #endif