2022-02-17 02:04:42 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
2022-12-05 17:58:23 +00:00
|
|
|
// SCSI Target Emulator PiSCSI
|
2022-02-17 02:04:42 +00:00
|
|
|
// for Raspberry Pi
|
|
|
|
//
|
2023-10-15 06:38:15 +00:00
|
|
|
// Copyright (C) 2022-2023 Uwe Seimet
|
2022-02-17 02:04:42 +00:00
|
|
|
//
|
|
|
|
// Implementation of a SCSI printer (see SCSI-2 specification for a command description)
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
//
|
|
|
|
// How to print:
|
|
|
|
//
|
2022-10-23 19:51:39 +00:00
|
|
|
// 1. The client sends the data to be printed with one or several PRINT commands. The maximum
|
|
|
|
// transfer size per PRINT command is currently limited to 4096 bytes.
|
|
|
|
// 2. The client triggers printing with SYNCHRONIZE BUFFER. Each SYNCHRONIZE BUFFER results in
|
2022-02-27 21:58:01 +00:00
|
|
|
// the print command for this printer (see below) to be called for the data not yet printed.
|
2022-02-17 02:04:42 +00:00
|
|
|
//
|
2022-10-25 08:29:57 +00:00
|
|
|
// It is recommended to reserve the printer device before printing and to release it afterwards.
|
2022-02-17 02:04:42 +00:00
|
|
|
// The command to be used for printing can be set with the "cmd" property when attaching the device.
|
2022-02-18 20:06:33 +00:00
|
|
|
// By default the data to be printed are sent to the printer unmodified, using "lp -oraw %f". This
|
2022-02-17 02:04:42 +00:00
|
|
|
// requires that the client uses a printer driver compatible with the respective printer, or that the
|
2022-02-18 20:06:33 +00:00
|
|
|
// printing service on the Pi is configured to do any necessary conversions, or that the print command
|
|
|
|
// applies any conversions on the file to be printed (%f) before passing it to the printing service.
|
2022-02-20 17:40:30 +00:00
|
|
|
// 'enscript' is an example for a conversion tool.
|
2022-02-17 02:04:42 +00:00
|
|
|
// By attaching different devices/LUNs multiple printers (i.e. different print commands) are possible.
|
|
|
|
//
|
|
|
|
// With STOP PRINT printing can be cancelled before SYNCHRONIZE BUFFER was sent.
|
|
|
|
//
|
|
|
|
|
2022-12-05 17:58:23 +00:00
|
|
|
#include "shared/piscsi_exceptions.h"
|
2022-10-01 15:56:06 +00:00
|
|
|
#include "scsi_command_util.h"
|
2022-02-17 02:04:42 +00:00
|
|
|
#include "scsi_printer.h"
|
2022-10-25 08:29:57 +00:00
|
|
|
#include <filesystem>
|
2022-02-17 02:04:42 +00:00
|
|
|
|
|
|
|
using namespace std;
|
2022-10-25 08:29:57 +00:00
|
|
|
using namespace filesystem;
|
2022-02-17 02:04:42 +00:00
|
|
|
using namespace scsi_defs;
|
2022-10-01 15:56:06 +00:00
|
|
|
using namespace scsi_command_util;
|
2022-02-17 02:04:42 +00:00
|
|
|
|
2022-11-11 20:08:48 +00:00
|
|
|
SCSIPrinter::SCSIPrinter(int lun) : PrimaryDevice(SCLP, lun)
|
|
|
|
{
|
|
|
|
SupportsParams(true);
|
|
|
|
}
|
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
bool SCSIPrinter::Init(const param_map& params)
|
2022-02-17 02:04:42 +00:00
|
|
|
{
|
2022-11-02 14:36:19 +00:00
|
|
|
PrimaryDevice::Init(params);
|
|
|
|
|
|
|
|
AddCommand(scsi_command::eCmdTestUnitReady, [this] { TestUnitReady(); });
|
|
|
|
AddCommand(scsi_command::eCmdPrint, [this] { Print(); });
|
|
|
|
AddCommand(scsi_command::eCmdSynchronizeBuffer, [this] { SynchronizeBuffer(); });
|
2022-10-25 08:29:57 +00:00
|
|
|
// STOP PRINT is identical with TEST UNIT READY, it just returns the status
|
2022-11-02 14:36:19 +00:00
|
|
|
AddCommand(scsi_command::eCmdStopPrint, [this] { TestUnitReady(); });
|
2022-10-23 19:51:39 +00:00
|
|
|
|
|
|
|
// Required also in this class in order to fulfill the ScsiPrinterCommands interface contract
|
2022-11-02 14:36:19 +00:00
|
|
|
AddCommand(scsi_command::eCmdReserve6, [this] { ReserveUnit(); });
|
|
|
|
AddCommand(scsi_command::eCmdRelease6, [this] { ReleaseUnit(); });
|
|
|
|
AddCommand(scsi_command::eCmdSendDiagnostic, [this] { SendDiagnostic(); });
|
|
|
|
|
|
|
|
if (GetParam("cmd").find("%f") == string::npos) {
|
2023-10-15 06:38:15 +00:00
|
|
|
LogTrace("Missing filename specifier %f");
|
2022-11-02 14:36:19 +00:00
|
|
|
return false;
|
|
|
|
}
|
2022-10-11 15:04:17 +00:00
|
|
|
|
2022-10-25 08:29:57 +00:00
|
|
|
error_code error;
|
|
|
|
file_template = temp_directory_path(error); //NOSONAR Publicly writable directory is fine here
|
|
|
|
file_template += PRINTER_FILE_PATTERN;
|
|
|
|
|
2022-10-11 15:04:17 +00:00
|
|
|
SetReady(true);
|
2022-02-18 20:06:33 +00:00
|
|
|
|
2022-02-17 02:04:42 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-10-30 10:24:18 +00:00
|
|
|
void SCSIPrinter::CleanUp()
|
|
|
|
{
|
|
|
|
PrimaryDevice::CleanUp();
|
|
|
|
|
|
|
|
if (out.is_open()) {
|
|
|
|
out.close();
|
2024-02-02 18:55:07 +00:00
|
|
|
}
|
2023-10-30 10:24:18 +00:00
|
|
|
|
2024-02-02 18:55:07 +00:00
|
|
|
if (!filename.empty()) {
|
2023-10-30 10:24:18 +00:00
|
|
|
error_code error;
|
|
|
|
remove(path(filename), error);
|
|
|
|
|
|
|
|
filename = "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
param_map SCSIPrinter::GetDefaultParams() const
|
|
|
|
{
|
|
|
|
return {
|
|
|
|
{ "cmd", "lp -oraw %f" }
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
void SCSIPrinter::TestUnitReady()
|
2022-02-17 02:04:42 +00:00
|
|
|
{
|
2022-10-23 19:51:39 +00:00
|
|
|
// The printer is always ready
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
EnterStatusPhase();
|
2022-02-17 02:04:42 +00:00
|
|
|
}
|
|
|
|
|
2022-11-02 14:36:19 +00:00
|
|
|
vector<uint8_t> SCSIPrinter::InquiryInternal() const
|
2022-02-17 02:04:42 +00:00
|
|
|
{
|
2023-10-15 06:38:15 +00:00
|
|
|
return HandleInquiry(device_type::printer, scsi_level::scsi_2, false);
|
2022-02-17 02:04:42 +00:00
|
|
|
}
|
|
|
|
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
void SCSIPrinter::Print()
|
2022-02-17 02:04:42 +00:00
|
|
|
{
|
2022-11-04 07:22:32 +00:00
|
|
|
const uint32_t length = GetInt24(GetController()->GetCmd(), 2);
|
2022-02-17 02:04:42 +00:00
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
LogTrace("Expecting to receive " + to_string(length) + " byte(s) to be printed");
|
2022-02-17 02:04:42 +00:00
|
|
|
|
2022-11-04 07:22:32 +00:00
|
|
|
if (length > GetController()->GetBuffer().size()) {
|
2023-10-15 06:38:15 +00:00
|
|
|
LogError("Transfer buffer overflow: Buffer size is " + to_string(GetController()->GetBuffer().size()) +
|
2022-11-11 20:08:48 +00:00
|
|
|
" bytes, " + to_string(length) + " bytes expected");
|
2022-02-20 17:40:30 +00:00
|
|
|
|
2023-10-30 12:32:45 +00:00
|
|
|
++print_error_count;
|
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
throw scsi_exception(sense_key::illegal_request, asc::invalid_field_in_cdb);
|
2022-02-17 02:04:42 +00:00
|
|
|
}
|
|
|
|
|
2022-11-04 07:22:32 +00:00
|
|
|
GetController()->SetLength(length);
|
|
|
|
GetController()->SetByteTransfer(true);
|
2022-02-17 02:04:42 +00:00
|
|
|
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
EnterDataOutPhase();
|
2022-02-17 02:04:42 +00:00
|
|
|
}
|
|
|
|
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
void SCSIPrinter::SynchronizeBuffer()
|
2022-02-17 02:04:42 +00:00
|
|
|
{
|
2022-10-25 08:29:57 +00:00
|
|
|
if (!out.is_open()) {
|
2023-10-15 06:38:15 +00:00
|
|
|
LogWarn("Nothing to print");
|
2022-02-17 02:04:42 +00:00
|
|
|
|
2023-10-30 12:32:45 +00:00
|
|
|
++print_warning_count;
|
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
throw scsi_exception(sense_key::aborted_command);
|
2022-10-23 19:51:39 +00:00
|
|
|
}
|
2022-02-17 02:04:42 +00:00
|
|
|
|
2024-02-02 18:55:07 +00:00
|
|
|
out.close();
|
|
|
|
|
2022-02-17 02:04:42 +00:00
|
|
|
string cmd = GetParam("cmd");
|
2022-10-08 17:26:04 +00:00
|
|
|
const size_t file_position = cmd.find("%f");
|
2022-02-18 20:06:33 +00:00
|
|
|
assert(file_position != string::npos);
|
|
|
|
cmd.replace(file_position, 2, filename);
|
2022-02-17 02:04:42 +00:00
|
|
|
|
2022-10-25 08:29:57 +00:00
|
|
|
error_code error;
|
2023-10-15 06:38:15 +00:00
|
|
|
LogTrace("Printing file '" + filename + "' with " + to_string(file_size(path(filename), error)) + " byte(s)");
|
2022-10-25 08:29:57 +00:00
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
LogDebug("Executing print command '" + cmd + "'");
|
2022-02-17 02:04:42 +00:00
|
|
|
|
|
|
|
if (system(cmd.c_str())) {
|
2023-10-15 06:38:15 +00:00
|
|
|
LogError("Printing file '" + filename + "' failed, the printing system might not be configured");
|
2022-02-17 02:04:42 +00:00
|
|
|
|
2023-10-30 12:32:45 +00:00
|
|
|
++print_error_count;
|
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
CleanUp();
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
throw scsi_exception(sense_key::aborted_command);
|
2022-02-17 02:04:42 +00:00
|
|
|
}
|
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
CleanUp();
|
SASI code removal, error handling update, bug fixes, code cleanup (#806)
Summary ov most important changes triggered by the SASI code removal:
- Removed the SASI controller code
- New controller management. There is a new controller base class AbstractController and a class ControllerManager managing the controller lifecycle. The lifecycle management was removed from rasci.cpp and is covered by unit tests.
- New device management. The DeviceFactory manages the device lifecycle instead of rascsi.cpp. The new code is covered by unit tests.
- The lifecycle managment uses C++ collections with variable size instead of arrays with hard-coded sizes.
- The ScsiController method contains most of what was previously contained in scsidev_ctrl.cpp plus the code from sasidev_ctrl.cpp that was relevant for SCSI.
- scsi_command_util contains helper methods used for identical SCSI command implementations of more than one device
- Devices know their controllers, so that the controller instance does not need to be passed to each SCSI command. This change helps to decouple the devices from the controller. The phase_handler interface is also part of this decoupling.
- Use scsi_command_exception for propagating SCSI command execution errors, This resolves issues with the previous error handling, which was based on return values and often on magic numbers.
- Removed legacy SCSI error codes, all errors are now encoded by sense_key::, asc:: and status::.
- Fixed various warnings reported with -Wextra, -Weffc++ and -Wpedantic.
- Use constructor member initialization lists (recommended for ISO C++)
- Consistently use new/delete instead of malloc/free (recommended for ISO C++), resulting in better type safety and error handling
- Replaced variable sized arrays on the stack (violates ISO C++ and can cause a stack overflow)
- Replaced NULL by nullptr (recommended for C++), resulting in better type safety
- Use more const member functions in order to avoid side effects
- The format device page can now also be changed for hard disk drives (Fujitsu M2624S supports this, for instance), not just for MOs.
- Better encapsulation, updated access specifiers in many places
- Removed unused methods and method arguments
- Fixed a number of TODOs
- Added/updated unit tests for a lot of non-legacy classes
- Makefile support for creating HTML coverage reports with lcov/genhtml
2022-09-03 14:53:53 +00:00
|
|
|
|
|
|
|
EnterStatusPhase();
|
2022-02-17 02:04:42 +00:00
|
|
|
}
|
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
bool SCSIPrinter::WriteByteSequence(span<const uint8_t> buf)
|
2022-02-17 02:04:42 +00:00
|
|
|
{
|
2023-10-30 12:32:45 +00:00
|
|
|
byte_receive_count += buf.size();
|
|
|
|
|
2022-10-25 08:29:57 +00:00
|
|
|
if (!out.is_open()) {
|
|
|
|
vector<char> f(file_template.begin(), file_template.end());
|
|
|
|
f.push_back(0);
|
|
|
|
|
|
|
|
// There is no C++ API that generates a file with a unique name
|
|
|
|
const int fd = mkstemp(f.data());
|
2022-02-17 02:04:42 +00:00
|
|
|
if (fd == -1) {
|
2023-10-15 06:38:15 +00:00
|
|
|
LogError("Can't create printer output file for pattern '" + filename + "': " + strerror(errno));
|
2023-10-30 12:32:45 +00:00
|
|
|
|
|
|
|
++print_error_count;
|
|
|
|
|
2022-02-17 02:04:42 +00:00
|
|
|
return false;
|
|
|
|
}
|
2022-10-25 08:29:57 +00:00
|
|
|
close(fd);
|
|
|
|
|
|
|
|
filename = f.data();
|
|
|
|
|
|
|
|
out.open(filename, ios::binary);
|
|
|
|
if (out.fail()) {
|
2023-10-30 12:32:45 +00:00
|
|
|
++print_error_count;
|
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
throw scsi_exception(sense_key::aborted_command);
|
2022-10-25 08:29:57 +00:00
|
|
|
}
|
2022-02-17 02:04:42 +00:00
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
LogTrace("Created printer output file '" + filename + "'");
|
2022-02-17 02:04:42 +00:00
|
|
|
}
|
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
LogTrace("Appending " + to_string(buf.size()) + " byte(s) to printer output file ''" + filename + "'");
|
2022-10-25 08:29:57 +00:00
|
|
|
|
2023-10-15 06:38:15 +00:00
|
|
|
out.write((const char *)buf.data(), buf.size());
|
2022-02-17 02:04:42 +00:00
|
|
|
|
2023-10-30 12:32:45 +00:00
|
|
|
const bool status = out.fail();
|
2023-11-14 14:16:23 +00:00
|
|
|
if (status) {
|
2023-10-30 12:32:45 +00:00
|
|
|
++print_error_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
return !status;
|
|
|
|
}
|
|
|
|
|
|
|
|
vector<PbStatistics> SCSIPrinter::GetStatistics() const
|
|
|
|
{
|
|
|
|
vector<PbStatistics> statistics = PrimaryDevice::GetStatistics();
|
|
|
|
|
|
|
|
PbStatistics s;
|
|
|
|
s.set_id(GetId());
|
|
|
|
s.set_unit(GetLun());
|
|
|
|
|
|
|
|
s.set_category(PbStatisticsCategory::CATEGORY_INFO);
|
|
|
|
|
|
|
|
s.set_key(FILE_PRINT_COUNT);
|
|
|
|
s.set_value(file_print_count);
|
|
|
|
statistics.push_back(s);
|
|
|
|
|
|
|
|
s.set_key(BYTE_RECEIVE_COUNT);
|
|
|
|
s.set_value(byte_receive_count);
|
|
|
|
statistics.push_back(s);
|
|
|
|
|
|
|
|
s.set_category(PbStatisticsCategory::CATEGORY_ERROR);
|
|
|
|
|
|
|
|
s.set_key(PRINT_ERROR_COUNT);
|
|
|
|
s.set_value(print_error_count);
|
|
|
|
statistics.push_back(s);
|
|
|
|
|
|
|
|
s.set_category(PbStatisticsCategory::CATEGORY_WARNING);
|
|
|
|
|
|
|
|
s.set_key(PRINT_WARNING_COUNT);
|
|
|
|
s.set_value(print_warning_count);
|
|
|
|
statistics.push_back(s);
|
|
|
|
|
|
|
|
return statistics;
|
2022-02-17 02:04:42 +00:00
|
|
|
}
|