diff --git a/.github/workflows/cmake.yaml b/.github/workflows/cmake.yaml index d3eeee0bd..99db098d8 100644 --- a/.github/workflows/cmake.yaml +++ b/.github/workflows/cmake.yaml @@ -21,11 +21,42 @@ jobs: cache: 'pip' - run: pip install pytest numpy colorama - - uses: awalsh128/cache-apt-pkgs-action@latest + # using a stable action version instead of latest to create/restore cache for now + - uses: awalsh128/cache-apt-pkgs-action@v1.6.1 with: packages: libhdf5-dev qtbase5-dev qt5-qmake libqt5svg5-dev libpng-dev libtiff-dev libfmt-dev version: 1.0 + # verify packages restored from cache are installed. + # This catches incomplete apt installs after cache restore. + - name: Verify apt packages + id: verify_packages + run: | + failed="" + + for pkg in \ + libhdf5-dev \ + qtbase5-dev \ + qt5-qmake \ + libqt5svg5-dev \ + libpng-dev \ + libtiff-dev \ + libfmt-dev + do + if ! dpkg -s "$pkg" >/dev/null 2>&1; then + echo "Missing: $pkg" + failed="$failed $pkg" + fi + done + + + if [ -n "$failed" ]; then + echo "Missing packages after cache restore: $failed. Try deleting the cache and rerunning the workflow." + exit 1 + else + echo "All apt packages are installed" + fi + - name: Configure CMake # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index 96d04205e..138d32e7e 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -20,11 +20,37 @@ jobs: cache: 'pip' - run: pip install pytest numpy colorama pyzmq - - uses: awalsh128/cache-apt-pkgs-action@latest + # using a stable action version instead of latest to create/restore cache for now + - uses: awalsh128/cache-apt-pkgs-action@v1.6.1 with: packages: libhdf5-dev libfmt-dev version: 1.0 + # verify packages restored from cache are installed. + # This catches incomplete apt installs after cache restore. + - name: Verify apt packages + id: verify_packages + run: | + failed="" + + for pkg in \ + libhdf5-dev \ + libfmt-dev + do + if ! dpkg -s "$pkg" >/dev/null 2>&1; then + echo "Missing: $pkg" + failed="$failed $pkg" + fi + done + + if [ -n "$failed" ]; then + echo "Missing packages after cache restore: $failed. Try deleting the cache and rerunning the workflow." + exit 1 + else + echo "All apt packages are installed" + fi + + - name: Configure CMake run: | cmake -B ${{github.workspace}}/build \ diff --git a/slsDetectorServers/eigerDetectorServer/9mhvserial_bf.c b/slsDetectorServers/eigerDetectorServer/9mhvserial_bf.c index f67a46dbf..8cd2c7c96 100644 --- a/slsDetectorServers/eigerDetectorServer/9mhvserial_bf.c +++ b/slsDetectorServers/eigerDetectorServer/9mhvserial_bf.c @@ -1,10 +1,10 @@ // SPDX-License-Identifier: LGPL-3.0-or-other // Copyright (C) 2021 Contributors to the SLS Detector Package +#include "clogger.h" #include "sls/ansi.h" #include -#include // File control definitions -#include // I2C_SLAVE, __u8 reg +#include // File control definitions #include #include // atoi #include // memset @@ -12,80 +12,102 @@ #include /* POSIX terminal control definitions */ #include // read, close -#define PORTNAME "/dev/ttyBF1" -#define GOODBYE 200 -#define BUFFERSIZE 16 -#define I2C_DEVICE_FILE "/dev/i2c-0" -#define I2C_DEVICE_ADDRESS 0x4C -// #define I2C_DEVICE_ADDRESS 0x48 -#define I2C_REGISTER_ADDRESS 0x40 +#define PORTNAME "/dev/ttyBF1" +#define GOODBYE 200 +#define BUFFERSIZE 16 +#define INFILE "/sys/devices/platform/i2c-bfin-twi.0/i2c-0/0-0048/in0_input" +#define OUTFILE "/sys/devices/platform/i2c-bfin-twi.0/i2c-0/0-0048/out0_output" +#define OUTENABLE \ + "/sys/devices/platform/i2c-bfin-twi.0/i2c-0/0-0048/out0_enable" -int i2c_open(const char *file, unsigned int addr) { - - // device file - int fd = open(file, O_RDWR); - if (fd < 0) { - LOG(logERROR, ("Warning: Unable to open file %s\n", file)); +int set_hv(int dac_value) { + if ((dac_value > 255) || (dac_value < 0)) { + LOG(logERROR, ("Invalid dac value %d\n", dac_value)); return -1; } - // device address - if (ioctl(fd, I2C_SLAVE, addr & 0x7F) < 0) { - LOG(logERROR, ("Warning: Unable to set slave address:0x%x \n", addr)); - return -2; - } - return fd; -} + dac_value = dac_value * 10; -int i2c_read() { - - int fd = i2c_open(I2C_DEVICE_FILE, I2C_DEVICE_ADDRESS); - __u8 reg = I2C_REGISTER_ADDRESS & 0xff; - - unsigned char buf = reg; - if (write(fd, &buf, 1) != 1) { - LOG(logERROR, - ("Warning: Unable to write read request to register %d\n", reg)); + FILE *file; + file = fopen(OUTFILE, "w"); + if (file == NULL) { + perror("set_hv:"); + LOG(logERROR, ("Cannot open out0_output file\n")); return -1; } - // read and update value (but old value read out) - if (read(fd, &buf, 1) != 1) { - LOG(logERROR, ("Warning: Unable to read register %d\n", reg)); - return -2; + if (setvbuf(file, NULL, _IONBF, 0) != 0) { + perror("set_hv:"); + LOG(logERROR, ("Cannot disable buffering\n")); + return -1; } - // read again to read the updated value - if (read(fd, &buf, 1) != 1) { - LOG(logERROR, ("Warning: Unable to read register %d\n", reg)); - return -2; + if (fprintf(file, "%d", dac_value) < 1) { + ferror(file); + LOG(logERROR, ("Couldn't write to out0_output file\n")); + return -1; } - close(fd); - return buf; -} - -int i2c_write(unsigned int value) { - - __u8 val = value & 0xff; - - int fd = i2c_open(I2C_DEVICE_FILE, I2C_DEVICE_ADDRESS); - if (fd < 0) - return fd; - - __u8 reg = I2C_REGISTER_ADDRESS & 0xff; - char buf[3]; - buf[0] = reg; - buf[1] = val; - if (write(fd, buf, 2) != 2) { - LOG(logERROR, - ("Warning: Unable to write %d to register %d\n", val, reg)); + if (fclose(file) != 0) { + perror("set_hv:"); + LOG(logERROR, ("Troubles closing out0_output file\n")); return -1; } - - close(fd); return 0; } +int enable_hv(int val) { + if ((val > 1) || (val < 0)) + return -1; + FILE *file; + file = fopen(OUTENABLE, "w"); + if (file == NULL) { + perror("enable_hv:"); + LOG(logERROR, ("Cannot open out0_enable file\n")); + return -1; + } + if (setvbuf(file, NULL, _IONBF, 0) != 0) { + perror("enable_hv:"); + LOG(logERROR, ("Cannot disable buffering\n")); + return -1; + } + if (fprintf(file, "%d", val) < 1) { + ferror(file); + LOG(logERROR, ("Couldn't write to out0_enable file\n")); + return -1; + } + if (fclose(file) != 0) { + perror("enable_hv:"); + LOG(logERROR, ("Troubles closing out0_enable file\n")); + return -1; + } + return 0; +} + +int get_hv() { + int value; + FILE *file; + file = fopen(INFILE, "r"); + if (file == NULL) { + perror("get_hv:"); + LOG(logERROR, ("Cannot open in0_input file\n")); + return -1; + } + if (fscanf(file, "%d", &value) < 1) { + ferror(file); + LOG(logERROR, ("Couldn't read from in0_input file\n")); + return -1; + } + if (fclose(file) != 0) { + perror("get_hv:"); + LOG(logERROR, ("Troubles closing out0_enable file\n")); + return -1; + } + return value / 10; +} + int main(int argc, char *argv[]) { + enable_hv(0); + set_hv(0); + int fd = open(PORTNAME, O_RDWR | O_NOCTTY | O_SYNC); if (fd < 0) { LOG(logERROR, ("Warning: Unable to open port %s\n", PORTNAME)); @@ -126,7 +148,7 @@ int main(int argc, char *argv[]) { int ival = 0; char buffer[BUFFERSIZE]; memset(buffer, 0, BUFFERSIZE); - buffer[BUFFERSIZE - 1] = '\n'; + // buffer[BUFFERSIZE - 1] = '\n'; LOG(logINFO, ("Ready...\n")); while (ret != GOODBYE) { @@ -149,35 +171,51 @@ int main(int argc, char *argv[]) { } // ok/ fail memset(buffer, 0, BUFFERSIZE); - buffer[BUFFERSIZE - 1] = '\n'; - if (i2c_write(ival) < 0) - strcpy(buffer, "fail "); + // buffer[BUFFERSIZE - 1] = '\n'; + + if (set_hv(ival) < 0) + strcpy(buffer, "fail\n"); + else if (enable_hv(ival > 0 ? 1 : 0) < 0) + strcpy(buffer, "fail\n"); else - strcpy(buffer, "success "); + strcpy(buffer, "success\n"); + /* + if (i2c_write(ival) < 0) + strcpy(buffer, "fail "); + else + strcpy(buffer, "success "); + */ LOG(logINFO, ("Sending: '%s'\n", buffer)); - n = write(fd, buffer, BUFFERSIZE); + n = write(fd, buffer, strlen(buffer)); // BUFFERSIZE); LOG(logDEBUG1, ("Sent %d Bytes\n", n)); break; case 'g': - ival = i2c_read(); - // ok/ fail - memset(buffer, 0, BUFFERSIZE); - buffer[BUFFERSIZE - 1] = '\n'; + ival = get_hv(); if (ival < 0) - strcpy(buffer, "fail "); + strcpy(buffer, "fail\n"); else - strcpy(buffer, "success "); - n = write(fd, buffer, BUFFERSIZE); + strcpy(buffer, "success\n"); + /* + ival = i2c_read(); + // ok/ fail + memset(buffer, 0, BUFFERSIZE); + buffer[BUFFERSIZE - 1] = '\n'; + if (ival < 0) + strcpy(buffer, "fail "); + else + strcpy(buffer, "success "); + */ + n = write(fd, buffer, strlen(buffer)); // BUFFERSIZE); LOG(logINFO, ("Sending: '%s'\n", buffer)); LOG(logDEBUG1, ("Sent %d Bytes\n", n)); // value memset(buffer, 0, BUFFERSIZE); - buffer[BUFFERSIZE - 1] = '\n'; + // buffer[BUFFERSIZE - 1] = '\n'; if (ival >= 0) { LOG(logINFO, ("Sending: '%d'\n", ival)); - sprintf(buffer, "%d ", ival); - n = write(fd, buffer, BUFFERSIZE); + sprintf(buffer, "%d\n", ival); + n = write(fd, buffer, strlen(buffer)); // BUFFERSIZE); LOG(logINFO, ("Sent %d Bytes\n", n)); } else LOG(logERROR, ("%s\n", buffer)); diff --git a/slsDetectorServers/eigerDetectorServer/Makefile b/slsDetectorServers/eigerDetectorServer/Makefile index f7f2be00a..950547c7d 100755 --- a/slsDetectorServers/eigerDetectorServer/Makefile +++ b/slsDetectorServers/eigerDetectorServer/Makefile @@ -41,9 +41,9 @@ $(PROGS): $(OBJS) hv9m_blackfin_server:9mhvserial_bf.c - $(BLACKFIN_CC) -o hv9m_blackfin_server 9mhvserial_bf.c -Wall #-DVERBOSE + $(BLACKFIN_CC) $(CFLAGS) -o hv9m_blackfin_server 9mhvserial_bf.c -Wall #-DVERBOSE mv hv9m_blackfin_server $(DESTDIR) - rm hv9m_blackfin_server.gdb $(main_src)*.o $(md5_dir)*.o + rm hv9m_blackfin_server.gdb clean: rm -rf $(DESTDIR)/$(PROGS) *.o $(DESTDIR)/hv9m_blackfin_server $(main_src)*.o $(md5_dir)*.o diff --git a/slsSupportLib/src/ClientSocket.cpp b/slsSupportLib/src/ClientSocket.cpp index 6dc6aac42..fe62d8208 100644 --- a/slsSupportLib/src/ClientSocket.cpp +++ b/slsSupportLib/src/ClientSocket.cpp @@ -27,8 +27,8 @@ ClientSocket::ClientSocket(std::string stype, const std::string &host, if (getaddrinfo(host.c_str(), nullptr, &hints, &result) != 0) { - - auto msg = fmt::format("Cannot resolve {} hostname: '{}'", to_lower(socketType), host); + auto msg = fmt::format("Cannot resolve {} hostname: '{}'", + to_lower(socketType), host); throwError(msg); } @@ -43,9 +43,8 @@ ClientSocket::ClientSocket(std::string stype, const std::string &host, if (::connect(getSocketId(), (struct sockaddr *)&serverAddr, sizeof(serverAddr)) != 0) { freeaddrinfo(result); - auto msg = fmt::format( - "Cannot connect to {} on {}:{}\n", - to_lower(socketType), host, port); + auto msg = fmt::format("Cannot connect to {} on {}:{}\n", + to_lower(socketType), host, port); throwError(msg); } @@ -58,7 +57,8 @@ ClientSocket::ClientSocket(std::string sType, struct sockaddr_in addr) if (::connect(getSocketId(), (struct sockaddr *)&addr, sizeof(addr)) != 0) { char address[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &addr.sin_addr, address, INET_ADDRSTRLEN); - auto msg = fmt::format("Cannot connect to {} on {}:{}", to_lower(socketType), address, addr.sin_port); + auto msg = fmt::format("Cannot connect to {} on {}:{}", + to_lower(socketType), address, addr.sin_port); throwError(msg); } } @@ -99,7 +99,8 @@ void ClientSocket::readReply(int &ret, void *retval, size_t retval_size) { } // debugging catch (SocketError &e) { - auto msg = fmt::format("While reading reply from {} {}", to_lower(socketType), e.what()); + auto msg = fmt::format("While reading reply from {} {}", + to_lower(socketType), e.what()); throwError(msg); } } diff --git a/slsSupportLib/src/DataSocket.cpp b/slsSupportLib/src/DataSocket.cpp index a8b4d2bfd..7979f9d70 100644 --- a/slsSupportLib/src/DataSocket.cpp +++ b/slsSupportLib/src/DataSocket.cpp @@ -113,10 +113,9 @@ int DataSocket::Send(const void *buffer, size_t size) { #endif Timer timer; while (bytes_sent < bytes_expected) { - this_send = ::send( - getSocketId(), - reinterpret_cast(buffer) + bytes_sent, - bytes_expected - bytes_sent, send_flags); + this_send = ::send(getSocketId(), + reinterpret_cast(buffer) + bytes_sent, + bytes_expected - bytes_sent, send_flags); if (this_send < 0 && errno == EINTR) continue; // interrupted by a signal, retry if (this_send <= 0) diff --git a/slsSupportLib/src/string_utils.cpp b/slsSupportLib/src/string_utils.cpp index 68e389c99..36d161e4e 100644 --- a/slsSupportLib/src/string_utils.cpp +++ b/slsSupportLib/src/string_utils.cpp @@ -78,7 +78,7 @@ std::pair ParseHostPort(const std::string &s) { std::string to_lower(const std::string &s) { std::string result = s; std::transform(result.begin(), result.end(), result.begin(), - [](unsigned char c) { return std::tolower(c); }); + [](unsigned char c) { return std::tolower(c); }); return result; } diff --git a/slsSupportLib/tests/test-Sockets.cpp b/slsSupportLib/tests/test-Sockets.cpp index 211df5858..897ed4e65 100644 --- a/slsSupportLib/tests/test-Sockets.cpp +++ b/slsSupportLib/tests/test-Sockets.cpp @@ -30,11 +30,8 @@ std::vector echo_server(uint16_t port, size_t bytes_to_send, std::vector buffer(100, '\0'); s.Receive(buffer.data(), buffer.size()); - if (port==1960){ - struct linger ling = { - .l_onoff = 1, - .l_linger = 0 - }; + if (port == 1960) { + struct linger ling = {.l_onoff = 1, .l_linger = 0}; auto fd = s.getSocketId(); setsockopt(fd, SOL_SOCKET, SO_LINGER, &ling, sizeof ling); @@ -199,7 +196,6 @@ TEST_CASE("Receiving with a socket error throws and reports the error", CHECK_THAT(error_message, Catch::Matchers::Contains("read error:")); } - TEST_CASE("Socket crash?", "[support]") { std::vector received_message(100, '\0'); std::vector sent_message(100, '\0'); @@ -211,25 +207,20 @@ TEST_CASE("Socket crash?", "[support]") { std::this_thread::sleep_for(std::chrono::milliseconds(100)); auto client = DetectorSocket("localhost", 1960); client.Send(sent_message.data(), sent_message.size()); - - - REQUIRE_THROWS(client.Receive(received_message.data(), received_message.size())); - - //Now try to send more - // client.Send(sent_message.data(), sent_message.size()); - + REQUIRE_THROWS( + client.Receive(received_message.data(), received_message.size())); + // Now try to send more + // client.Send(sent_message.data(), sent_message.size()); } - TEST_CASE("ClientSocket throws on invalid hostname", "[support]") { CHECK_THROWS(ReceiverSocket("invalidhostname", 1950)); CHECK_THROWS(DetectorSocket("invalidhostname", 1950)); CHECK_THROWS(GuiSocket("invalidhostname", 1950)); } - TEST_CASE("Using DetectorSocket to talk to a Server Socket", "[support]") { constexpr uint16_t port = 1961; constexpr int fnum = F_GET_DETECTOR_TYPE; @@ -240,9 +231,8 @@ TEST_CASE("Using DetectorSocket to talk to a Server Socket", "[support]") { auto client = DetectorSocket("localhost", port); int retval = 0; - int ret = - client.sendCommandThenRead(fnum, &arg, sizeof(arg), &retval, - sizeof(retval)); + int ret = client.sendCommandThenRead(fnum, &arg, sizeof(arg), &retval, + sizeof(retval)); client.close(); auto server_received = s.get(); @@ -294,8 +284,8 @@ TEST_CASE("Client cannot send the expected number of bytes", "[support]") { // Server accepts but never reads; it stays open until we tell it the // client is done, so it cannot close mid-transfer. std::atomic client_done{false}; - auto s = std::async(std::launch::async, non_reading_server, port, - &client_done); + auto s = + std::async(std::launch::async, non_reading_server, port, &client_done); std::this_thread::sleep_for(std::chrono::milliseconds(100)); auto client = DetectorSocket("localhost", port); diff --git a/slsSupportLib/tests/test-string_utils.cpp b/slsSupportLib/tests/test-string_utils.cpp index 21200eca9..58f431f54 100644 --- a/slsSupportLib/tests/test-string_utils.cpp +++ b/slsSupportLib/tests/test-string_utils.cpp @@ -148,8 +148,6 @@ TEST_CASE("to_lower does not modify the original string") { REQUIRE(original == "MixedCase"); } - - // TEST_CASE("concat things not being strings") } // namespace sls