Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion cpp/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,14 @@ if to_build.contains('scsimon')
)
endif

if to_build.contains('scsiloop')
if to_build.contains('scsiloop') and host_machine.system() == 'linux'
scsiloop_bin = executable('scsiloop',
scsiloop_src + shared_src,
dependencies : common_deps,
install : true,
)
elif to_build.contains('scsiloop')
message('Skipping scsiloop: it requires Linux on Raspberry Pi GPIO hardware')
endif

if connect_type == 'FULLSPEC' and to_build.contains('scsidump')
Expand Down
70 changes: 45 additions & 25 deletions cpp/scsiloop/scsiloop_core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
//---------------------------------------------------------------------------

#include "hal/log.h"
#include "hal/sbc_version.h"
#include "shared/piscsi_version.h"
#include "shared/piscsi_util.h"
#include "spdlog/sinks/stdout_color_sinks.h"
Expand All @@ -22,7 +23,10 @@
#include "scsiloop/scsiloop_gpio.h"
#include "scsiloop/scsiloop_timer.h"

#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string_view>
#include <signal.h>

#if defined CONNECT_TYPE_STANDARD
Expand All @@ -42,6 +46,25 @@ using namespace spdlog;

string current_log_level = "unknown"; // Some versions of spdlog do not support get_log_level()

namespace {

bool IsSupportedPlatform()
{
#if defined(__linux__)
try {
SBC_Version::Init();
return SBC_Version::IsRaspberryPi();
}
catch (const invalid_argument&) {
return false;
}
#else
return false;
#endif
}

}

