diff --git a/doc/rascsi.1 b/doc/rascsi.1 index 32f60a29..8c63bc13 100644 --- a/doc/rascsi.1 +++ b/doc/rascsi.1 @@ -71,9 +71,9 @@ Set the vendor, product and revision for the device, to be returned with the INQ The rascsi server port, default is 6868. .TP .BR \-r\fI " " \fIRESERVED_IDS -Comma-separated list of IDs to reserve. +Comma-separated list of IDs to reserve. Pass an empty list in order to not reserve anything. .BR \-p\fI " " \fITYPE -The optional case-insensitive device type (SAHD, SCHD, SCRM, SCCD, SCMO, SCBR, SCDP, SCHS). If no type is specified for devices that support an image file, rascsi tries to derive the type from the file extension. +The optional case-insensitive device type (SAHD, SCHD, SCRM, SCCD, SCMO, SCBR, SCDP, SCLP, SCHS). If no type is specified for devices that support an image file, rascsi tries to derive the type from the file extension. .TP .BR \-v\fI " " \fI Display the rascsi version. @@ -84,7 +84,7 @@ Overrides the default locale for client-faces error messages. The client can ove .BR \-ID\fIn[:u] " " \fIFILE n is the SCSI ID number (0-7). u (0-31) is the optional LUN (logical unit). The default LUN is 0. .IP -FILE is the name of the image file to use for the SCSI device. For devices that do not support an image file (SCBR, SCDP, SCHS) a dummy name must be provided. +FILE is the name of the image file to use for the SCSI device. For devices that do not support an image file (SCBR, SCDP, SCLP, SCHS) the filename may have a special meaning or a dummy name can be provided. For SCBR and SCDP it is an optioinal prioritized list of network interfaces, an optional IP address and netmask, e.g. "interfaces=eth0,eth1,wlan0:inet=10.10.20.1/24". For SCLP it is the print command to be used and a reservation timeout in seconds, e.g. "cmd=lp -oraw %f:timeout=60". .TP .BR \-HD\fIn[:u] " " \fIFILE n is the SASI ID number (0-15). The effective SASI ID is calculated as n/2, the effective SASI LUN is calculated is the remainder of n/2. Alternatively the n:u syntax can be used, where ns is the SASI ID (0-7) and u the LUN (0-1). diff --git a/doc/rascsi_man_page.txt b/doc/rascsi_man_page.txt index 4ff5553e..1f6d8518 100644 --- a/doc/rascsi_man_page.txt +++ b/doc/rascsi_man_page.txt @@ -91,25 +91,31 @@ OPTIONS The rascsi server port, default is 6868. -r RESERVED_IDS - Comma-separated list of IDs to reserve. -p TYPE The optional - case-insensitive device type (SAHD, SCHD, SCRM, SCCD, SCMO, - SCBR, SCDP, SCHS). If no type is specified for devices that sup‐ - port an image file, rascsi tries to derive the type from the - file extension. + Comma-separated list of IDs to reserve. Pass an empty list in + order to not reserve anything. -p TYPE The optional case-insen‐ + sitive device type (SAHD, SCHD, SCRM, SCCD, SCMO, SCBR, SCDP, + SCLP, SCHS). If no type is specified for devices that support an + image file, rascsi tries to derive the type from the file exten‐ + sion. -v Display the rascsi version. -z LOCALE - Overrides the default locale for client-faces error messages. + Overrides the default locale for client-faces error messages. The client can override the locale. -IDn[:u] FILE - n is the SCSI ID number (0-7). u (0-31) is the optional LUN + n is the SCSI ID number (0-7). u (0-31) is the optional LUN (logical unit). The default LUN is 0. - FILE is the name of the image file to use for the SCSI device. - For devices that do not support an image file (SCBR, SCDP, SCHS) - a dummy name must be provided. + FILE is the name of the image file to use for the SCSI device. + For devices that do not support an image file (SCBR, SCDP, SCLP, + SCHS) the filename may have a special meaning or a dummy name + can be provided. For SCBR and SCDP it is an optioinal priori‐ + tized list of network interfaces, an optional IP address and + netmask, e.g. "interfaces=eth0,eth1,wlan0:inet=10.10.20.1/24". + For SCLP it is the print command to be used and a reservation + timeout in seconds, e.g. "cmd=lp -oraw %f:timeout=60". -HDn[:u] FILE n is the SASI ID number (0-15). The effective SASI ID is calcu‐ diff --git a/doc/rasctl.1 b/doc/rasctl.1 index 1159ee1d..61b7a153 100644 --- a/doc/rasctl.1 +++ b/doc/rasctl.1 @@ -94,7 +94,7 @@ Rename an image file in the default image folder. The rascsi port to connect to, default is 6868. .TP .BR \-r\fI " " \fIRESERVED_IDS -Comma-separated list of IDs to reserve. +Comma-separated list of IDs to reserve. Pass an empty list in order to not reserve anything. .TP .BR \-s\fI Display server-side settings like available images or supported device types. @@ -147,6 +147,7 @@ Specifies the device type. This type overrides the type derived from the file ex rm: SCSI removable media drive cd: CD-ROM mo: Magneto-Optical disk + lp: SCSI printer bridge: Bridge device (Only applicable to the Sharp X68000) daynaport: DaynaPort network adapter services: Host services device diff --git a/doc/rasctl_man_page.txt b/doc/rasctl_man_page.txt index 03413ee6..ad1f4da7 100644 --- a/doc/rasctl_man_page.txt +++ b/doc/rasctl_man_page.txt @@ -71,9 +71,10 @@ OPTIONS The rascsi port to connect to, default is 6868. -r RESERVED_IDS - Comma-separated list of IDs to reserve. + Comma-separated list of IDs to reserve. Pass an empty list in + order to not reserve anything. - -s Display server-side settings like available images or supported + -s Display server-side settings like available images or supported device types. -T Display all device types and their properties. @@ -100,7 +101,7 @@ OPTIONS d(etach): Detach disk i(nsert): Insert media (removable media devices only) e(ject): Eject media (removable media devices only) - p(rotect): Write protect the medium (not for CD-ROMs, which + p(rotect): Write protect the medium (not for CD-ROMs, which are always read-only) u(nprotect): Remove write protection from the medium (not for CD-ROMs, which are always read-only) @@ -110,38 +111,39 @@ OPTIONS -b BLOCK_SIZE The optional block size. For SCSI drives 512, 1024, 2048 or 4096 - bytes, default size is 512 bytes. For SASI drives 256 or 1024 + bytes, default size is 512 bytes. For SASI drives 256 or 1024 bytes, default is 256 bytes. -f FILE|PARAM Device-specific: Either a path to a disk image file, or a param‐ - eter for a non-disk device. See the rascsi(1) man page for per‐ + eter for a non-disk device. See the rascsi(1) man page for per‐ mitted file types. -t TYPE - Specifies the device type. This type overrides the type derived + Specifies the device type. This type overrides the type derived from the file extension of the specified image. See the - rascsi(1) man page for the available device types. For some + rascsi(1) man page for the available device types. For some types there are shortcuts (only the first letter is required): hd: SCSI hard disk drive rm: SCSI removable media drive cd: CD-ROM mo: Magneto-Optical disk + lp: SCSI printer bridge: Bridge device (Only applicable to the Sharp X68000) daynaport: DaynaPort network adapter services: Host services device -n VENDOR:PRODUCT:REVISION - The vendor, product and revision for the device, to be returned + The vendor, product and revision for the device, to be returned with the INQUIRY data. A complete set of name components must be provided. VENDOR may have up to 8, PRODUCT up to 16, REVISION up to 4 characters. Padding with blanks to the maxium length is au‐ - tomatically applied. Once set the name of a device cannot be + tomatically applied. Once set the name of a device cannot be changed. -u UNIT - Unit number (0-31). This will default to 0. This option is only - used when there are multiple SCSI devices on a shared SCSI con‐ + Unit number (0-31). This will default to 0. This option is only + used when there are multiple SCSI devices on a shared SCSI con‐ troller. (This is not common) EXAMPLES diff --git a/easyinstall.sh b/easyinstall.sh index 95d398e8..6bfa87ca 100755 --- a/easyinstall.sh +++ b/easyinstall.sh @@ -113,9 +113,17 @@ function installRaScsi() { } function preparePythonCommon() { - if [ -f "$PYTHON_COMMON_PATH/rascsi_interface_pb2.py" ]; then - sudo rm "$PYTHON_COMMON_PATH/rascsi_interface_pb2.py" - echo "Deleting old Python protobuf library rascsi_interface_pb2.py" + if [ -f "$WEB_INSTALL_PATH/src/rascsi_interface_pb2.py" ]; then + sudo rm "$WEB_INSTALL_PATH/src/rascsi_interface_pb2.py" + echo "Deleting old Python protobuf library $WEB_INSTALL_PATH/src/rascsi_interface_pb2.py" + fi + if [ -f "$OLED_INSTALL_PATH/src/rascsi_interface_pb2.py" ]; then + sudo rm "$OLED_INSTALL_PATH/src/rascsi_interface_pb2.py" + echo "Deleting old Python protobuf library $OLED_INSTALL_PATH/src/rascsi_interface_pb2.py" + fi + if [ -f "$PYTHON_COMMON_PATH/src/rascsi_interface_pb2.py" ]; then + sudo rm "$PYTHON_COMMON_PATH/src/rascsi_interface_pb2.py" + echo "Deleting old Python protobuf library $PYTHON_COMMON_PATH/src/rascsi_interface_pb2.py" fi echo "Compiling the Python protobuf library rascsi_interface_pb2.py..." protoc -I="$BASE/src/raspberrypi/" --python_out="$PYTHON_COMMON_PATH/src" rascsi_interface.proto diff --git a/python/common/src/rascsi/common_settings.py b/python/common/src/rascsi/common_settings.py index 0bd83a84..8e0d80e5 100644 --- a/python/common/src/rascsi/common_settings.py +++ b/python/common/src/rascsi/common_settings.py @@ -4,13 +4,8 @@ Module for general settings used in the rascsi module from os import getcwd -WORK_DIR = getcwd() - -REMOVABLE_DEVICE_TYPES = ("SCCD", "SCRM", "SCMO") -NETWORK_DEVICE_TYPES = ("SCDP", "SCBR") - # There may be a more elegant way to get the HOME dir of the user that installed RaSCSI -HOME_DIR = "/".join(WORK_DIR.split("/")[0:3]) +HOME_DIR = "/".join(getcwd().split("/")[0:3]) CFG_DIR = f"{HOME_DIR}/.config/rascsi" CONFIG_FILE_SUFFIX = "json" diff --git a/python/common/src/rascsi/file_cmds.py b/python/common/src/rascsi/file_cmds.py index 009edfff..b3e493ec 100644 --- a/python/common/src/rascsi/file_cmds.py +++ b/python/common/src/rascsi/file_cmds.py @@ -450,17 +450,16 @@ class FileCmds: for row in config["devices"]: kwargs = { "device_type": row["device_type"], - "image": row["image"], "unit": int(row["unit"]), "vendor": row["vendor"], "product": row["product"], "revision": row["revision"], "block_size": row["block_size"], + "params": dict(row["params"]), } - params = dict(row["params"]) - for param in params.keys(): - kwargs[param] = params[param] - self.ractl.attach_image(row["id"], **kwargs) + if row["image"]: + kwargs["params"]["file"] = row["image"] + self.ractl.attach_device(row["id"], **kwargs) # The config file format in RaSCSI 21.10 is using a list data type at the top level. # If future config file formats return to the list data type, # introduce more sophisticated format detection logic here. @@ -470,17 +469,17 @@ class FileCmds: kwargs = { "device_type": row["device_type"], "image": row["image"], - # "un" for backwards compatibility "unit": int(row["un"]), "vendor": row["vendor"], "product": row["product"], "revision": row["revision"], "block_size": row["block_size"], + "params": dict(row["params"]), } - params = dict(row["params"]) - for param in params.keys(): - kwargs[param] = params[param] - self.ractl.attach_image(row["id"], **kwargs) + if row["image"]: + kwargs["params"]["file"] = row["image"] + self.ractl.attach_device(row["id"], **kwargs) + logging.warning("%s is in an obsolete config file format", file_name) else: return {"status": False, "return_code": ReturnCodes.READCONFIG_INVALID_CONFIG_FILE_FORMAT} diff --git a/python/common/src/rascsi/ractl_cmds.py b/python/common/src/rascsi/ractl_cmds.py index 2bba4030..3e0576fe 100644 --- a/python/common/src/rascsi/ractl_cmds.py +++ b/python/common/src/rascsi/ractl_cmds.py @@ -3,7 +3,6 @@ Module for commands sent to the RaSCSI backend service. """ import rascsi_interface_pb2 as proto -from rascsi.common_settings import REMOVABLE_DEVICE_TYPES from rascsi.return_codes import ReturnCodes from rascsi.socket_cmds import SocketCmds @@ -125,7 +124,8 @@ class RaCtlCmds: Sends a DEVICE_TYPES_INFO command to the server. Returns a dict with: - (bool) status - - (list) of (str) device_types (device types that RaSCSI supports, ex. SCHD, SCCD, etc) + - (dict) device_types, where keys are the four letter device type acronym, + and the value is a (dict) of supported parameters and their default values. """ command = proto.PbCommand() command.operation = proto.PbOperation.DEVICE_TYPES_INFO @@ -135,11 +135,55 @@ class RaCtlCmds: data = self.sock_cmd.send_pb_command(command.SerializeToString()) result = proto.PbResult() result.ParseFromString(data) - device_types = [] - for prop in result.device_types_info.properties: - device_types.append(proto.PbDeviceType.Name(prop.type)) + device_types = {} + for device in result.device_types_info.properties: + params = {} + for key, value in device.properties.default_params.items(): + params[key] = value + device_types[proto.PbDeviceType.Name(device.type)] = { + "removable": device.properties.removable, + "supports_file": device.properties.supports_file, + "params": params, + "block_sizes": device.properties.block_sizes, + } return {"status": result.status, "device_types": device_types} + def get_removable_device_types(self): + """ + Returns a (list) of (str) of four letter device acronyms + that are of the removable type. + """ + device_types = self.get_device_types() + removable_device_types = [] + for device, value in device_types["device_types"].items(): + if value["removable"]: + removable_device_types.append(device) + return removable_device_types + + def get_disk_device_types(self): + """ + Returns a (list) of (str) of four letter device acronyms + that take image files as arguments. + """ + device_types = self.get_device_types() + disk_device_types = [] + for device, value in device_types["device_types"].items(): + if value["supports_file"]: + disk_device_types.append(device) + return disk_device_types + + def get_peripheral_device_types(self): + """ + Returns a (list) of (str) of four letter device acronyms + that don't take image files as arguments. + """ + device_types = self.get_device_types() + image_device_types = self.get_disk_device_types() + peripheral_device_types = [ + x for x in device_types["device_types"] if x not in image_device_types + ] + return peripheral_device_types + def get_image_files_info(self): """ Sends a DEFAULT_IMAGE_FILES_INFO command to the server. @@ -167,7 +211,7 @@ class RaCtlCmds: "scan_depth": scan_depth, } - def attach_image(self, scsi_id, **kwargs): + def attach_device(self, scsi_id, **kwargs): """ Takes (int) scsi_id and kwargs containing 0 or more device properties @@ -185,14 +229,15 @@ class RaCtlCmds: devices.id = int(scsi_id) if "device_type" in kwargs.keys(): - if kwargs["device_type"] not in [None, ""]: + if kwargs["device_type"]: devices.type = proto.PbDeviceType.Value(str(kwargs["device_type"])) if "unit" in kwargs.keys(): - if kwargs["unit"] not in [None, ""]: + if kwargs["unit"]: devices.unit = kwargs["unit"] - if "image" in kwargs.keys(): - if kwargs["image"] not in [None, ""]: - devices.params["file"] = kwargs["image"] + if "params" in kwargs.keys(): + if isinstance(kwargs["params"], dict): + for param in kwargs["params"]: + devices.params[param] = kwargs["params"][param] # Handling the inserting of media into an attached removable type device device_type = kwargs.get("device_type", None) @@ -202,7 +247,8 @@ class RaCtlCmds: else: current_type = None - if device_type in REMOVABLE_DEVICE_TYPES and current_type in REMOVABLE_DEVICE_TYPES: + removable_device_types = self.get_removable_device_types() + if device_type in removable_device_types and current_type in removable_device_types: if current_type != device_type: parameters = { "device_type": device_type, @@ -214,23 +260,21 @@ class RaCtlCmds: "parameters": parameters, } command.operation = proto.PbOperation.INSERT + # Handling attaching a new device else: command.operation = proto.PbOperation.ATTACH - if "interfaces" in kwargs.keys(): - if kwargs["interfaces"] not in [None, ""]: - devices.params["interfaces"] = kwargs["interfaces"] if "vendor" in kwargs.keys(): - if kwargs["vendor"] is not None: + if kwargs["vendor"]: devices.vendor = kwargs["vendor"] if "product" in kwargs.keys(): - if kwargs["product"] is not None: + if kwargs["product"]: devices.product = kwargs["product"] if "revision" in kwargs.keys(): - if kwargs["revision"] is not None: + if kwargs["revision"]: devices.revision = kwargs["revision"] if "block_size" in kwargs.keys(): - if kwargs["block_size"] not in [None, ""]: + if kwargs["block_size"]: devices.block_size = int(kwargs["block_size"]) command.devices.append(devices) diff --git a/python/oled/src/rascsi_oled_monitor.py b/python/oled/src/rascsi_oled_monitor.py index 90ba7d29..343bd396 100755 --- a/python/oled/src/rascsi_oled_monitor.py +++ b/python/oled/src/rascsi_oled_monitor.py @@ -43,11 +43,6 @@ from pi_cmds import get_ip_and_host from rascsi.ractl_cmds import RaCtlCmds from rascsi.socket_cmds import SocketCmds -from rascsi.common_settings import ( - REMOVABLE_DEVICE_TYPES, - NETWORK_DEVICE_TYPES, -) - parser = argparse.ArgumentParser(description="RaSCSI OLED Monitor script") parser.add_argument( "--rotation", @@ -165,7 +160,8 @@ LINE_SPACING = 8 FONT = ImageFont.truetype('resources/type_writer.ttf', FONT_SIZE) IP_ADDR, HOSTNAME = get_ip_and_host() - +REMOVABLE_DEVICE_TYPES = ractl_cmd.get_removable_device_types() +SUPPORT_DEVICE_TYPES = ractl_cmd.get_support_device_types() def formatted_output(): """ @@ -186,10 +182,13 @@ def formatted_output(): f"{line['file']} {line['status']}") else: output.append(f"{line['id']} {line['device_type'][2:4]} {line['status']}") - # Special handling for network devices - elif line["device_type"] in NETWORK_DEVICE_TYPES: - output.append(f"{line['id']} {line['device_type'][2:4]} {line['vendor']} " - f"{line['product']}") + # Special handling of devices that don't use image files + elif line["device_type"] in (SUPPORT_DEVICE_TYPES): + if line["vendor"] == "RaSCSI": + output.append(f"{line['id']} {line['device_type'][2:4]} {line['product']}") + else: + output.append(f"{line['id']} {line['device_type'][2:4]} {line['vendor']} " + f"{line['product']}") # Print only the Vendor/Product info if it's not generic RaSCSI elif line["vendor"] not in "RaSCSI": output.append(f"{line['id']} {line['device_type'][2:4]} {line['file']} " diff --git a/python/web/src/device_utils.py b/python/web/src/device_utils.py index e5abdff7..0d1d6cf8 100644 --- a/python/web/src/device_utils.py +++ b/python/web/src/device_utils.py @@ -52,29 +52,39 @@ def sort_and_format_devices(devices): return formatted_devices -def extend_device_names(device_types): +def map_device_types_and_names(device_types): """ - Takes a (list) of (str) device_types with the four letter device acronyms + Takes a (dict) corresponding to the data structure returned by RaCtlCmds.get_device_types() Returns a (dict) of device_type:device_name mappings of localized device names """ - mapped_device_types = {} - for device_type in device_types: - if device_type is "SAHD": - device_name = _("SASI Hard Drive") - elif device_type is "SCHD": - device_name = _("SCSI Hard Drive") - elif device_type is "SCRM": - device_name = _("Removable Drive") - elif device_type is "SCMO": - device_name = _("Magneto-Optical Drive") - elif device_type is "SCCD": - device_name = _("CD-ROM Drive") - elif device_type is "SCBR": - device_name = _("X68000 Host Bridge") - elif device_type is "SCDP": - device_name = _("DaynaPORT SCSI/Link") - else: - device_name = _("Unknown Device") - mapped_device_types[device_type] = device_name + for key, value in device_types.items(): + device_types[key]["name"] = get_device_name(key) - return mapped_device_types + return device_types + + +def get_device_name(device_type): + """ + Takes a four letter device acronym (str) device_type. + Returns the human-readable name for the device type. + """ + if device_type == "SAHD": + return _("SASI Hard Disk") + elif device_type == "SCHD": + return _("SCSI Hard Disk") + elif device_type == "SCRM": + return _("Removable Disk") + elif device_type == "SCMO": + return _("Magneto-Optical") + elif device_type == "SCCD": + return _("CD / DVD") + elif device_type == "SCBR": + return _("X68000 Host Bridge") + elif device_type == "SCDP": + return _("DaynaPORT SCSI/Link") + elif device_type == "SCLP": + return _("Printer") + elif device_type == "SCHS": + return _("Host Services") + else: + return device_type diff --git a/python/web/src/templates/drives.html b/python/web/src/templates/drives.html index 24656035..accaee99 100644 --- a/python/web/src/templates/drives.html +++ b/python/web/src/templates/drives.html @@ -15,7 +15,7 @@