void ScsiLoop::Banner(const vector<char *> &args) const
{
cout << piscsi_util::Banner("(SCSI Loopback Test)");
Expand Down Expand Up @@ -87,34 +110,26 @@ void ScsiLoop::TerminationHandler(int signum)

bool ScsiLoop::ParseArgument(const vector<char *> &args)
{
string name;
string log_level;

const char *locale = setlocale(LC_MESSAGES, "");
if (locale == nullptr || !strcmp(locale, "C")) {
locale = "en";
}

opterr = 1;
int opt;

while ((opt = getopt(static_cast<int>(args.size()), args.data(), "-L:")) != -1) {
switch (opt) {
case 'L':
log_level = optarg;
continue;

default:
return false;
}

if (optopt) {
return false;
}
}
for (size_t i = 1; i < args.size(); ++i) {
const string_view argument(args[i]);
if (argument == "-L") {
if (++i == args.size()) {
return false;
}
log_level = args[i];
}
else if (argument.starts_with("-L") && argument.size() > 2) {
log_level = argument.substr(2);
}
else {
return false;
}
}

if (!log_level.empty()) {
SetLogLevel(log_level);
return SetLogLevel(log_level);
}

return true;
Expand All @@ -131,12 +146,17 @@ int ScsiLoop::run(const vector<char *> &args)
// ParseArgument() requires the bus to have been initialized first, which requires the root user.
// The -v option should be available for any user, which requires special handling.
for (auto this_arg : args) {
if (!strcasecmp(this_arg, "-v")) {
if (!strcmp(this_arg, "-v")) {
cout << piscsi_get_version_string() << endl;
return 0;
}
}

if (!IsSupportedPlatform()) {
cerr << "scsiloop requires Linux on a Raspberry Pi with access to the GPIO hardware." << endl;
return EXIT_FAILURE;
}

// Create a thread-safe stdout logger to process the log messages
const auto logger = stdout_color_mt("scsiloop stdout logger");
set_level(level::info);
Expand Down
18 changes: 10 additions & 8 deletions cpp/scsiloop/scsiloop_gpio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#include "hal/sbc_version.h"
#include "scsiloop/scsiloop_cout.h"
#include "hal/log.h"
#include <chrono>
#include <thread>

#if defined CONNECT_TYPE_STANDARD
#include "hal/connection_type/connection_standard.h"
Expand Down Expand Up @@ -221,23 +223,23 @@ int ScsiLoop_GPIO::test_gpio_pin(loopback_connection &gpio_rec, vector<string> &

LOGTRACE("dir ctrl pin: %d", (int)gpio_rec.dir_ctrl_pin);
set_output_channel(gpio_rec.dir_ctrl_pin);
usleep(sleep_time);
this_thread::sleep_for(chrono::microseconds(sleep_time));

// Set all GPIOs high (initialize to a known state)
for (auto cur_gpio : loopback_conn_table) {
// bus->SetSignal(cur_gpio.this_pin, OFF);
bus->SetMode(cur_gpio.this_pin, GPIO_INPUT);
}

usleep(sleep_time);
this_thread::sleep_for(chrono::microseconds(sleep_time));
bus->Acquire();

// ############################################
// set the test gpio low
bus->SetMode(gpio_rec.this_pin, GPIO_OUTPUT);
bus->SetSignal(gpio_rec.this_pin, ON);

usleep(sleep_time);
this_thread::sleep_for(chrono::microseconds(sleep_time));

bus->Acquire();
// loop through all of the gpios
Expand Down Expand Up @@ -281,7 +283,7 @@ int ScsiLoop_GPIO::test_gpio_pin(loopback_connection &gpio_rec, vector<string> &
// set the transceivers to input
set_output_channel(-1);

usleep(sleep_time);
this_thread::sleep_for(chrono::microseconds(sleep_time));

bus->Acquire();
// # loop through all of the gpios
Expand Down Expand Up @@ -311,14 +313,14 @@ int ScsiLoop_GPIO::test_gpio_pin(loopback_connection &gpio_rec, vector<string> &

// Set the transceiver back to output
set_output_channel(gpio_rec.dir_ctrl_pin);
usleep(sleep_time);
this_thread::sleep_for(chrono::microseconds(sleep_time));

// #############################################
// set the test gpio high
bus->SetMode(gpio_rec.this_pin, GPIO_OUTPUT);
bus->SetSignal(gpio_rec.this_pin, OFF);

usleep(sleep_time);
this_thread::sleep_for(chrono::microseconds(sleep_time));

bus->Acquire();
// loop through all of the gpios
Expand Down Expand Up @@ -458,7 +460,7 @@ int ScsiLoop_GPIO::RunDataInputTest(vector<string> &error_list)

for (uint32_t val = 0; val < UINT8_MAX; val++) {
set_dat_inputs_loop(val);
usleep(delay_time_us);
this_thread::sleep_for(chrono::microseconds(delay_time_us));

bus->Acquire();
uint8_t read_val = bus->GetDAT();
Expand Down Expand Up @@ -488,7 +490,7 @@ int ScsiLoop_GPIO::RunDataOutputTest(vector<string> &error_list)

for (uint32_t val = 0; val < UINT8_MAX; val++) {
bus->SetDAT(val);
usleep(delay_time_us);
this_thread::sleep_for(chrono::microseconds(delay_time_us));

bus->Acquire();
uint8_t read_val = get_dat_outputs_loop();
Expand Down
4 changes: 3 additions & 1 deletion cpp/scsiloop/scsiloop_timer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include "hal/systimer.h"
#include "scsiloop/scsiloop_cout.h"
#include "hal/log.h"
#include <chrono>
#include <thread>

int ScsiLoop_Timer::RunTimerTest(vector<string> &error_list)
{
Expand All @@ -27,7 +29,7 @@ int ScsiLoop_Timer::RunTimerTest(vector<string> &error_list)
LOGDEBUG("++ Testing SysTimer::GetTimerLow()")
uint32_t before = SysTimer::GetTimerLow();
for (int i = 0; i < 10; i++) {
usleep(100000);
this_thread::sleep_for(chrono::microseconds(100000));
ScsiLoop_Cout::PrintUpdate();
}
uint32_t after = SysTimer::GetTimerLow();
Expand Down
Loading