From 3236bea76baaee64c548cfe74b6e2869c1fa5018 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Thu, 14 Aug 2025 02:28:53 +0100 Subject: [PATCH] Moved submodules to directories. --- .gitmodules | 24 - .idea/.idea.Aaru/.idea/vcs.xml | 15 +- Aaru.Checksums | 1 - Aaru.Checksums/.editorconfig | 632 ++ Aaru.Checksums/.gitignore | 595 ++ Aaru.Checksums/Aaru.Checksums.csproj | 79 + Aaru.Checksums/Adler32Context.cs | 165 + Aaru.Checksums/CDChecksums.cs | 648 ++ Aaru.Checksums/CRC16CCITTContext.cs | 103 + Aaru.Checksums/CRC16Context.cs | 243 + Aaru.Checksums/CRC16IBMContext.cs | 102 + Aaru.Checksums/CRC32Context.cs | 234 + Aaru.Checksums/CRC64Context.cs | 240 + Aaru.Checksums/FletcherContext.cs | 292 + Aaru.Checksums/MD5Context.cs | 133 + Aaru.Checksums/ReedSolomon.cs | 730 ++ Aaru.Checksums/Register.cs | 82 + Aaru.Checksums/SHA1Context.cs | 134 + Aaru.Checksums/SHA256Context.cs | 134 + Aaru.Checksums/SHA384Context.cs | 134 + Aaru.Checksums/SHA512Context.cs | 134 + Aaru.Checksums/SpamSumContext.cs | 527 + Aaru.CommonTypes | 1 - Aaru.CommonTypes/.editorconfig | 632 ++ Aaru.CommonTypes/.gitignore | 595 ++ Aaru.CommonTypes/Aaru.CommonTypes.csproj | 121 + .../Aaru.CommonTypes.csproj.DotSettings | 2 + Aaru.CommonTypes/Delegates.cs | 90 + Aaru.CommonTypes/Enums/DeviceType.cs | 59 + Aaru.CommonTypes/Enums/ErrorNumber.cs | 115 + Aaru.CommonTypes/Enums/Images.cs | 395 + Aaru.CommonTypes/Exceptions/Images.cs | 179 + Aaru.CommonTypes/Extents/ExtentsByte.cs | 254 + Aaru.CommonTypes/Extents/ExtentsConverter.cs | 84 + Aaru.CommonTypes/Extents/ExtentsInt.cs | 254 + Aaru.CommonTypes/Extents/ExtentsLong.cs | 254 + Aaru.CommonTypes/Extents/ExtentsSByte.cs | 255 + Aaru.CommonTypes/Extents/ExtentsShort.cs | 255 + Aaru.CommonTypes/Extents/ExtentsUInt.cs | 254 + Aaru.CommonTypes/Extents/ExtentsULong.cs | 255 + Aaru.CommonTypes/Extents/ExtentsUShort.cs | 255 + Aaru.CommonTypes/Filters.cs | 118 + Aaru.CommonTypes/Geometry.cs | 145 + Aaru.CommonTypes/Interfaces/IChecksum.cs | 59 + Aaru.CommonTypes/Interfaces/IFilesystem.cs | 73 + Aaru.CommonTypes/Interfaces/IFilter.cs | 152 + Aaru.CommonTypes/Interfaces/IFloppyImage.cs | 121 + Aaru.CommonTypes/Interfaces/IMediaImage.cs | 117 + .../Interfaces/IOpticalMediaImage.cs | 117 + Aaru.CommonTypes/Interfaces/IPartition.cs | 62 + .../Interfaces/IPartitionableMediaImage.cs | 54 + .../Interfaces/IPluginRegister.cs | 83 + .../Interfaces/IReadOnlyFilesystem.cs | 124 + Aaru.CommonTypes/Interfaces/ITapeImage.cs | 56 + .../Interfaces/IVerifiableImage.cs | 49 + .../Interfaces/IVerifiableSectorsImage.cs | 60 + .../Interfaces/IWritableFloppyImage.cs | 97 + Aaru.CommonTypes/Interfaces/IWritableImage.cs | 154 + .../Interfaces/IWritableOpticalImage.cs | 56 + .../Interfaces/IWritableTapeImage.cs | 64 + Aaru.CommonTypes/Interop/DetectOS.cs | 390 + Aaru.CommonTypes/Interop/PlatformID.cs | 122 + Aaru.CommonTypes/Interop/Version.cs | 91 + Aaru.CommonTypes/MediaType.cs | 1045 ++ Aaru.CommonTypes/MediaType.csv | 532 + .../MediaTypeFromDevice/FromAta.cs | 73 + .../MediaTypeFromDevice/FromMmc.cs | 179 + .../MediaTypeFromDevice/FromOdc.cs | 342 + .../MediaTypeFromDevice/FromSbc.cs | 951 ++ .../MediaTypeFromDevice/FromScsi.cs | 134 + .../MediaTypeFromDevice/FromSsc.cs | 1611 +++ Aaru.CommonTypes/Metadata/CdOffset.cs | 58 + Aaru.CommonTypes/Metadata/DeviceReport.cs | 1070 ++ Aaru.CommonTypes/Metadata/DeviceReportV2.cs | 2307 +++++ Aaru.CommonTypes/Metadata/Dimensions.cs | 1105 ++ Aaru.CommonTypes/Metadata/MediaType.cs | 2559 +++++ Aaru.CommonTypes/Metadata/Resume.cs | 80 + Aaru.CommonTypes/Metadata/Statistics.cs | 309 + Aaru.CommonTypes/Metadata/Version.cs | 56 + Aaru.CommonTypes/Partition.cs | 119 + Aaru.CommonTypes/PluginBase.cs | 140 + .../Structs/Devices/ATA/Identify.cs | 1127 ++ .../Structs/Devices/SCSI/Enums.cs | 245 + .../Structs/Devices/SCSI/Inquiry.cs | 788 ++ .../Structs/Devices/SCSI/Modes/2A.cs | 514 + Aaru.CommonTypes/Structs/Filesystems.cs | 350 + Aaru.CommonTypes/Structs/Images.cs | 190 + Aaru.CommonTypes/Structs/TapeFile.cs | 53 + Aaru.CommonTypes/Structs/TapePartition.cs | 51 + Aaru.Console | 1 - Aaru.Console/.editorconfig | 632 ++ Aaru.Console/.gitignore | 595 ++ Aaru.Console/Aaru.Console.csproj | 50 + Aaru.Console/AaruConsole.cs | 236 + Aaru.Decoders | 1 - Aaru.Decoders/.editorconfig | 632 ++ Aaru.Decoders/.gitignore | 595 ++ Aaru.Decoders/ATA/Identify.cs | 2243 ++++ Aaru.Decoders/ATA/Registers.cs | 114 + Aaru.Decoders/Aaru.Decoders.csproj | 197 + .../Aaru.Decoders.csproj.DotSettings | 2 + Aaru.Decoders/Bluray/BCA.cs | 124 + Aaru.Decoders/Bluray/Cartridge.cs | 180 + Aaru.Decoders/Bluray/DDS.cs | 229 + Aaru.Decoders/Bluray/DI.cs | 580 ++ Aaru.Decoders/Bluray/Spare.cs | 130 + Aaru.Decoders/CD/ATIP.cs | 679 ++ Aaru.Decoders/CD/CDTextOnLeadIn.cs | 377 + Aaru.Decoders/CD/Enums.cs | 73 + Aaru.Decoders/CD/FullTOC.cs | 789 ++ Aaru.Decoders/CD/PMA.cs | 345 + Aaru.Decoders/CD/Sector.cs | 476 + Aaru.Decoders/CD/SectorBuilder.cs | 238 + Aaru.Decoders/CD/Session.cs | 223 + Aaru.Decoders/CD/Subchannel.cs | 594 ++ Aaru.Decoders/CD/TOC.cs | 236 + Aaru.Decoders/DVD/AACS.cs | 67 + Aaru.Decoders/DVD/ADIP.cs | 67 + Aaru.Decoders/DVD/BCA.cs | 67 + Aaru.Decoders/DVD/CPRM.cs | 79 + Aaru.Decoders/DVD/CSS&CPRM.cs | 352 + Aaru.Decoders/DVD/Cartridge.cs | 175 + Aaru.Decoders/DVD/DDS.cs | 251 + Aaru.Decoders/DVD/DMI.cs | 67 + Aaru.Decoders/DVD/Enums.cs | 182 + Aaru.Decoders/DVD/Layers.cs | 139 + Aaru.Decoders/DVD/PFI.cs | 1563 +++ Aaru.Decoders/DVD/PRI.cs | 625 ++ Aaru.Decoders/DVD/RMD.cs | 85 + Aaru.Decoders/DVD/Spare.cs | 109 + Aaru.Decoders/DVD/UDI.cs | 83 + Aaru.Decoders/Floppy/Amiga.cs | 70 + Aaru.Decoders/Floppy/Apple2.cs | 665 ++ Aaru.Decoders/Floppy/AppleSony.cs | 513 + Aaru.Decoders/Floppy/Commodore.cs | 74 + Aaru.Decoders/Floppy/Enums.cs | 78 + Aaru.Decoders/Floppy/ISO.cs | 121 + Aaru.Decoders/Floppy/Perpendicular.cs | 139 + Aaru.Decoders/Floppy/System34.cs | 139 + Aaru.Decoders/Floppy/System3740.cs | 130 + Aaru.Decoders/LisaTag.cs | 506 + Aaru.Decoders/MMC/CID.cs | 214 + Aaru.Decoders/MMC/CSD.cs | 684 ++ Aaru.Decoders/MMC/ExtendedCSD.cs | 1228 +++ Aaru.Decoders/MMC/OCR.cs | 182 + Aaru.Decoders/MMC/VendorString.cs | 49 + Aaru.Decoders/PCMCIA/CIS.cs | 318 + Aaru.Decoders/PCMCIA/Enums.cs | 174 + Aaru.Decoders/PCMCIA/Types.cs | 381 + Aaru.Decoders/PCMCIA/VendorCode.cs | 363 + .../SCSI/DiscStructureCapabilities.cs | 79 + Aaru.Decoders/SCSI/EVPD.cs | 2376 +++++ Aaru.Decoders/SCSI/Inquiry.cs | 2490 +++++ Aaru.Decoders/SCSI/MMC/AACS.cs | 429 + Aaru.Decoders/SCSI/MMC/CPRM.cs | 116 + Aaru.Decoders/SCSI/MMC/DiscInformation.cs | 466 + Aaru.Decoders/SCSI/MMC/Enums.cs | 77 + Aaru.Decoders/SCSI/MMC/Features.cs | 4893 +++++++++ Aaru.Decoders/SCSI/MMC/Hybrid.cs | 196 + Aaru.Decoders/SCSI/MMC/TrackInformation.cs | 110 + Aaru.Decoders/SCSI/MMC/WriteProtect.cs | 157 + Aaru.Decoders/SCSI/Modes/00_SFF.cs | 117 + Aaru.Decoders/SCSI/Modes/01.cs | 229 + Aaru.Decoders/SCSI/Modes/01_MMC.cs | 234 + Aaru.Decoders/SCSI/Modes/02.cs | 190 + Aaru.Decoders/SCSI/Modes/03.cs | 169 + Aaru.Decoders/SCSI/Modes/04.cs | 162 + Aaru.Decoders/SCSI/Modes/05.cs | 313 + Aaru.Decoders/SCSI/Modes/06.cs | 97 + Aaru.Decoders/SCSI/Modes/07.cs | 132 + Aaru.Decoders/SCSI/Modes/07_MMC.cs | 192 + Aaru.Decoders/SCSI/Modes/08.cs | 279 + Aaru.Decoders/SCSI/Modes/0A.cs | 447 + Aaru.Decoders/SCSI/Modes/0B.cs | 115 + Aaru.Decoders/SCSI/Modes/0C.cs | 41 + Aaru.Decoders/SCSI/Modes/0D.cs | 174 + Aaru.Decoders/SCSI/Modes/0E.cs | 280 + Aaru.Decoders/SCSI/Modes/0F.cs | 204 + Aaru.Decoders/SCSI/Modes/10.cs | 135 + Aaru.Decoders/SCSI/Modes/10_SSC.cs | 331 + Aaru.Decoders/SCSI/Modes/11.cs | 250 + Aaru.Decoders/SCSI/Modes/12_13_14.cs | 111 + Aaru.Decoders/SCSI/Modes/1A.cs | 272 + Aaru.Decoders/SCSI/Modes/1B.cs | 122 + Aaru.Decoders/SCSI/Modes/1C.cs | 310 + Aaru.Decoders/SCSI/Modes/1C_SFF.cs | 175 + Aaru.Decoders/SCSI/Modes/1D.cs | 137 + Aaru.Decoders/SCSI/Modes/21_Certance.cs | 205 + Aaru.Decoders/SCSI/Modes/22_Certance.cs | 190 + Aaru.Decoders/SCSI/Modes/24_IBM.cs | 109 + Aaru.Decoders/SCSI/Modes/2A.cs | 243 + Aaru.Decoders/SCSI/Modes/2F_IBM.cs | 195 + Aaru.Decoders/SCSI/Modes/30_Apple.cs | 71 + Aaru.Decoders/SCSI/Modes/3B_HP.cs | 111 + Aaru.Decoders/SCSI/Modes/3C_HP.cs | 152 + Aaru.Decoders/SCSI/Modes/3D_HP.cs | 108 + Aaru.Decoders/SCSI/Modes/3D_IBM.cs | 94 + Aaru.Decoders/SCSI/Modes/3E_Fujitsu.cs | 149 + Aaru.Decoders/SCSI/Modes/3E_HP.cs | 100 + Aaru.Decoders/SCSI/Modes/Headers.cs | 2129 ++++ Aaru.Decoders/SCSI/Modes/Mode10.cs | 360 + Aaru.Decoders/SCSI/Modes/Mode6.cs | 279 + Aaru.Decoders/SCSI/Modes/Structs.cs | 72 + Aaru.Decoders/SCSI/SSC/BlockLimits.cs | 94 + Aaru.Decoders/SCSI/SSC/DensitySupport.cs | 294 + Aaru.Decoders/SCSI/Sense.cs | 2001 ++++ Aaru.Decoders/SCSI/Types.cs | 587 ++ Aaru.Decoders/SCSI/VendorString.cs | 843 ++ Aaru.Decoders/SecureDigital/CID.cs | 129 + Aaru.Decoders/SecureDigital/CSD.cs | 654 ++ Aaru.Decoders/SecureDigital/OCR.cs | 144 + Aaru.Decoders/SecureDigital/SCR.cs | 232 + Aaru.Decoders/SecureDigital/VendorString.cs | 51 + Aaru.Decoders/Sega/CD.cs | 385 + Aaru.Decoders/Sega/Dreamcast.cs | 327 + Aaru.Decoders/Sega/Saturn.cs | 245 + Aaru.Decoders/Xbox/DMI.cs | 283 + Aaru.Decoders/Xbox/SS.cs | 403 + Aaru.Decryption | 1 - Aaru.Decryption/.editorconfig | 632 ++ Aaru.Decryption/.gitignore | 608 ++ Aaru.Decryption/Aaru.Decryption.csproj | 42 + Aaru.Decryption/DVD/CSS.cs | 716 ++ Aaru.Decryption/DVD/Dump.cs | 508 + Aaru.Decryption/Enums.cs | 12 + Aaru.Decryption/LICENSE | 19 + Aaru.Dto | 1 - Aaru.Dto/.editorconfig | 632 ++ Aaru.Dto/.gitignore | 595 ++ Aaru.Dto/Aaru.Dto.csproj | 59 + Aaru.Dto/CdOffsetDto.cs | 68 + Aaru.Dto/DeviceDto.cs | 278 + Aaru.Dto/SyncDto.cs | 59 + Aaru.Dto/UsbProductDto.cs | 57 + Aaru.Dto/UsbVendorDto.cs | 49 + Aaru.Helpers | 1 - Aaru.Helpers/.editorconfig | 632 ++ Aaru.Helpers/.gitignore | 595 ++ Aaru.Helpers/Aaru.Helpers.csproj | 69 + Aaru.Helpers/ArrayFill.cs | 81 + Aaru.Helpers/ArrayIsEmpty.cs | 50 + Aaru.Helpers/BigEndianBitConverter.cs | 324 + Aaru.Helpers/BitEndian.cs | 51 + Aaru.Helpers/CHS.cs | 49 + Aaru.Helpers/CompareBytes.cs | 72 + Aaru.Helpers/CountBits.cs | 49 + Aaru.Helpers/DateHandlers.cs | 389 + Aaru.Helpers/Marshal.cs | 498 + .../MarshallingPropertiesAttribute.cs | 62 + Aaru.Helpers/PrintHex.cs | 136 + Aaru.Helpers/StringHandlers.cs | 185 + Aaru.Helpers/Swapping.cs | 112 + CICMMetadata | 1 - CICMMetadata/.editorconfig | 631 ++ .../.externalToolBuilders/New_Builder.launch | 9 + CICMMetadata/.gitignore | 597 ++ CICMMetadata/.project | 21 + .../.settings/org.eclipse.wst.xsl.core.prefs | 11 + CICMMetadata/CICMMetadata.iml | 9 + CICMMetadata/CICMMetadataEditor.sln | 29 + .../CICMMetadataEditor.Desktop.csproj | 20 + .../CICMMetadataEditor.Desktop/Info.plist | 20 + .../CICMMetadataEditor.Desktop/MacIcon.icns | Bin 0 -> 114177 bytes .../CICMMetadataEditor.Desktop/Program.cs | 46 + .../AppIcon.appiconset/AppIcon-128.png | Bin 0 -> 8125 bytes .../AppIcon.appiconset/AppIcon-128@2x.png | Bin 0 -> 20798 bytes .../AppIcon.appiconset/AppIcon-16.png | Bin 0 -> 711 bytes .../AppIcon.appiconset/AppIcon-16@2x.png | Bin 0 -> 1484 bytes .../AppIcon.appiconset/AppIcon-256.png | Bin 0 -> 20798 bytes .../AppIcon.appiconset/AppIcon-256@2x.png | Bin 0 -> 59335 bytes .../AppIcon.appiconset/AppIcon-32.png | Bin 0 -> 1484 bytes .../AppIcon.appiconset/AppIcon-32@2x.png | Bin 0 -> 3428 bytes .../AppIcon.appiconset/AppIcon-512.png | Bin 0 -> 59335 bytes .../AppIcon.appiconset/AppIcon-512@2x.png | Bin 0 -> 177632 bytes .../AppIcon.appiconset/Contents.json | 68 + .../Assets.xcassets/Contents.json | 6 + .../CICMMetadataEditor.XamMac.csproj | 99 + .../CICMMetadataEditor.XamMac/Info.plist | 30 + .../CICMMetadataEditor.XamMac/Program.cs | 43 + .../CICMMetadataEditor.csproj | 34 + .../CICMMetadataEditor/WrappersForEto.cs | 64 + .../CICMMetadataEditor/dlgBlockMedia.xeto | 678 ++ .../CICMMetadataEditor/dlgBlockMedia.xeto.cs | 1769 ++++ .../CICMMetadataEditor/dlgMetadata.xeto | 373 + .../CICMMetadataEditor/dlgMetadata.xeto.cs | 1291 +++ .../CICMMetadataEditor/dlgOpticalDisc.xeto | 778 ++ .../CICMMetadataEditor/dlgOpticalDisc.xeto.cs | 1979 ++++ CICMMetadata/CICMMetadataEditor/LICENSE | 21 + CICMMetadata/README.md | 28 + CICMMetadata/build.sh | 26 + CICMMetadata/cicm.xml | 1773 ++++ CICMMetadata/cicm.xsd | 3419 +++++++ CICMMetadata/dotnet/cicm.cs | 9090 ++++++++++++++++ CICMMetadata/dotnet/cicm.vb | 9093 +++++++++++++++++ CICMMetadata/java/generated/ATAType.java | 71 + .../java/generated/AdvertisementType.java | 390 + .../java/generated/ArchitecturesType.java | 156 + .../java/generated/AudioBlockType.java | 186 + .../java/generated/AudioMediaType.java | 447 + .../java/generated/AudioTracksType.java | 208 + CICMMetadata/java/generated/BarcodeType.java | 129 + CICMMetadata/java/generated/BarcodesType.java | 78 + .../java/generated/BlockMediaType.java | 1051 ++ .../java/generated/BlockSizeType.java | 81 + .../java/generated/BlockTrackType.java | 308 + CICMMetadata/java/generated/BookType.java | 325 + CICMMetadata/java/generated/BorderType.java | 162 + .../java/generated/CICMMetadataType.java | 886 ++ CICMMetadata/java/generated/CaseScanType.java | 111 + CICMMetadata/java/generated/CaseType.java | 129 + .../java/generated/CategoriesType.java | 76 + CICMMetadata/java/generated/ChecksumType.java | 125 + .../java/generated/ChecksumsType.java | 78 + .../java/generated/ContentsFileType.java | 492 + .../java/generated/CoordinatesType.java | 81 + CICMMetadata/java/generated/CoverType.java | 123 + .../java/generated/DimensionsType.java | 147 + .../java/generated/DirectoryType.java | 476 + CICMMetadata/java/generated/DiscScanType.java | 108 + .../java/generated/DumpHardwareArrayType.java | 78 + .../java/generated/DumpHardwareType.java | 237 + CICMMetadata/java/generated/DumpType.java | 131 + CICMMetadata/java/generated/EVPDType.java | 163 + .../java/generated/ExtendedAttributeType.java | 127 + .../generated/ExtendedAttributesType.java | 76 + CICMMetadata/java/generated/ExtentType.java | 101 + CICMMetadata/java/generated/ExtentsType.java | 76 + .../generated/FileSystemInformationType.java | 76 + .../java/generated/FileSystemType.java | 591 ++ .../java/generated/FileSystemsType.java | 76 + CICMMetadata/java/generated/FileType.java | 96 + .../generated/FilesystemContentsType.java | 137 + CICMMetadata/java/generated/ImageType.java | 127 + CICMMetadata/java/generated/KeywordsType.java | 76 + .../java/generated/LanguagesType.java | 567 + .../java/generated/LayeredTextType.java | 100 + CICMMetadata/java/generated/LayersType.java | 111 + .../java/generated/LinearMediaType.java | 583 ++ CICMMetadata/java/generated/MagazineType.java | 326 + .../java/generated/MediaScanType.java | 108 + .../java/generated/MultiMediaCardType.java | 155 + CICMMetadata/java/generated/OCRType.java | 153 + .../java/generated/ObjectFactory.java | 716 ++ .../java/generated/OpticalDiscType.java | 1406 +++ CICMMetadata/java/generated/PCIType.java | 153 + CICMMetadata/java/generated/PCMCIAType.java | 249 + .../java/generated/PS3EncryptionType.java | 97 + .../java/generated/PartitionType.java | 239 + .../java/generated/RecordingType.java | 292 + .../RequiredOperatingSystemType.java | 104 + .../RequiredOperatingSystemsType.java | 76 + CICMMetadata/java/generated/SCSIType.java | 190 + .../java/generated/ScanProcessingType.java | 128 + CICMMetadata/java/generated/ScanType.java | 198 + CICMMetadata/java/generated/ScannerType.java | 211 + CICMMetadata/java/generated/ScansType.java | 97 + CICMMetadata/java/generated/SectorsType.java | 98 + .../java/generated/SecureDigitalType.java | 155 + .../java/generated/SecuritySectorsType.java | 104 + CICMMetadata/java/generated/SequenceType.java | 190 + CICMMetadata/java/generated/SoftwareType.java | 127 + .../java/generated/SubChannelType.java | 130 + .../java/generated/SubcategoriesType.java | 76 + .../java/generated/SubtitleTracksType.java | 122 + CICMMetadata/java/generated/SystemsType.java | 76 + CICMMetadata/java/generated/TapeFileType.java | 246 + .../java/generated/TapeInformationType.java | 76 + .../java/generated/TapePartitionType.java | 254 + .../java/generated/TrackFlagsType.java | 141 + .../java/generated/TrackIndexType.java | 80 + .../java/generated/TrackIndexesType.java | 76 + .../java/generated/TrackSequenceType.java | 92 + CICMMetadata/java/generated/TrackType.java | 504 + CICMMetadata/java/generated/USBType.java | 125 + .../java/generated/UserManualType.java | 150 + .../java/generated/VariableBlockSizeType.java | 76 + .../java/generated/VideoTracksType.java | 201 + .../generated/XboxSecuritySectorsType.java | 112 + CICMMetadata/java/generated/XboxType.java | 132 + CICMMetadata/samples/advertisement.xml | 56 + CICMMetadata/samples/floppy_and_cd.xml | 241 + CICMMetadata/samples/mixedcd.xml | 258 + CICMMetadata/samples/multiple_floppies.xml | 198 + CICMMetadata/samples/pcirom.xml | 42 + CICMMetadata/samples/pspumd.xml | 263 + 385 files changed, 135357 insertions(+), 40 deletions(-) delete mode 160000 Aaru.Checksums create mode 100644 Aaru.Checksums/.editorconfig create mode 100644 Aaru.Checksums/.gitignore create mode 100644 Aaru.Checksums/Aaru.Checksums.csproj create mode 100644 Aaru.Checksums/Adler32Context.cs create mode 100644 Aaru.Checksums/CDChecksums.cs create mode 100644 Aaru.Checksums/CRC16CCITTContext.cs create mode 100644 Aaru.Checksums/CRC16Context.cs create mode 100644 Aaru.Checksums/CRC16IBMContext.cs create mode 100644 Aaru.Checksums/CRC32Context.cs create mode 100644 Aaru.Checksums/CRC64Context.cs create mode 100644 Aaru.Checksums/FletcherContext.cs create mode 100644 Aaru.Checksums/MD5Context.cs create mode 100644 Aaru.Checksums/ReedSolomon.cs create mode 100644 Aaru.Checksums/Register.cs create mode 100644 Aaru.Checksums/SHA1Context.cs create mode 100644 Aaru.Checksums/SHA256Context.cs create mode 100644 Aaru.Checksums/SHA384Context.cs create mode 100644 Aaru.Checksums/SHA512Context.cs create mode 100644 Aaru.Checksums/SpamSumContext.cs delete mode 160000 Aaru.CommonTypes create mode 100644 Aaru.CommonTypes/.editorconfig create mode 100644 Aaru.CommonTypes/.gitignore create mode 100644 Aaru.CommonTypes/Aaru.CommonTypes.csproj create mode 100644 Aaru.CommonTypes/Aaru.CommonTypes.csproj.DotSettings create mode 100644 Aaru.CommonTypes/Delegates.cs create mode 100644 Aaru.CommonTypes/Enums/DeviceType.cs create mode 100644 Aaru.CommonTypes/Enums/ErrorNumber.cs create mode 100644 Aaru.CommonTypes/Enums/Images.cs create mode 100644 Aaru.CommonTypes/Exceptions/Images.cs create mode 100644 Aaru.CommonTypes/Extents/ExtentsByte.cs create mode 100644 Aaru.CommonTypes/Extents/ExtentsConverter.cs create mode 100644 Aaru.CommonTypes/Extents/ExtentsInt.cs create mode 100644 Aaru.CommonTypes/Extents/ExtentsLong.cs create mode 100644 Aaru.CommonTypes/Extents/ExtentsSByte.cs create mode 100644 Aaru.CommonTypes/Extents/ExtentsShort.cs create mode 100644 Aaru.CommonTypes/Extents/ExtentsUInt.cs create mode 100644 Aaru.CommonTypes/Extents/ExtentsULong.cs create mode 100644 Aaru.CommonTypes/Extents/ExtentsUShort.cs create mode 100644 Aaru.CommonTypes/Filters.cs create mode 100644 Aaru.CommonTypes/Geometry.cs create mode 100644 Aaru.CommonTypes/Interfaces/IChecksum.cs create mode 100644 Aaru.CommonTypes/Interfaces/IFilesystem.cs create mode 100644 Aaru.CommonTypes/Interfaces/IFilter.cs create mode 100644 Aaru.CommonTypes/Interfaces/IFloppyImage.cs create mode 100644 Aaru.CommonTypes/Interfaces/IMediaImage.cs create mode 100644 Aaru.CommonTypes/Interfaces/IOpticalMediaImage.cs create mode 100644 Aaru.CommonTypes/Interfaces/IPartition.cs create mode 100644 Aaru.CommonTypes/Interfaces/IPartitionableMediaImage.cs create mode 100644 Aaru.CommonTypes/Interfaces/IPluginRegister.cs create mode 100644 Aaru.CommonTypes/Interfaces/IReadOnlyFilesystem.cs create mode 100644 Aaru.CommonTypes/Interfaces/ITapeImage.cs create mode 100644 Aaru.CommonTypes/Interfaces/IVerifiableImage.cs create mode 100644 Aaru.CommonTypes/Interfaces/IVerifiableSectorsImage.cs create mode 100644 Aaru.CommonTypes/Interfaces/IWritableFloppyImage.cs create mode 100644 Aaru.CommonTypes/Interfaces/IWritableImage.cs create mode 100644 Aaru.CommonTypes/Interfaces/IWritableOpticalImage.cs create mode 100644 Aaru.CommonTypes/Interfaces/IWritableTapeImage.cs create mode 100644 Aaru.CommonTypes/Interop/DetectOS.cs create mode 100644 Aaru.CommonTypes/Interop/PlatformID.cs create mode 100644 Aaru.CommonTypes/Interop/Version.cs create mode 100644 Aaru.CommonTypes/MediaType.cs create mode 100644 Aaru.CommonTypes/MediaType.csv create mode 100644 Aaru.CommonTypes/MediaTypeFromDevice/FromAta.cs create mode 100644 Aaru.CommonTypes/MediaTypeFromDevice/FromMmc.cs create mode 100644 Aaru.CommonTypes/MediaTypeFromDevice/FromOdc.cs create mode 100644 Aaru.CommonTypes/MediaTypeFromDevice/FromSbc.cs create mode 100644 Aaru.CommonTypes/MediaTypeFromDevice/FromScsi.cs create mode 100644 Aaru.CommonTypes/MediaTypeFromDevice/FromSsc.cs create mode 100644 Aaru.CommonTypes/Metadata/CdOffset.cs create mode 100644 Aaru.CommonTypes/Metadata/DeviceReport.cs create mode 100644 Aaru.CommonTypes/Metadata/DeviceReportV2.cs create mode 100644 Aaru.CommonTypes/Metadata/Dimensions.cs create mode 100644 Aaru.CommonTypes/Metadata/MediaType.cs create mode 100644 Aaru.CommonTypes/Metadata/Resume.cs create mode 100644 Aaru.CommonTypes/Metadata/Statistics.cs create mode 100644 Aaru.CommonTypes/Metadata/Version.cs create mode 100644 Aaru.CommonTypes/Partition.cs create mode 100644 Aaru.CommonTypes/PluginBase.cs create mode 100644 Aaru.CommonTypes/Structs/Devices/ATA/Identify.cs create mode 100644 Aaru.CommonTypes/Structs/Devices/SCSI/Enums.cs create mode 100644 Aaru.CommonTypes/Structs/Devices/SCSI/Inquiry.cs create mode 100644 Aaru.CommonTypes/Structs/Devices/SCSI/Modes/2A.cs create mode 100644 Aaru.CommonTypes/Structs/Filesystems.cs create mode 100644 Aaru.CommonTypes/Structs/Images.cs create mode 100644 Aaru.CommonTypes/Structs/TapeFile.cs create mode 100644 Aaru.CommonTypes/Structs/TapePartition.cs delete mode 160000 Aaru.Console create mode 100644 Aaru.Console/.editorconfig create mode 100644 Aaru.Console/.gitignore create mode 100644 Aaru.Console/Aaru.Console.csproj create mode 100644 Aaru.Console/AaruConsole.cs delete mode 160000 Aaru.Decoders create mode 100644 Aaru.Decoders/.editorconfig create mode 100644 Aaru.Decoders/.gitignore create mode 100644 Aaru.Decoders/ATA/Identify.cs create mode 100644 Aaru.Decoders/ATA/Registers.cs create mode 100644 Aaru.Decoders/Aaru.Decoders.csproj create mode 100644 Aaru.Decoders/Aaru.Decoders.csproj.DotSettings create mode 100644 Aaru.Decoders/Bluray/BCA.cs create mode 100644 Aaru.Decoders/Bluray/Cartridge.cs create mode 100644 Aaru.Decoders/Bluray/DDS.cs create mode 100644 Aaru.Decoders/Bluray/DI.cs create mode 100644 Aaru.Decoders/Bluray/Spare.cs create mode 100644 Aaru.Decoders/CD/ATIP.cs create mode 100644 Aaru.Decoders/CD/CDTextOnLeadIn.cs create mode 100644 Aaru.Decoders/CD/Enums.cs create mode 100644 Aaru.Decoders/CD/FullTOC.cs create mode 100644 Aaru.Decoders/CD/PMA.cs create mode 100644 Aaru.Decoders/CD/Sector.cs create mode 100644 Aaru.Decoders/CD/SectorBuilder.cs create mode 100644 Aaru.Decoders/CD/Session.cs create mode 100644 Aaru.Decoders/CD/Subchannel.cs create mode 100644 Aaru.Decoders/CD/TOC.cs create mode 100644 Aaru.Decoders/DVD/AACS.cs create mode 100644 Aaru.Decoders/DVD/ADIP.cs create mode 100644 Aaru.Decoders/DVD/BCA.cs create mode 100644 Aaru.Decoders/DVD/CPRM.cs create mode 100644 Aaru.Decoders/DVD/CSS&CPRM.cs create mode 100644 Aaru.Decoders/DVD/Cartridge.cs create mode 100644 Aaru.Decoders/DVD/DDS.cs create mode 100644 Aaru.Decoders/DVD/DMI.cs create mode 100644 Aaru.Decoders/DVD/Enums.cs create mode 100644 Aaru.Decoders/DVD/Layers.cs create mode 100644 Aaru.Decoders/DVD/PFI.cs create mode 100644 Aaru.Decoders/DVD/PRI.cs create mode 100644 Aaru.Decoders/DVD/RMD.cs create mode 100644 Aaru.Decoders/DVD/Spare.cs create mode 100644 Aaru.Decoders/DVD/UDI.cs create mode 100644 Aaru.Decoders/Floppy/Amiga.cs create mode 100644 Aaru.Decoders/Floppy/Apple2.cs create mode 100644 Aaru.Decoders/Floppy/AppleSony.cs create mode 100644 Aaru.Decoders/Floppy/Commodore.cs create mode 100644 Aaru.Decoders/Floppy/Enums.cs create mode 100644 Aaru.Decoders/Floppy/ISO.cs create mode 100644 Aaru.Decoders/Floppy/Perpendicular.cs create mode 100644 Aaru.Decoders/Floppy/System34.cs create mode 100644 Aaru.Decoders/Floppy/System3740.cs create mode 100644 Aaru.Decoders/LisaTag.cs create mode 100644 Aaru.Decoders/MMC/CID.cs create mode 100644 Aaru.Decoders/MMC/CSD.cs create mode 100644 Aaru.Decoders/MMC/ExtendedCSD.cs create mode 100644 Aaru.Decoders/MMC/OCR.cs create mode 100644 Aaru.Decoders/MMC/VendorString.cs create mode 100644 Aaru.Decoders/PCMCIA/CIS.cs create mode 100644 Aaru.Decoders/PCMCIA/Enums.cs create mode 100644 Aaru.Decoders/PCMCIA/Types.cs create mode 100644 Aaru.Decoders/PCMCIA/VendorCode.cs create mode 100644 Aaru.Decoders/SCSI/DiscStructureCapabilities.cs create mode 100644 Aaru.Decoders/SCSI/EVPD.cs create mode 100644 Aaru.Decoders/SCSI/Inquiry.cs create mode 100644 Aaru.Decoders/SCSI/MMC/AACS.cs create mode 100644 Aaru.Decoders/SCSI/MMC/CPRM.cs create mode 100644 Aaru.Decoders/SCSI/MMC/DiscInformation.cs create mode 100644 Aaru.Decoders/SCSI/MMC/Enums.cs create mode 100644 Aaru.Decoders/SCSI/MMC/Features.cs create mode 100644 Aaru.Decoders/SCSI/MMC/Hybrid.cs create mode 100644 Aaru.Decoders/SCSI/MMC/TrackInformation.cs create mode 100644 Aaru.Decoders/SCSI/MMC/WriteProtect.cs create mode 100644 Aaru.Decoders/SCSI/Modes/00_SFF.cs create mode 100644 Aaru.Decoders/SCSI/Modes/01.cs create mode 100644 Aaru.Decoders/SCSI/Modes/01_MMC.cs create mode 100644 Aaru.Decoders/SCSI/Modes/02.cs create mode 100644 Aaru.Decoders/SCSI/Modes/03.cs create mode 100644 Aaru.Decoders/SCSI/Modes/04.cs create mode 100644 Aaru.Decoders/SCSI/Modes/05.cs create mode 100644 Aaru.Decoders/SCSI/Modes/06.cs create mode 100644 Aaru.Decoders/SCSI/Modes/07.cs create mode 100644 Aaru.Decoders/SCSI/Modes/07_MMC.cs create mode 100644 Aaru.Decoders/SCSI/Modes/08.cs create mode 100644 Aaru.Decoders/SCSI/Modes/0A.cs create mode 100644 Aaru.Decoders/SCSI/Modes/0B.cs create mode 100644 Aaru.Decoders/SCSI/Modes/0C.cs create mode 100644 Aaru.Decoders/SCSI/Modes/0D.cs create mode 100644 Aaru.Decoders/SCSI/Modes/0E.cs create mode 100644 Aaru.Decoders/SCSI/Modes/0F.cs create mode 100644 Aaru.Decoders/SCSI/Modes/10.cs create mode 100644 Aaru.Decoders/SCSI/Modes/10_SSC.cs create mode 100644 Aaru.Decoders/SCSI/Modes/11.cs create mode 100644 Aaru.Decoders/SCSI/Modes/12_13_14.cs create mode 100644 Aaru.Decoders/SCSI/Modes/1A.cs create mode 100644 Aaru.Decoders/SCSI/Modes/1B.cs create mode 100644 Aaru.Decoders/SCSI/Modes/1C.cs create mode 100644 Aaru.Decoders/SCSI/Modes/1C_SFF.cs create mode 100644 Aaru.Decoders/SCSI/Modes/1D.cs create mode 100644 Aaru.Decoders/SCSI/Modes/21_Certance.cs create mode 100644 Aaru.Decoders/SCSI/Modes/22_Certance.cs create mode 100644 Aaru.Decoders/SCSI/Modes/24_IBM.cs create mode 100644 Aaru.Decoders/SCSI/Modes/2A.cs create mode 100644 Aaru.Decoders/SCSI/Modes/2F_IBM.cs create mode 100644 Aaru.Decoders/SCSI/Modes/30_Apple.cs create mode 100644 Aaru.Decoders/SCSI/Modes/3B_HP.cs create mode 100644 Aaru.Decoders/SCSI/Modes/3C_HP.cs create mode 100644 Aaru.Decoders/SCSI/Modes/3D_HP.cs create mode 100644 Aaru.Decoders/SCSI/Modes/3D_IBM.cs create mode 100644 Aaru.Decoders/SCSI/Modes/3E_Fujitsu.cs create mode 100644 Aaru.Decoders/SCSI/Modes/3E_HP.cs create mode 100644 Aaru.Decoders/SCSI/Modes/Headers.cs create mode 100644 Aaru.Decoders/SCSI/Modes/Mode10.cs create mode 100644 Aaru.Decoders/SCSI/Modes/Mode6.cs create mode 100644 Aaru.Decoders/SCSI/Modes/Structs.cs create mode 100644 Aaru.Decoders/SCSI/SSC/BlockLimits.cs create mode 100644 Aaru.Decoders/SCSI/SSC/DensitySupport.cs create mode 100644 Aaru.Decoders/SCSI/Sense.cs create mode 100644 Aaru.Decoders/SCSI/Types.cs create mode 100644 Aaru.Decoders/SCSI/VendorString.cs create mode 100644 Aaru.Decoders/SecureDigital/CID.cs create mode 100644 Aaru.Decoders/SecureDigital/CSD.cs create mode 100644 Aaru.Decoders/SecureDigital/OCR.cs create mode 100644 Aaru.Decoders/SecureDigital/SCR.cs create mode 100644 Aaru.Decoders/SecureDigital/VendorString.cs create mode 100644 Aaru.Decoders/Sega/CD.cs create mode 100644 Aaru.Decoders/Sega/Dreamcast.cs create mode 100644 Aaru.Decoders/Sega/Saturn.cs create mode 100644 Aaru.Decoders/Xbox/DMI.cs create mode 100644 Aaru.Decoders/Xbox/SS.cs delete mode 160000 Aaru.Decryption create mode 100644 Aaru.Decryption/.editorconfig create mode 100644 Aaru.Decryption/.gitignore create mode 100644 Aaru.Decryption/Aaru.Decryption.csproj create mode 100644 Aaru.Decryption/DVD/CSS.cs create mode 100644 Aaru.Decryption/DVD/Dump.cs create mode 100644 Aaru.Decryption/Enums.cs create mode 100644 Aaru.Decryption/LICENSE delete mode 160000 Aaru.Dto create mode 100644 Aaru.Dto/.editorconfig create mode 100644 Aaru.Dto/.gitignore create mode 100644 Aaru.Dto/Aaru.Dto.csproj create mode 100644 Aaru.Dto/CdOffsetDto.cs create mode 100644 Aaru.Dto/DeviceDto.cs create mode 100644 Aaru.Dto/SyncDto.cs create mode 100644 Aaru.Dto/UsbProductDto.cs create mode 100644 Aaru.Dto/UsbVendorDto.cs delete mode 160000 Aaru.Helpers create mode 100644 Aaru.Helpers/.editorconfig create mode 100644 Aaru.Helpers/.gitignore create mode 100644 Aaru.Helpers/Aaru.Helpers.csproj create mode 100644 Aaru.Helpers/ArrayFill.cs create mode 100644 Aaru.Helpers/ArrayIsEmpty.cs create mode 100644 Aaru.Helpers/BigEndianBitConverter.cs create mode 100644 Aaru.Helpers/BitEndian.cs create mode 100644 Aaru.Helpers/CHS.cs create mode 100644 Aaru.Helpers/CompareBytes.cs create mode 100644 Aaru.Helpers/CountBits.cs create mode 100644 Aaru.Helpers/DateHandlers.cs create mode 100644 Aaru.Helpers/Marshal.cs create mode 100644 Aaru.Helpers/MarshallingPropertiesAttribute.cs create mode 100644 Aaru.Helpers/PrintHex.cs create mode 100644 Aaru.Helpers/StringHandlers.cs create mode 100644 Aaru.Helpers/Swapping.cs delete mode 160000 CICMMetadata create mode 100644 CICMMetadata/.editorconfig create mode 100644 CICMMetadata/.externalToolBuilders/New_Builder.launch create mode 100644 CICMMetadata/.gitignore create mode 100644 CICMMetadata/.project create mode 100644 CICMMetadata/.settings/org.eclipse.wst.xsl.core.prefs create mode 100644 CICMMetadata/CICMMetadata.iml create mode 100644 CICMMetadata/CICMMetadataEditor.sln create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.Desktop/CICMMetadataEditor.Desktop.csproj create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.Desktop/Info.plist create mode 100755 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.Desktop/MacIcon.icns create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.Desktop/Program.cs create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-128.png create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-128@2x.png create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-16.png create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-16@2x.png create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-256.png create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-256@2x.png create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-32.png create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-32@2x.png create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-512.png create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/Contents.json create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/CICMMetadataEditor.XamMac.csproj create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Info.plist create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Program.cs create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/CICMMetadataEditor.csproj create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/WrappersForEto.cs create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgBlockMedia.xeto create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgBlockMedia.xeto.cs create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgMetadata.xeto create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgMetadata.xeto.cs create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgOpticalDisc.xeto create mode 100644 CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgOpticalDisc.xeto.cs create mode 100644 CICMMetadata/CICMMetadataEditor/LICENSE create mode 100644 CICMMetadata/README.md create mode 100755 CICMMetadata/build.sh create mode 100644 CICMMetadata/cicm.xml create mode 100644 CICMMetadata/cicm.xsd create mode 100644 CICMMetadata/dotnet/cicm.cs create mode 100644 CICMMetadata/dotnet/cicm.vb create mode 100644 CICMMetadata/java/generated/ATAType.java create mode 100644 CICMMetadata/java/generated/AdvertisementType.java create mode 100644 CICMMetadata/java/generated/ArchitecturesType.java create mode 100644 CICMMetadata/java/generated/AudioBlockType.java create mode 100644 CICMMetadata/java/generated/AudioMediaType.java create mode 100644 CICMMetadata/java/generated/AudioTracksType.java create mode 100644 CICMMetadata/java/generated/BarcodeType.java create mode 100644 CICMMetadata/java/generated/BarcodesType.java create mode 100644 CICMMetadata/java/generated/BlockMediaType.java create mode 100644 CICMMetadata/java/generated/BlockSizeType.java create mode 100644 CICMMetadata/java/generated/BlockTrackType.java create mode 100644 CICMMetadata/java/generated/BookType.java create mode 100644 CICMMetadata/java/generated/BorderType.java create mode 100644 CICMMetadata/java/generated/CICMMetadataType.java create mode 100644 CICMMetadata/java/generated/CaseScanType.java create mode 100644 CICMMetadata/java/generated/CaseType.java create mode 100644 CICMMetadata/java/generated/CategoriesType.java create mode 100644 CICMMetadata/java/generated/ChecksumType.java create mode 100644 CICMMetadata/java/generated/ChecksumsType.java create mode 100644 CICMMetadata/java/generated/ContentsFileType.java create mode 100644 CICMMetadata/java/generated/CoordinatesType.java create mode 100644 CICMMetadata/java/generated/CoverType.java create mode 100644 CICMMetadata/java/generated/DimensionsType.java create mode 100644 CICMMetadata/java/generated/DirectoryType.java create mode 100644 CICMMetadata/java/generated/DiscScanType.java create mode 100644 CICMMetadata/java/generated/DumpHardwareArrayType.java create mode 100644 CICMMetadata/java/generated/DumpHardwareType.java create mode 100644 CICMMetadata/java/generated/DumpType.java create mode 100644 CICMMetadata/java/generated/EVPDType.java create mode 100644 CICMMetadata/java/generated/ExtendedAttributeType.java create mode 100644 CICMMetadata/java/generated/ExtendedAttributesType.java create mode 100644 CICMMetadata/java/generated/ExtentType.java create mode 100644 CICMMetadata/java/generated/ExtentsType.java create mode 100644 CICMMetadata/java/generated/FileSystemInformationType.java create mode 100644 CICMMetadata/java/generated/FileSystemType.java create mode 100644 CICMMetadata/java/generated/FileSystemsType.java create mode 100644 CICMMetadata/java/generated/FileType.java create mode 100644 CICMMetadata/java/generated/FilesystemContentsType.java create mode 100644 CICMMetadata/java/generated/ImageType.java create mode 100644 CICMMetadata/java/generated/KeywordsType.java create mode 100644 CICMMetadata/java/generated/LanguagesType.java create mode 100644 CICMMetadata/java/generated/LayeredTextType.java create mode 100644 CICMMetadata/java/generated/LayersType.java create mode 100644 CICMMetadata/java/generated/LinearMediaType.java create mode 100644 CICMMetadata/java/generated/MagazineType.java create mode 100644 CICMMetadata/java/generated/MediaScanType.java create mode 100644 CICMMetadata/java/generated/MultiMediaCardType.java create mode 100644 CICMMetadata/java/generated/OCRType.java create mode 100644 CICMMetadata/java/generated/ObjectFactory.java create mode 100644 CICMMetadata/java/generated/OpticalDiscType.java create mode 100644 CICMMetadata/java/generated/PCIType.java create mode 100644 CICMMetadata/java/generated/PCMCIAType.java create mode 100644 CICMMetadata/java/generated/PS3EncryptionType.java create mode 100644 CICMMetadata/java/generated/PartitionType.java create mode 100644 CICMMetadata/java/generated/RecordingType.java create mode 100644 CICMMetadata/java/generated/RequiredOperatingSystemType.java create mode 100644 CICMMetadata/java/generated/RequiredOperatingSystemsType.java create mode 100644 CICMMetadata/java/generated/SCSIType.java create mode 100644 CICMMetadata/java/generated/ScanProcessingType.java create mode 100644 CICMMetadata/java/generated/ScanType.java create mode 100644 CICMMetadata/java/generated/ScannerType.java create mode 100644 CICMMetadata/java/generated/ScansType.java create mode 100644 CICMMetadata/java/generated/SectorsType.java create mode 100644 CICMMetadata/java/generated/SecureDigitalType.java create mode 100644 CICMMetadata/java/generated/SecuritySectorsType.java create mode 100644 CICMMetadata/java/generated/SequenceType.java create mode 100644 CICMMetadata/java/generated/SoftwareType.java create mode 100644 CICMMetadata/java/generated/SubChannelType.java create mode 100644 CICMMetadata/java/generated/SubcategoriesType.java create mode 100644 CICMMetadata/java/generated/SubtitleTracksType.java create mode 100644 CICMMetadata/java/generated/SystemsType.java create mode 100644 CICMMetadata/java/generated/TapeFileType.java create mode 100644 CICMMetadata/java/generated/TapeInformationType.java create mode 100644 CICMMetadata/java/generated/TapePartitionType.java create mode 100644 CICMMetadata/java/generated/TrackFlagsType.java create mode 100644 CICMMetadata/java/generated/TrackIndexType.java create mode 100644 CICMMetadata/java/generated/TrackIndexesType.java create mode 100644 CICMMetadata/java/generated/TrackSequenceType.java create mode 100644 CICMMetadata/java/generated/TrackType.java create mode 100644 CICMMetadata/java/generated/USBType.java create mode 100644 CICMMetadata/java/generated/UserManualType.java create mode 100644 CICMMetadata/java/generated/VariableBlockSizeType.java create mode 100644 CICMMetadata/java/generated/VideoTracksType.java create mode 100644 CICMMetadata/java/generated/XboxSecuritySectorsType.java create mode 100644 CICMMetadata/java/generated/XboxType.java create mode 100644 CICMMetadata/samples/advertisement.xml create mode 100644 CICMMetadata/samples/floppy_and_cd.xml create mode 100644 CICMMetadata/samples/mixedcd.xml create mode 100644 CICMMetadata/samples/multiple_floppies.xml create mode 100644 CICMMetadata/samples/pcirom.xml create mode 100644 CICMMetadata/samples/pspumd.xml diff --git a/.gitmodules b/.gitmodules index 0a8499607..9775764f9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,27 +1,3 @@ -[submodule "CICMMetadata"] - path = CICMMetadata - url = https://github.com/claunia/CICMMetadata -[submodule "Aaru.Checksums"] - path = Aaru.Checksums - url = https://github.com/aaru-dps/Aaru.Checksums -[submodule "Aaru.CommonTypes"] - path = Aaru.CommonTypes - url = https://github.com/aaru-dps/Aaru.CommonTypes -[submodule "Aaru.Console"] - path = Aaru.Console - url = https://github.com/aaru-dps/Aaru.Console -[submodule "Aaru.Decoders"] - path = Aaru.Decoders - url = https://github.com/aaru-dps/Aaru.Decoders -[submodule "Aaru.Dto"] - path = Aaru.Dto - url = https://github.com/aaru-dps/Aaru.Dto -[submodule "Aaru.Helpers"] - path = Aaru.Helpers - url = https://github.com/aaru-dps/Aaru.Helpers [submodule "cuetools.net"] path = Aaru.Compression/cuetools.net url = https://github.com/gchudov/cuetools.net -[submodule "Aaru.Decryption"] - path = Aaru.Decryption - url = https://github.com/aaru-dps/Aaru.Decryption diff --git a/.idea/.idea.Aaru/.idea/vcs.xml b/.idea/.idea.Aaru/.idea/vcs.xml index 361dcec1e..0200e55f5 100644 --- a/.idea/.idea.Aaru/.idea/vcs.xml +++ b/.idea/.idea.Aaru/.idea/vcs.xml @@ -7,14 +7,13 @@ - - - - - - - - + + + + + + + \ No newline at end of file diff --git a/Aaru.Checksums b/Aaru.Checksums deleted file mode 160000 index b5a6772dc..000000000 --- a/Aaru.Checksums +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b5a6772dcf101d3f8667c69ecba256c5f988d30b diff --git a/Aaru.Checksums/.editorconfig b/Aaru.Checksums/.editorconfig new file mode 100644 index 000000000..9181fe501 --- /dev/null +++ b/Aaru.Checksums/.editorconfig @@ -0,0 +1,632 @@ +root = true + +[*] +charset = utf-8 +next_line = crlf +insert_final_newline = false +indent_style = space +indent_size = 4 + +# Generic non-language specific ones for Resharper and friends +brace_style = next_line +int_align = true +keep_existing_arrangement = false +place_simple_blocks_on_single_line = true +place_simple_declaration_blocks_on_single_line = true +place_attribute_on_same_line = false +space_after_unary_operator = false +space_after_comma = true +space_around_ternary_operator = true +space_around_binary_operator = true +space_around_member_access_operator = false +space_before_open_square_brackets = false +space_after_keywords_in_control_flow_statements = true +space_before_comma = false +space_between_method_call_name_and_opening_parenthesis = false +space_between_method_declaration_name_and_open_parenthesis = false +space_between_square_brackets = false +space_between_parentheses_of_control_flow_statements = false +accessor_owner_declaration_braces = next_line +accessor_declaration_braces = next_line +case_block_braces = next_line +initializer_braces = next_line +other_braces = next_line +allow_comment_after_lbrace = false +empty_block_style = together_same_line +braces_for_ifelse = not_required +braces_for_for = not_required +braces_for_foreach = not_required +braces_for_while = not_required +braces_for_dowhile = not_required +braces_for_using = not_required +braces_for_lock = not_required +braces_for_fixed = not_required +method_or_operator_body = expression_body +local_function_body = expression_body +constructor_or_destructor_body = expression_body +accessor_owner_body = expression_body +force_attribute_style = join +function_braces = next_line +force_control_statements_braces = always_remove +space_in_singleline_accessorholder = true +type_declaration_braces = next_line +invocable_declaration_braces = next_line +anonymous_method_declaration_braces = next_line +space_between_accessors_in_singleline_property = true +indent_nested_usings_stmt = true +space_within_empty_braces = false +indent_nested_fixed_stmt = true +indent_nested_lock_stmt = true +indent_nested_for_stmt = true +indent_nested_foreach_stmt = true +indent_nested_while_stmt = true +use_continuous_indent_inside_parens = true +indent_method_decl_pars = inside +indent_invocation_pars = inside +indent_statement_pars = inside +indent_typeparam_angles = inside +indent_typearg_angles = inside +indent_pars = inside +indent_preprocessor_if = outdent +indent_preprocessor_region = usual_indent +indent_preprocessor_other = usual_indent +indent_switch_labels = true +indent_type_constraints = true +stick_comment = false +alignment_tab_fill_style = use_spaces +align_multiline_parameter = true +align_multiline_extends_list = true +align_linq_query = true +align_multiline_binary_expressions_chain = true +outdent_binary_ops = true +align_multiline_calls_chain = true +outdent_dots = true +align_multiline_array_and_object_initializer = false +indent_anonymous_method_block = false +align_first_arg_by_paren = true +align_multiline_argument = true +align_tuple_components = true +align_multiline_expression = true +align_multiline_for_stmt = true +align_multiple_declaration = true +align_multline_type_parameter_list = true +align_multline_type_parameter_constrains = true +int_align_fields = true +int_align_properties = true +int_align_methods = true +int_align_parameters = false +int_align_variables = true +int_align_assignments = true +int_align_nested_ternary = true +int_align_invocations = false +int_align_binary_expressions = true +int_align_comments = true +int_align_switch_sections = true +keep_user_linebreaks = false +keep_existing_arrangement = false +keep_existing_linebreaks = false +max_line_length = 120 +wrap_before_comma = false +special_else_if_treatment = true +place_type_attribute_on_same_line = never +place_method_attribute_on_same_line = never +place_accessorholder_attribute_on_same_line = never +place_attribute_on_same_line = never +place_accessor_attribute_on_same_line = never +place_attribute_on_same_line = never +place_field_attribute_on_same_line = never +place_attribute_on_same_line = never +wrap_parameters_style = wrap_if_long +keep_existing_declaration_parens_arrangement = false +wrap_before_declaration_lpar = false +wrap_after_declaration_lpar = false +wrap_before_declaration_rpar = false +place_constructor_initializer_on_same_line = true +keep_existing_expr_member_arrangement = false +place_expr_method_on_single_line = true +place_expr_property_on_single_line = true +place_expr_accessor_on_single_line = true +wrap_before_arrow_with_expressions = false +place_type_constraints_on_same_line = true +wrap_before_first_type_parameter_constraint = true +wrap_multiple_type_parameter_constraints_style = wrap_if_long +wrap_before_type_parameter_langle = true +wrap_before_extends_colon = false +wrap_extends_list_style = wrap_if_long +keep_existing_declaration_block_arrangement = false +place_abstract_accessorholder_on_single_line = true +place_simple_accessorholder_on_single_line = false +place_accessor_with_attrs_holder_on_single_line = false +place_simple_accessor_on_single_line = true +place_simple_method_on_single_line = false +keep_existing_enum_arrangement = false +place_simple_enum_on_single_line = false +wrap_enum_declaration = wrap_if_long +new_line_before_else = true +new_line_before_while = false +wrap_for_stmt_header_style = wrap_if_long +wrap_multiple_declaration_style = wrap_if_long +keep_existing_embedded_arrangement = false +place_simple_embedded_statement_on_same_line = false +place_simple_case_statement_on_same_line = true +keep_existing_embedded_block_arrangement = false +place_simple_embedded_block_on_same_line = false +place_simple_anonymousmethod_on_single_line = false +keep_existing_initializer_arrangement = false +place_simple_initializer_on_single_line = false +wrap_object_and_collection_initializer_style = chop_always +wrap_array_initializer_style = wrap_if_long +wrap_arguments_style = wrap_if_long +keep_existing_invocation_parens_arrangement = false +wrap_after_invocation_lpar = false +wrap_before_invocation_rpar = false +wrap_after_dot_in_method_calls = true +wrap_chained_method_calls = wrap_if_long +wrap_before_binary_opsign = false +wrap_chained_binary_expressions = wrap_if_long +force_chop_compound_if_expression = true +force_chop_compound_while_expression = true +force_chop_compound_do_expression = true +wrap_before_ternary_opsigns = true +wrap_ternary_expr_style = wrap_if_long +nested_ternary_style = expanded +wrap_linq_expressions = wrap_if_long +wrap_before_linq_expression = false +place_linq_into_on_new_line = false +wrap_verbatim_interpolated_strings = wrap_if_long +extra_spaces = remove_all +space_after_keywords_in_control_flow_statements = false +space_between_method_call_name_and_opening_parenthesis = false +space_between_method_declaration_name_and_open_parenthesis = false +space_before_typeof_parentheses = false +space_before_checked_parentheses = false +space_before_sizeof_parentheses = false +space_before_nameof_parentheses = false +space_between_keyword_and_expression = true +space_between_keyword_and_type = true +space_around_assignment_op = true +space_around_logical_op = true +space_around_binary_operator = true +space_around_equality_op = true +space_around_relational_op = true +space_around_bitwise_op = true +space_around_additive_op = true +space_around_multiplicative_op = true +space_around_shift_op = true +space_around_nullcoalescing_op = true +space_around_arrow_op = false +space_after_logical_not_op = false +space_after_unary_operator = false +space_after_cast = false +space_around_dot = false +space_around_lambda_arrow = true +space_before_pointer_asterik_declaration = false +space_before_nullable_mark = false +blank_lines_around_class_definition = 1 +namespace_indentation = all +space_within_template_argument = false +align_union_type_usage = true +space_in_singleline_method = true +space_in_singleline_anonymous_method = true +space_within_single_line_array_initializer_braces = true +space_around_arrow_op = false + +# These are for markup languages (HTML, XML, etc) +spaces_around_eq_in_pi_attribute = false +space_after_last_pi_attribute = true +pi_attributes_indent = align_by_first_attribute +blank_line_after_pi = true +spaces_around_eq_in_attribute = false +space_after_last_attribute = false +space_before_self_closing = true +attribute_style = on_single_line +attribute_indent = align_by_first_attribute +sort_attributes = true +sort_class_selectors = true +max_blank_lines_between_tags = 0 +linebreak_before_all_elements = true +linebreak_before_multiline_elements = true +quote_style = doublequoted +delete_quotes_from_solid_values = false +normalize_tag_names = true + + +[{.babelrc,.stylelintrc,jest.config,.eslintrc,.prettierrc,*.json,*.jsb3,*.jsb2,*.bowerrc}] +indent_size = 2 + +[*.js.map] +indent_size = 2 + +[*.{css,scss}] +indent_size = 2 +declarations_style = separate_lines_for_nonsingle +media_query_style = separate_lines +selector_style = same_line +properties_style = separate_lines_for_nonsingle +brace_style = next_line + +[{.analysis_options,*.yml,*.yaml}] +indent_size = 2 + +# Xml project files +[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] +indent_size = 2 + +# Xml files +[*.{xml,stylecop,resx,ruleset}] +indent_size = 2 + +# Xml config files +[*.{props,targets,config,nuspec}] +indent_size = 2 + +# .net files +[*.{cs,vb}] +# These set the this. / Me. +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning + +# These make it suggest Int32 instead of int, etc. +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# This controls implicit access modifiers +dotnet_style_require_accessibility_modifiers = never:suggestion + +# Prefer non modified fields to be marked readonly +dotnet_style_readonly_field = true:warning + +# Parenthesis settings +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_operators = always_for_clarity:warning + +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:error +dotnet_style_prefer_inferred_tuple_names = true:warning +dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning +dotnet_style_prefer_conditional_expression_over_return = true:warning +dotnet_style_coalesce_expression = true:warning +dotnet_style_null_propagation = true:error + +dotnet_sort_system_directives_first = true + +# Constants in C style, all-caps +dotnet_naming_rule.constant_fields_caps.symbols = constant_fields +dotnet_naming_rule.constant_fields_caps.severity = warning +dotnet_naming_rule.constant_fields_caps.style = caps_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.required_modifiers = const +dotnet_naming_style.caps_style.capitalization = all_upper + +# interfaces should be prefixed with I +dotnet_naming_rule.pascal_case_for_interface.severity = error +dotnet_naming_rule.pascal_case_for_interface.symbols = interfaces_fields +dotnet_naming_rule.pascal_case_for_interface.style = pascal_case_interface_style +dotnet_naming_symbols.interfaces_fields.applicable_kinds = interface +dotnet_naming_style.pascal_case_interface_style.required_prefix = I +dotnet_naming_style.pascal_case_interface_style.capitalization = pascal_case + +## internal and private fields should be _camelCase +dotnet_naming_rule.camel_case_for_private_internal_fields.severity = warning +dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields +dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style +dotnet_naming_symbols.private_internal_fields.applicable_kinds = field +dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal +dotnet_naming_style.camel_case_underscore_style.required_prefix = _ +dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case + +# 2018-12-07 NP: This is not yet working in VS2017 +# local variables should be camelCase +#dotnet_naming_rule.camel_case_for_locals.severity = suggestion +#dotnet_naming_rule.camel_case_for_locals.symbols = local_fields +#dotnet_naming_rule.camel_case_for_locals.style = camel_case_style +#dotnet_naming_symbols.local_fields.applicable_kinds = local +#dotnet_naming_style.camel_case_style.capitalization = camel_case + +[*.cs] +# var var var +csharp_style_var_for_built_in_types = false:warning +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = false:warning + +csharp_style_expression_bodied_methods = when_on_single_line:suggestion +csharp_style_expression_bodied_constructors = when_on_single_line:suggestion +csharp_style_expression_bodied_operators = when_on_single_line:suggestion +csharp_style_expression_bodied_properties = when_on_single_line:suggestion +csharp_style_expression_bodied_indexers = when_on_single_line:suggestion +csharp_style_expression_bodied_accessors = when_on_single_line:suggestion + +csharp_style_pattern_matching_over_is_with_cast_check = true:warning +csharp_style_pattern_matching_over_as_with_null_check = when_on_single_line:warning + +csharp_style_inlined_variable_declaration = true:warning + +csharp_prefer_simple_default_expression = true:warning +csharp_style_deconstructed_variable_declaration = false:warning + +csharp_style_throw_expression = true:warning +csharp_style_conditional_delegate_call = true:warning + +csharp_prefer_braces = false + +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true + +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = flush_left + +csharp_space_after_cast = false +csharp_space_after_keywords_in_control_flow_statements = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = none +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false + +csharp_preserve_single_line_statements = false +csharp_preserve_single_line_blocks = true + +csharp_blank_lines_around_region = 0 +csharp_blank_lines_inside_region = 0 +csharp_blank_lines_before_single_line_comment = 1 +csharp_keep_blank_lines_in_declarations = 1 +csharp_remove_blank_lines_near_braces_in_declarations = true +csharp_blank_lines_after_start_comment = false +csharp_blank_lines_between_using_groups = 0 +csharp_blank_lines_after_using_list = 1 +csharp_blank_lines_around_namespace = 1 +csharp_blank_lines_inside_namespace = 0 +csharp_blank_lines_around_type = 1 +csharp_blank_lines_inside_type = 0 +csharp_blank_lines_around_field = 0 +csharp_blank_lines_around_single_line_field = 0 +csharp_blank_lines_around_property = 1 +csharp_blank_lines_around_single_line_property = 0 +csharp_blank_lines_around_auto_property = 0 +csharp_blank_lines_around_single_line_auto_property = 0 +csharp_blank_lines_around_invocable = 1 +csharp_blank_lines_around_single_line_invocable = 1 +csharp_keep_blank_lines_in_code = 1 +csharp_remove_blank_lines_near_braces_in_code = true +csharp_blank_lines_around_local_method = 1 +csharp_blank_lines_around_single_line_local_method = 1 +csharp_blank_lines_before_control_transfer_statements = 1 +csharp_blank_lines_after_control_transfer_statements = 1 +csharp_blank_lines_before_block_statements = 1 +csharp_blank_lines_after_block_statements = 1 +csharp_blank_lines_before_multiline_statements = 1 +csharp_blank_lines_after_multiline_statements = 1 + +csharp_type_declaration_braces = next_line +csharp_brace_style = next_line +csharp_indent_inside_namespace = true +csharp_invocable_declaration_braces = next_line +csharp_anonymous_method_declaration_braces = next_line +csharp_accessor_owner_declaration_braces = next_line +csharp_accessor_declaration_braces = next_line +csharp_case_block_braces = next_line +csharp_initializer_braces = next_line +csharp_other_braces = next_line +csharp_allow_comment_after_lbrace = false +csharp_empty_block_style = together_same_line + +csharp_for_built_in_types = use_explicit_type +csharp_for_simple_types = use_var_when_evident +csharp_for_other_types = use_explicit_type +csharp_prefer_separate_deconstructed_variables_declaration = true +csharp_prefer_explicit_discard_declaration = false + +csharp_instance_members_qualify_members = none +csharp_builtin_type_reference_style = use_keyword +csharp_prefer_qualified_reference = false +csharp_add_imports_to_deepest_scope = false +csharp_allow_alias = true +csharp_default_private_modifier = implicit +csharp_default_internal_modifier = explicit +csharp_arguments_literal = positional +csharp_arguments_string_literal = positional +csharp_arguments_named = positional +csharp_arguments_anonymous_function = positional +csharp_arguments_other = positional +csharp_braces_for_ifelse = not_required +csharp_braces_for_for = not_required +csharp_braces_for_foreach = not_required +csharp_braces_for_while = not_required +csharp_braces_for_dowhile = not_required +csharp_braces_for_using = not_required +csharp_braces_for_lock = not_required +csharp_braces_for_fixed = not_required +csharp_method_or_operator_body = expression_body +csharp_local_function_body = expression_body +csharp_constructor_or_destructor_body = expression_body +csharp_accessor_owner_body = expression_body +csharp_force_attribute_style = join +csharp_indent_nested_usings_stmt = true + +csharp_builtin_type_reference_for_member_access_style = use_keyword +csharp_indent_nested_fixed_stmt = true +csharp_indent_nested_lock_stmt = true +csharp_indent_nested_for_stmt = true +csharp_indent_nested_foreach_stmt = true +csharp_indent_nested_while_stmt = true +csharp_use_continuous_indent_inside_parens = true +csharp_indent_method_decl_pars = inside +csharp_indent_invocation_pars = inside +csharp_indent_statement_pars = inside +csharp_indent_typeparam_angles = inside +csharp_indent_typearg_angles = inside +csharp_indent_pars = inside +csharp_indent_preprocessor_if = outdent +csharp_indent_preprocessor_region = usual_indent +csharp_indent_preprocessor_other = usual_indent +csharp_indent_switch_labels = true +csharp_indent_type_constraints = true +csharp_stick_comment = false +csharp_alignment_tab_fill_style = use_spaces +csharp_align_multiline_parameter = true +csharp_align_multiline_extends_list = true +csharp_align_linq_query = true +csharp_align_multiline_binary_expressions_chain = true +csharp_outdent_binary_ops = true +csharp_align_multiline_calls_chain = true +csharp_outdent_dots = true +csharp_align_multiline_array_and_object_initializer = false +csharp_indent_anonymous_method_block = false +csharp_align_first_arg_by_paren = true +csharp_align_multiline_argument = true +csharp_align_tuple_components = true +csharp_align_multiline_expression = true +csharp_align_multiline_for_stmt = true +csharp_align_multiple_declaration = true +csharp_align_multline_type_parameter_list = true +csharp_align_multline_type_parameter_constrains = true +csharp_int_align_fields = true +csharp_int_align_properties = true +csharp_int_align_methods = true +csharp_int_align_parameters = false +csharp_int_align_variables = true +csharp_int_align_assignments = true +csharp_int_align_nested_ternary = true +csharp_int_align_invocations = false +csharp_int_align_binary_expressions = true +csharp_int_align_comments = true +csharp_int_align_switch_sections = true +csharp_int_align = true +csharp_keep_user_linebreaks = false +csharp_keep_existing_arrangement = false +csharp_keep_existing_linebreaks = false +csharp_max_line_length = 120 +csharp_wrap_before_comma = false +csharp_special_else_if_treatment = true +csharp_insert_final_newline = false +csharp_place_type_attribute_on_same_line = never +csharp_place_method_attribute_on_same_line = never +csharp_place_accessorholder_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_place_accessor_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_place_field_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_wrap_parameters_style = wrap_if_long +csharp_keep_existing_declaration_parens_arrangement = false +csharp_wrap_before_declaration_lpar = false +csharp_wrap_after_declaration_lpar = false +csharp_wrap_before_declaration_rpar = false +csharp_place_constructor_initializer_on_same_line = true +csharp_keep_existing_expr_member_arrangement = false +csharp_place_expr_method_on_single_line = true +csharp_place_expr_property_on_single_line = true +csharp_place_expr_accessor_on_single_line = true +csharp_wrap_before_arrow_with_expressions = false +csharp_place_type_constraints_on_same_line = true +csharp_wrap_before_first_type_parameter_constraint = true +csharp_wrap_multiple_type_parameter_constraints_style = wrap_if_long +csharp_wrap_before_type_parameter_langle = true +csharp_wrap_before_extends_colon = false +csharp_wrap_extends_list_style = wrap_if_long +csharp_keep_existing_declaration_block_arrangement = false +csharp_place_abstract_accessorholder_on_single_line = true +csharp_place_simple_accessorholder_on_single_line = false +csharp_place_accessor_with_attrs_holder_on_single_line = false +csharp_place_simple_accessor_on_single_line = true +csharp_place_simple_method_on_single_line = false +csharp_keep_existing_enum_arrangement = false +csharp_place_simple_enum_on_single_line = false +csharp_wrap_enum_declaration = wrap_if_long +csharp_new_line_before_else = true +csharp_new_line_before_while = false +csharp_wrap_for_stmt_header_style = wrap_if_long +csharp_wrap_multiple_declaration_style = wrap_if_long +csharp_keep_existing_embedded_arrangement = false +csharp_place_simple_embedded_statement_on_same_line = false +csharp_place_simple_case_statement_on_same_line = true +csharp_keep_existing_embedded_block_arrangement = false +csharp_place_simple_embedded_block_on_same_line = false +csharp_place_simple_anonymousmethod_on_single_line = false +csharp_keep_existing_initializer_arrangement = false +csharp_place_simple_initializer_on_single_line = false +csharp_wrap_object_and_collection_initializer_style = chop_always +csharp_wrap_array_initializer_style = wrap_if_long +csharp_wrap_arguments_style = wrap_if_long +csharp_keep_existing_invocation_parens_arrangement = false +csharp_wrap_after_invocation_lpar = false +csharp_wrap_before_invocation_rpar = false +csharp_wrap_after_dot_in_method_calls = true +csharp_wrap_chained_method_calls = wrap_if_long +csharp_wrap_before_binary_opsign = false +csharp_wrap_chained_binary_expressions = wrap_if_long +csharp_force_chop_compound_if_expression = true +csharp_force_chop_compound_while_expression = true +csharp_force_chop_compound_do_expression = true +csharp_wrap_before_ternary_opsigns = true +csharp_wrap_ternary_expr_style = wrap_if_long +csharp_nested_ternary_style = expanded +csharp_wrap_linq_expressions = wrap_if_long +csharp_wrap_before_linq_expression = false +csharp_place_linq_into_on_new_line = false +csharp_wrap_verbatim_interpolated_strings = wrap_if_long +csharp_extra_spaces = remove_all +csharp_space_after_keywords_in_control_flow_statements = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_before_typeof_parentheses = false +csharp_space_before_checked_parentheses = false +csharp_space_before_sizeof_parentheses = false +csharp_space_before_nameof_parentheses = false +csharp_space_between_keyword_and_expression = true +csharp_space_between_keyword_and_type = true +csharp_space_around_assignment_op = true +csharp_space_around_logical_op = true +csharp_space_around_binary_operator = true +csharp_space_around_equality_op = true +csharp_space_around_relational_op = true +csharp_space_around_bitwise_op = true +csharp_space_around_additive_op = true +csharp_space_around_multiplicative_op = true +csharp_space_around_shift_op = true +csharp_space_around_nullcoalescing_op = true +csharp_space_around_arrow_op = false +csharp_space_after_logical_not_op = false +csharp_space_after_unary_operator = false +csharp_space_after_cast = false +csharp_space_around_dot = false +csharp_space_around_lambda_arrow = true +csharp_space_before_pointer_asterik_declaration = false +csharp_space_before_nullable_mark = false + +[*.cshtml] +linebreaks_around_razor_statements = true +blank_lines_around_razor_functions = true +blank_lines_around_razor_helpers = true +blank_lines_around_razor_sections = true + +# C++ +[*.{cc,cpp,cxx,h,hpp,hxx}] +cpp_indent_access_specifiers_from_class = true +cpp_indent_wrapped_function_names = false +cpp_align_multiline_type_argument = true + +# C, C++ and ObjectiveC +[*.{c,h,cc,cpp,cxx,m,hpp,hxx}] +indent_preprocessor_directives = normal +indent_type_constraints = true + +# Javascript and Typescript +[*.{js,js.map,ts}] +quote_style = doublequoted +termination_style = ensure_semicolon \ No newline at end of file diff --git a/Aaru.Checksums/.gitignore b/Aaru.Checksums/.gitignore new file mode 100644 index 000000000..05c540d38 --- /dev/null +++ b/Aaru.Checksums/.gitignore @@ -0,0 +1,595 @@ +### VisualStudio template +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ +### Linux template + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* +### Xcode template +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +### VisualStudioCode template +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +### C++ template +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o + +# Precompiled Headers +*.gch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +### MonoDevelop template +#User Specific +*.usertasks + +#Mono Project Files +*.resources +test-results/ +### GPG template +secring.* + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests +### CMake template +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +### C template +# Object files +*.ko +*.elf + +# Linker output +*.map +*.exp + +*.so.* + +# Executables +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf +### Windows template +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# NuGet Packages Directory +packages/ +## TODO: If the tool you use requires repositories.config uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +# This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented) +!packages/build/ + + +# Others +sql/ +*.Cache + +# Visual Studio 2017 +.vs + +workspace.xml +cmake-build-debug +### macOS template +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +pkg/**/pkg +pkg/**/src +pkg/**/*.asc +pkg/**/*.sig +pkg/**/*.tar.xz +pkg/**/*.zip +pkg/**/aaru + +.sonarqube \ No newline at end of file diff --git a/Aaru.Checksums/Aaru.Checksums.csproj b/Aaru.Checksums/Aaru.Checksums.csproj new file mode 100644 index 000000000..986ae4fd4 --- /dev/null +++ b/Aaru.Checksums/Aaru.Checksums.csproj @@ -0,0 +1,79 @@ + + + + 2.0 + {CC48B324-A532-4A45-87A6-6F91F7141E8D} + Library + Aaru.Checksums + Aaru.Checksums + $(Version) + false + true + 5.3.2 + Claunia.com + Copyright © 2011-2023 Natalia Portillo + Aaru Data Preservation Suite + Aaru.Checksums + $(Version) + netcoreapp3.1 + 8 + C# implementation of CRC16, CRC32, CRC64, Fletcher, MD5, SHA1, SHA2 and SpamSum. + https://github.com/aaru-dps/ + LGPL-2.1-only + https://github.com/aaru-dps/Aaru.Checksums + true + en-US + true + true + snupkg + Natalia Portillo <claunia@claunia.com> + + + $(Version)+{chash:8} + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + {F8BDF57B-1571-4CD0-84B3-B422088D359A} + Aaru.Helpers + + + {CCAA7AFE-C094-4D82-A66D-630DE8A3F545} + Aaru.Console + + + + + LICENSE.LGPL + + + LICENSE + + + + + + \ No newline at end of file diff --git a/Aaru.Checksums/Adler32Context.cs b/Aaru.Checksums/Adler32Context.cs new file mode 100644 index 000000000..691e57d67 --- /dev/null +++ b/Aaru.Checksums/Adler32Context.cs @@ -0,0 +1,165 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Adler32Context.cs +// Author(s) : Natalia Portillo +// +// Component : Checksums. +// +// --[ Description ] ---------------------------------------------------------- +// +// Implements an Adler-32 algorithm. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.IO; +using System.Text; +using Aaru.CommonTypes.Interfaces; +using Aaru.Helpers; + +namespace Aaru.Checksums +{ + /// + /// Implements the Adler-32 algorithm + public sealed class Adler32Context : IChecksum + { + const ushort ADLER_MODULE = 65521; + ushort _sum1, _sum2; + + /// Initializes the Adler-32 sums + public Adler32Context() + { + _sum1 = 1; + _sum2 = 0; + } + + /// + /// Updates the hash with data. + /// Data buffer. + /// Length of buffer to hash. + public void Update(byte[] data, uint len) + { + for(int i = 0; i < len; i++) + { + _sum1 = (ushort)((_sum1 + data[i]) % ADLER_MODULE); + _sum2 = (ushort)((_sum2 + _sum1) % ADLER_MODULE); + } + } + + /// + /// Updates the hash with data. + /// Data buffer. + public void Update(byte[] data) => Update(data, (uint)data.Length); + + /// + /// Returns a byte array of the hash value. + public byte[] Final() + { + uint finalSum = (uint)((_sum2 << 16) | _sum1); + + return BigEndianBitConverter.GetBytes(finalSum); + } + + /// + /// Returns a hexadecimal representation of the hash value. + public string End() + { + uint finalSum = (uint)((_sum2 << 16) | _sum1); + var adlerOutput = new StringBuilder(); + + for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++) + adlerOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2")); + + return adlerOutput.ToString(); + } + + /// Gets the hash of a file + /// File path. + public static byte[] File(string filename) + { + File(filename, out byte[] hash); + + return hash; + } + + /// Gets the hash of a file in hexadecimal and as a byte array. + /// File path. + /// Byte array of the hash value. + public static string File(string filename, out byte[] hash) + { + var fileStream = new FileStream(filename, FileMode.Open); + + ushort localSum1 = 1; + ushort localSum2 = 0; + + for(int i = 0; i < fileStream.Length; i++) + { + localSum1 = (ushort)((localSum1 + fileStream.ReadByte()) % ADLER_MODULE); + localSum2 = (ushort)((localSum2 + localSum1) % ADLER_MODULE); + } + + uint finalSum = (uint)((localSum2 << 16) | localSum1); + + hash = BigEndianBitConverter.GetBytes(finalSum); + + var adlerOutput = new StringBuilder(); + + foreach(byte h in hash) + adlerOutput.Append(h.ToString("x2")); + + fileStream.Close(); + + return adlerOutput.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Length of the data buffer to hash. + /// Byte array of the hash value. + public static string Data(byte[] data, uint len, out byte[] hash) + { + ushort localSum1 = 1; + ushort localSum2 = 0; + + for(int i = 0; i < len; i++) + { + localSum1 = (ushort)((localSum1 + data[i]) % ADLER_MODULE); + localSum2 = (ushort)((localSum2 + localSum1) % ADLER_MODULE); + } + + uint finalSum = (uint)((localSum2 << 16) | localSum1); + + hash = BigEndianBitConverter.GetBytes(finalSum); + + var adlerOutput = new StringBuilder(); + + foreach(byte h in hash) + adlerOutput.Append(h.ToString("x2")); + + return adlerOutput.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Byte array of the hash value. + public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); + } +} \ No newline at end of file diff --git a/Aaru.Checksums/CDChecksums.cs b/Aaru.Checksums/CDChecksums.cs new file mode 100644 index 000000000..84156ef15 --- /dev/null +++ b/Aaru.Checksums/CDChecksums.cs @@ -0,0 +1,648 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CDChecksums.cs +// Author(s) : Natalia Portillo +// +// Component : Checksums. +// +// --[ Description ] ---------------------------------------------------------- +// +// Implements CD checksums. +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.If not, see. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ECC algorithm from ECM(c) 2002-2011 Neill Corlett +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using Aaru.Console; +using Aaru.Helpers; + +namespace Aaru.Checksums +{ + /// Implements ReedSolomon and CRC32 algorithms as used by CD-ROM + public static class CdChecksums + { + static byte[] _eccFTable; + static byte[] _eccBTable; + static uint[] _edcTable; + + /// Checks the EDC and ECC of a CD sector + /// CD sector + /// + /// true if all checks were correct, false if any of them weren't, and null if none of them + /// are present. + /// + public static bool? CheckCdSector(byte[] buffer) => CheckCdSector(buffer, out _, out _, out _); + + /// Checks the EDC and ECC of a CD sector + /// CD sector + /// + /// true if ECC P is correct, false if it isn't, and null if there is no ECC + /// P in sector. + /// + /// + /// true if ECC Q is correct, false if it isn't, and null if there is no ECC + /// Q in sector. + /// + /// + /// true if EDC is correct, false if it isn't, and null if there is no EDC in + /// sector. + /// + /// + /// true if all checks were correct, false if any of them weren't, and null if none of them + /// are present. + /// + public static bool? CheckCdSector(byte[] buffer, out bool? correctEccP, out bool? correctEccQ, + out bool? correctEdc) + { + correctEccP = null; + correctEccQ = null; + correctEdc = null; + + switch(buffer.Length) + { + case 2448: + { + byte[] subchannel = new byte[96]; + byte[] channel = new byte[2352]; + + Array.Copy(buffer, 0, channel, 0, 2352); + Array.Copy(buffer, 2352, subchannel, 0, 96); + + bool? channelStatus = + CheckCdSectorChannel(channel, out correctEccP, out correctEccQ, out correctEdc); + + bool? subchannelStatus = CheckCdSectorSubChannel(subchannel); + bool? status = null; + + if(channelStatus == false || + subchannelStatus == false) + status = false; + + switch(channelStatus) + { + case null when subchannelStatus == true: + status = true; + + break; + case true when subchannelStatus == null: + status = true; + + break; + } + + return status; + } + + case 2352: return CheckCdSectorChannel(buffer, out correctEccP, out correctEccQ, out correctEdc); + default: return null; + } + } + + static void EccInit() + { + _eccFTable = new byte[256]; + _eccBTable = new byte[256]; + _edcTable = new uint[256]; + + for(uint i = 0; i < 256; i++) + { + uint edc = i; + uint j = (uint)((i << 1) ^ ((i & 0x80) == 0x80 ? 0x11D : 0)); + _eccFTable[i] = (byte)j; + _eccBTable[i ^ j] = (byte)i; + + for(j = 0; j < 8; j++) + edc = (edc >> 1) ^ ((edc & 1) > 0 ? 0xD8018001 : 0); + + _edcTable[i] = edc; + } + } + + static bool CheckEcc(byte[] address, byte[] data, uint majorCount, uint minorCount, uint majorMult, + uint minorInc, byte[] ecc) + { + uint size = majorCount * minorCount; + uint major; + + for(major = 0; major < majorCount; major++) + { + uint index = ((major >> 1) * majorMult) + (major & 1); + byte eccA = 0; + byte eccB = 0; + uint minor; + + for(minor = 0; minor < minorCount; minor++) + { + byte temp = index < 4 ? address[index] : data[index - 4]; + index += minorInc; + + if(index >= size) + index -= size; + + eccA ^= temp; + eccB ^= temp; + eccA = _eccFTable[eccA]; + } + + eccA = _eccBTable[_eccFTable[eccA] ^ eccB]; + + if(ecc[major] != eccA || + ecc[major + majorCount] != (eccA ^ eccB)) + return false; + } + + return true; + } + + static bool? CheckCdSectorChannel(byte[] channel, out bool? correctEccP, out bool? correctEccQ, + out bool? correctEdc) + { + EccInit(); + + correctEccP = null; + correctEccQ = null; + correctEdc = null; + + if(channel[0x000] != 0x00 || + channel[0x001] != 0xFF || + channel[0x002] != 0xFF || + channel[0x003] != 0xFF || + channel[0x004] != 0xFF || + channel[0x005] != 0xFF || + channel[0x006] != 0xFF || + channel[0x007] != 0xFF || + channel[0x008] != 0xFF || + channel[0x009] != 0xFF || + channel[0x00A] != 0xFF || + channel[0x00B] != 0x00) + return null; + + //AaruConsole.DebugWriteLine("CD checksums", "Data sector, address {0:X2}:{1:X2}:{2:X2}", channel[0x00C], + // channel[0x00D], channel[0x00E]); + + if((channel[0x00F] & 0x03) == 0x00) // mode (1 byte) + { + //AaruConsole.DebugWriteLine("CD checksums", "Mode 0 sector at address {0:X2}:{1:X2}:{2:X2}", + // channel[0x00C], channel[0x00D], channel[0x00E]); + for(int i = 0x010; i < 0x930; i++) + if(channel[i] != 0x00) + { + AaruConsole.DebugWriteLine("CD checksums", + "Mode 0 sector with error at address: {0:X2}:{1:X2}:{2:X2}", + channel[0x00C], channel[0x00D], channel[0x00E]); + + return false; + } + + return true; + } + + if((channel[0x00F] & 0x03) == 0x01) // mode (1 byte) + { + //AaruConsole.DebugWriteLine("CD checksums", "Mode 1 sector at address {0:X2}:{1:X2}:{2:X2}", + // channel[0x00C], channel[0x00D], channel[0x00E]); + + if(channel[0x814] != 0x00 || // reserved (8 bytes) + channel[0x815] != 0x00 || + channel[0x816] != 0x00 || + channel[0x817] != 0x00 || + channel[0x818] != 0x00 || + channel[0x819] != 0x00 || + channel[0x81A] != 0x00 || + channel[0x81B] != 0x00) + { + AaruConsole.DebugWriteLine("CD checksums", + "Mode 1 sector with data in reserved bytes at address: {0:X2}:{1:X2}:{2:X2}", + channel[0x00C], channel[0x00D], channel[0x00E]); + + return false; + } + + byte[] address = new byte[4]; + byte[] data = new byte[2060]; + byte[] data2 = new byte[2232]; + byte[] eccP = new byte[172]; + byte[] eccQ = new byte[104]; + + Array.Copy(channel, 0x0C, address, 0, 4); + Array.Copy(channel, 0x10, data, 0, 2060); + Array.Copy(channel, 0x10, data2, 0, 2232); + Array.Copy(channel, 0x81C, eccP, 0, 172); + Array.Copy(channel, 0x8C8, eccQ, 0, 104); + + bool failedEccP = !CheckEcc(address, data, 86, 24, 2, 86, eccP); + bool failedEccQ = !CheckEcc(address, data2, 52, 43, 86, 88, eccQ); + + correctEccP = !failedEccP; + correctEccQ = !failedEccQ; + + if(failedEccP) + AaruConsole.DebugWriteLine("CD checksums", + "Mode 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC P check", + channel[0x00C], channel[0x00D], channel[0x00E]); + + if(failedEccQ) + AaruConsole.DebugWriteLine("CD checksums", + "Mode 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC Q check", + channel[0x00C], channel[0x00D], channel[0x00E]); + + uint storedEdc = BitConverter.ToUInt32(channel, 0x810); + uint calculatedEdc = ComputeEdc(0, channel, 0x810); + + correctEdc = calculatedEdc == storedEdc; + + if(calculatedEdc == storedEdc) + return !failedEccP && !failedEccQ; + + AaruConsole.DebugWriteLine("CD checksums", + "Mode 1 sector at address: {0:X2}:{1:X2}:{2:X2}, got CRC 0x{3:X8} expected 0x{4:X8}", + channel[0x00C], channel[0x00D], channel[0x00E], calculatedEdc, storedEdc); + + return false; + } + + if((channel[0x00F] & 0x03) == 0x02) // mode (1 byte) + { + //AaruConsole.DebugWriteLine("CD checksums", "Mode 2 sector at address {0:X2}:{1:X2}:{2:X2}", + // channel[0x00C], channel[0x00D], channel[0x00E]); + byte[] mode2Sector = new byte[channel.Length - 0x10]; + Array.Copy(channel, 0x10, mode2Sector, 0, mode2Sector.Length); + + if((channel[0x012] & 0x20) == 0x20) // mode 2 form 2 + { + if(channel[0x010] != channel[0x014] || + channel[0x011] != channel[0x015] || + channel[0x012] != channel[0x016] || + channel[0x013] != channel[0x017]) + AaruConsole.DebugWriteLine("CD checksums", + "Subheader copies differ in mode 2 form 2 sector at address: {0:X2}:{1:X2}:{2:X2}", + channel[0x00C], channel[0x00D], channel[0x00E]); + + uint storedEdc = BitConverter.ToUInt32(mode2Sector, 0x91C); + + // No CRC stored! + if(storedEdc == 0x00000000) + return true; + + uint calculatedEdc = ComputeEdc(0, mode2Sector, 0x91C); + + correctEdc = calculatedEdc == storedEdc || storedEdc == 0; + + if(calculatedEdc == storedEdc || + storedEdc == 0x00000000) + return true; + + AaruConsole.DebugWriteLine("CD checksums", + "Mode 2 form 2 sector at address: {0:X2}:{1:X2}:{2:X2}, got CRC 0x{3:X8} expected 0x{4:X8}", + channel[0x00C], channel[0x00D], channel[0x00E], calculatedEdc, + storedEdc); + + return false; + } + else + { + if(channel[0x010] != channel[0x014] || + channel[0x011] != channel[0x015] || + channel[0x012] != channel[0x016] || + channel[0x013] != channel[0x017]) + AaruConsole.DebugWriteLine("CD checksums", + "Subheader copies differ in mode 2 form 1 sector at address: {0:X2}:{1:X2}:{2:X2}", + channel[0x00C], channel[0x00D], channel[0x00E]); + + byte[] address = new byte[4]; + byte[] eccP = new byte[172]; + byte[] eccQ = new byte[104]; + + Array.Copy(mode2Sector, 0x80C, eccP, 0, 172); + Array.Copy(mode2Sector, 0x8B8, eccQ, 0, 104); + + bool failedEccP = !CheckEcc(address, mode2Sector, 86, 24, 2, 86, eccP); + bool failedEccQ = !CheckEcc(address, mode2Sector, 52, 43, 86, 88, eccQ); + + correctEccP = !failedEccP; + correctEccQ = !failedEccQ; + + if(failedEccP) + AaruConsole.DebugWriteLine("CD checksums", + "Mode 2 form 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC P check", + channel[0x00C], channel[0x00D], channel[0x00E]); + + if(failedEccQ) + AaruConsole.DebugWriteLine("CD checksums", + "Mode 2 form 1 sector at address: {0:X2}:{1:X2}:{2:X2}, fails ECC Q check", + channel[0x00C], channel[0x00D], channel[0x00E]); + + uint storedEdc = BitConverter.ToUInt32(mode2Sector, 0x808); + uint calculatedEdc = ComputeEdc(0, mode2Sector, 0x808); + + correctEdc = calculatedEdc == storedEdc; + + if(calculatedEdc == storedEdc) + return !failedEccP && !failedEccQ; + + AaruConsole.DebugWriteLine("CD checksums", + "Mode 2 sector at address: {0:X2}:{1:X2}:{2:X2}, got CRC 0x{3:X8} expected 0x{4:X8}", + channel[0x00C], channel[0x00D], channel[0x00E], calculatedEdc, + storedEdc); + + return false; + } + } + + AaruConsole.DebugWriteLine("CD checksums", "Unknown mode {0} sector at address: {1:X2}:{2:X2}:{3:X2}", + channel[0x00F], channel[0x00C], channel[0x00D], channel[0x00E]); + + return null; + } + + static uint ComputeEdc(uint edc, IReadOnlyList src, int size) + { + int pos = 0; + + for(; size > 0; size--) + edc = (edc >> 8) ^ _edcTable[(edc ^ src[pos++]) & 0xFF]; + + return edc; + } + + static bool? CheckCdSectorSubChannel(IReadOnlyList subchannel) + { + bool? status = true; + byte[] qSubChannel = new byte[12]; + byte[] cdTextPack1 = new byte[18]; + byte[] cdTextPack2 = new byte[18]; + byte[] cdTextPack3 = new byte[18]; + byte[] cdTextPack4 = new byte[18]; + byte[] cdSubRwPack1 = new byte[24]; + byte[] cdSubRwPack2 = new byte[24]; + byte[] cdSubRwPack3 = new byte[24]; + byte[] cdSubRwPack4 = new byte[24]; + + int i = 0; + + for(int j = 0; j < 12; j++) + qSubChannel[j] = 0; + + for(int j = 0; j < 18; j++) + { + cdTextPack1[j] = 0; + cdTextPack2[j] = 0; + cdTextPack3[j] = 0; + cdTextPack4[j] = 0; + } + + for(int j = 0; j < 24; j++) + { + cdSubRwPack1[j] = 0; + cdSubRwPack2[j] = 0; + cdSubRwPack3[j] = 0; + cdSubRwPack4[j] = 0; + } + + for(int j = 0; j < 12; j++) + { + qSubChannel[j] = (byte)(qSubChannel[j] | ((subchannel[i++] & 0x40) << 1)); + qSubChannel[j] = (byte)(qSubChannel[j] | (subchannel[i++] & 0x40)); + qSubChannel[j] = (byte)(qSubChannel[j] | ((subchannel[i++] & 0x40) >> 1)); + qSubChannel[j] = (byte)(qSubChannel[j] | ((subchannel[i++] & 0x40) >> 2)); + qSubChannel[j] = (byte)(qSubChannel[j] | ((subchannel[i++] & 0x40) >> 3)); + qSubChannel[j] = (byte)(qSubChannel[j] | ((subchannel[i++] & 0x40) >> 4)); + qSubChannel[j] = (byte)(qSubChannel[j] | ((subchannel[i++] & 0x40) >> 5)); + qSubChannel[j] = (byte)(qSubChannel[j] | ((subchannel[i++] & 0x40) >> 6)); + } + + i = 0; + + for(int j = 0; j < 18; j++) + { + cdTextPack1[j] = (byte)(cdTextPack1[j] | ((subchannel[i++] & 0x3F) << 2)); + + if(j < 17) + cdTextPack1[j] = (byte)(cdTextPack1[j++] | ((subchannel[i] & 0xC0) >> 4)); + + cdTextPack1[j] = (byte)(cdTextPack1[j] | ((subchannel[i++] & 0x0F) << 4)); + + if(j < 17) + cdTextPack1[j] = (byte)(cdTextPack1[j++] | ((subchannel[i] & 0x3C) >> 2)); + + cdTextPack1[j] = (byte)(cdTextPack1[j] | ((subchannel[i++] & 0x03) << 6)); + + cdTextPack1[j] = (byte)(cdTextPack1[j] | (subchannel[i++] & 0x3F)); + } + + for(int j = 0; j < 18; j++) + { + cdTextPack2[j] = (byte)(cdTextPack2[j] | ((subchannel[i++] & 0x3F) << 2)); + + if(j < 17) + cdTextPack2[j] = (byte)(cdTextPack2[j++] | ((subchannel[i] & 0xC0) >> 4)); + + cdTextPack2[j] = (byte)(cdTextPack2[j] | ((subchannel[i++] & 0x0F) << 4)); + + if(j < 17) + cdTextPack2[j] = (byte)(cdTextPack2[j++] | ((subchannel[i] & 0x3C) >> 2)); + + cdTextPack2[j] = (byte)(cdTextPack2[j] | ((subchannel[i++] & 0x03) << 6)); + + cdTextPack2[j] = (byte)(cdTextPack2[j] | (subchannel[i++] & 0x3F)); + } + + for(int j = 0; j < 18; j++) + { + cdTextPack3[j] = (byte)(cdTextPack3[j] | ((subchannel[i++] & 0x3F) << 2)); + + if(j < 17) + cdTextPack3[j] = (byte)(cdTextPack3[j++] | ((subchannel[i] & 0xC0) >> 4)); + + cdTextPack3[j] = (byte)(cdTextPack3[j] | ((subchannel[i++] & 0x0F) << 4)); + + if(j < 17) + cdTextPack3[j] = (byte)(cdTextPack3[j++] | ((subchannel[i] & 0x3C) >> 2)); + + cdTextPack3[j] = (byte)(cdTextPack3[j] | ((subchannel[i++] & 0x03) << 6)); + + cdTextPack3[j] = (byte)(cdTextPack3[j] | (subchannel[i++] & 0x3F)); + } + + for(int j = 0; j < 18; j++) + { + cdTextPack4[j] = (byte)(cdTextPack4[j] | ((subchannel[i++] & 0x3F) << 2)); + + if(j < 17) + cdTextPack4[j] = (byte)(cdTextPack4[j++] | ((subchannel[i] & 0xC0) >> 4)); + + cdTextPack4[j] = (byte)(cdTextPack4[j] | ((subchannel[i++] & 0x0F) << 4)); + + if(j < 17) + cdTextPack4[j] = (byte)(cdTextPack4[j++] | ((subchannel[i] & 0x3C) >> 2)); + + cdTextPack4[j] = (byte)(cdTextPack4[j] | ((subchannel[i++] & 0x03) << 6)); + + cdTextPack4[j] = (byte)(cdTextPack4[j] | (subchannel[i++] & 0x3F)); + } + + i = 0; + + for(int j = 0; j < 24; j++) + cdSubRwPack1[j] = (byte)(subchannel[i++] & 0x3F); + + for(int j = 0; j < 24; j++) + cdSubRwPack2[j] = (byte)(subchannel[i++] & 0x3F); + + for(int j = 0; j < 24; j++) + cdSubRwPack3[j] = (byte)(subchannel[i++] & 0x3F); + + for(int j = 0; j < 24; j++) + cdSubRwPack4[j] = (byte)(subchannel[i++] & 0x3F); + + switch(cdSubRwPack1[0]) + { + case 0x00: + AaruConsole.DebugWriteLine("CD checksums", "Detected Zero Pack in subchannel"); + + break; + case 0x08: + AaruConsole.DebugWriteLine("CD checksums", "Detected Line Graphics Pack in subchannel"); + + break; + case 0x09: + AaruConsole.DebugWriteLine("CD checksums", "Detected CD+G Pack in subchannel"); + + break; + case 0x0A: + AaruConsole.DebugWriteLine("CD checksums", "Detected CD+EG Pack in subchannel"); + + break; + case 0x14: + AaruConsole.DebugWriteLine("CD checksums", "Detected CD-TEXT Pack in subchannel"); + + break; + case 0x18: + AaruConsole.DebugWriteLine("CD checksums", "Detected CD+MIDI Pack in subchannel"); + + break; + case 0x38: + AaruConsole.DebugWriteLine("CD checksums", "Detected User Pack in subchannel"); + + break; + default: + AaruConsole.DebugWriteLine("CD checksums", + "Detected unknown Pack type in subchannel: mode {0}, item {1}", + Convert.ToString(cdSubRwPack1[0] & 0x38, 2), + Convert.ToString(cdSubRwPack1[0] & 0x07, 2)); + + break; + } + + ushort qSubChannelCrc = BigEndianBitConverter.ToUInt16(qSubChannel, 10); + byte[] qSubChannelForCrc = new byte[10]; + Array.Copy(qSubChannel, 0, qSubChannelForCrc, 0, 10); + ushort calculatedQcrc = CRC16CCITTContext.Calculate(qSubChannelForCrc); + + if(qSubChannelCrc != calculatedQcrc) + { + AaruConsole.DebugWriteLine("CD checksums", "Q subchannel CRC 0x{0:X4}, expected 0x{1:X4}", + calculatedQcrc, qSubChannelCrc); + + status = false; + } + + if((cdTextPack1[0] & 0x80) == 0x80) + { + ushort cdTextPack1Crc = BigEndianBitConverter.ToUInt16(cdTextPack1, 16); + byte[] cdTextPack1ForCrc = new byte[16]; + Array.Copy(cdTextPack1, 0, cdTextPack1ForCrc, 0, 16); + ushort calculatedCdtp1Crc = CRC16CCITTContext.Calculate(cdTextPack1ForCrc); + + if(cdTextPack1Crc != calculatedCdtp1Crc && + cdTextPack1Crc != 0) + { + AaruConsole.DebugWriteLine("CD checksums", "CD-Text Pack 1 CRC 0x{0:X4}, expected 0x{1:X4}", + cdTextPack1Crc, calculatedCdtp1Crc); + + status = false; + } + } + + if((cdTextPack2[0] & 0x80) == 0x80) + { + ushort cdTextPack2Crc = BigEndianBitConverter.ToUInt16(cdTextPack2, 16); + byte[] cdTextPack2ForCrc = new byte[16]; + Array.Copy(cdTextPack2, 0, cdTextPack2ForCrc, 0, 16); + ushort calculatedCdtp2Crc = CRC16CCITTContext.Calculate(cdTextPack2ForCrc); + + AaruConsole.DebugWriteLine("CD checksums", "Cyclic CDTP2 0x{0:X4}, Calc CDTP2 0x{1:X4}", cdTextPack2Crc, + calculatedCdtp2Crc); + + if(cdTextPack2Crc != calculatedCdtp2Crc && + cdTextPack2Crc != 0) + { + AaruConsole.DebugWriteLine("CD checksums", "CD-Text Pack 2 CRC 0x{0:X4}, expected 0x{1:X4}", + cdTextPack2Crc, calculatedCdtp2Crc); + + status = false; + } + } + + if((cdTextPack3[0] & 0x80) == 0x80) + { + ushort cdTextPack3Crc = BigEndianBitConverter.ToUInt16(cdTextPack3, 16); + byte[] cdTextPack3ForCrc = new byte[16]; + Array.Copy(cdTextPack3, 0, cdTextPack3ForCrc, 0, 16); + ushort calculatedCdtp3Crc = CRC16CCITTContext.Calculate(cdTextPack3ForCrc); + + AaruConsole.DebugWriteLine("CD checksums", "Cyclic CDTP3 0x{0:X4}, Calc CDTP3 0x{1:X4}", cdTextPack3Crc, + calculatedCdtp3Crc); + + if(cdTextPack3Crc != calculatedCdtp3Crc && + cdTextPack3Crc != 0) + { + AaruConsole.DebugWriteLine("CD checksums", "CD-Text Pack 3 CRC 0x{0:X4}, expected 0x{1:X4}", + cdTextPack3Crc, calculatedCdtp3Crc); + + status = false; + } + } + + if((cdTextPack4[0] & 0x80) != 0x80) + return status; + + ushort cdTextPack4Crc = BigEndianBitConverter.ToUInt16(cdTextPack4, 16); + byte[] cdTextPack4ForCrc = new byte[16]; + Array.Copy(cdTextPack4, 0, cdTextPack4ForCrc, 0, 16); + ushort calculatedCdtp4Crc = CRC16CCITTContext.Calculate(cdTextPack4ForCrc); + + AaruConsole.DebugWriteLine("CD checksums", "Cyclic CDTP4 0x{0:X4}, Calc CDTP4 0x{1:X4}", cdTextPack4Crc, + calculatedCdtp4Crc); + + if(cdTextPack4Crc == calculatedCdtp4Crc || + cdTextPack4Crc == 0) + return status; + + AaruConsole.DebugWriteLine("CD checksums", "CD-Text Pack 4 CRC 0x{0:X4}, expected 0x{1:X4}", cdTextPack4Crc, + calculatedCdtp4Crc); + + return false; + } + } +} \ No newline at end of file diff --git a/Aaru.Checksums/CRC16CCITTContext.cs b/Aaru.Checksums/CRC16CCITTContext.cs new file mode 100644 index 000000000..838d8665b --- /dev/null +++ b/Aaru.Checksums/CRC16CCITTContext.cs @@ -0,0 +1,103 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CRC16CCITTContext.cs +// Author(s) : Natalia Portillo +// +// Component : Checksums. +// +// --[ Description ] ---------------------------------------------------------- +// +// Implements a CRC16 algorithm with the CCITT polynomial. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.Checksums +{ + /// + /// Implements the CRC16 algorithm with CCITT polynomial and seed + public sealed class CRC16CCITTContext : Crc16Context + { + /// CCITT CRC16 polynomial + public const ushort CRC16_CCITT_POLY = 0x8408; + /// CCITT CRC16 seed + public const ushort CRC16_CCITT_SEED = 0x0000; + static readonly ushort[] _ccittCrc16Table = + { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, + 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, + 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, + 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, + 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, + 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, + 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, + 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, + 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, + 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, + 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, + 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, + 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, + 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, + 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, + 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, + 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, + 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 + }; + + /// Initializes an instance of the CRC16 with CCITT polynomial and seed. + /// + public CRC16CCITTContext() : base(CRC16_CCITT_POLY, CRC16_CCITT_SEED, _ccittCrc16Table, true) {} + + /// Gets the hash of a file + /// File path. + public static byte[] File(string filename) + { + File(filename, out byte[] hash); + + return hash; + } + + /// Gets the hash of a file in hexadecimal and as a byte array. + /// File path. + /// Byte array of the hash value. + public static string File(string filename, out byte[] hash) => + File(filename, out hash, CRC16_CCITT_POLY, CRC16_CCITT_SEED, _ccittCrc16Table, true); + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Length of the data buffer to hash. + /// Byte array of the hash value. + public static string Data(byte[] data, uint len, out byte[] hash) => + Data(data, len, out hash, CRC16_CCITT_POLY, CRC16_CCITT_SEED, _ccittCrc16Table, true); + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Byte array of the hash value. + public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); + + /// Calculates the CCITT CRC16 of the specified buffer with the specified parameters + /// Buffer + public static ushort Calculate(byte[] buffer) => + Calculate(buffer, CRC16_CCITT_POLY, CRC16_CCITT_SEED, _ccittCrc16Table, true); + } +} \ No newline at end of file diff --git a/Aaru.Checksums/CRC16Context.cs b/Aaru.Checksums/CRC16Context.cs new file mode 100644 index 000000000..7a97984e7 --- /dev/null +++ b/Aaru.Checksums/CRC16Context.cs @@ -0,0 +1,243 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CRC16Context.cs +// Author(s) : Natalia Portillo +// +// Component : Checksums. +// +// --[ Description ] ---------------------------------------------------------- +// +// Implements a CRC16 algorithm. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.IO; +using System.Linq; +using System.Text; +using Aaru.CommonTypes.Interfaces; +using Aaru.Helpers; + +namespace Aaru.Checksums +{ + /// + /// Implements a CRC16 algorithm + public class Crc16Context : IChecksum + { + readonly ushort _finalSeed; + readonly bool _inverse; + readonly ushort[] _table; + ushort _hashInt; + + /// Initializes the CRC16 table with a custom polynomial and seed + public Crc16Context(ushort polynomial, ushort seed, ushort[] table, bool inverse) + { + _hashInt = seed; + _finalSeed = seed; + _inverse = inverse; + + _table = table ?? GenerateTable(polynomial, inverse); + } + + /// + /// Updates the hash with data. + /// Data buffer. + /// Length of buffer to hash. + public void Update(byte[] data, uint len) + { + for(int i = 0; i < len; i++) + { + if(_inverse) + _hashInt = (ushort)(_table[(_hashInt >> 8) ^ data[i]] ^ (_hashInt << 8)); + else + _hashInt = (ushort)((_hashInt >> 8) ^ _table[data[i] ^ (_hashInt & 0xFF)]); + } + } + + /// + /// Updates the hash with data. + /// Data buffer. + public void Update(byte[] data) => Update(data, (uint)data.Length); + + /// + /// Returns a byte array of the hash value. + public byte[] Final() => BigEndianBitConverter.GetBytes((ushort)(_hashInt ^ _finalSeed)); + + /// + /// Returns a hexadecimal representation of the hash value. + public string End() + { + var crc16Output = new StringBuilder(); + + ushort final = (ushort)(_hashInt ^ _finalSeed); + + if(_inverse) + final = (ushort)~final; + + byte[] finalBytes = BigEndianBitConverter.GetBytes(final); + + for(int i = 0; i < finalBytes.Length; i++) + crc16Output.Append(finalBytes[i].ToString("x2")); + + return crc16Output.ToString(); + } + + static ushort[] GenerateTable(ushort polynomial, bool inverseTable) + { + ushort[] table = new ushort[256]; + + if(!inverseTable) + for(uint i = 0; i < 256; i++) + { + uint entry = i; + + for(int j = 0; j < 8; j++) + if((entry & 1) == 1) + entry = (entry >> 1) ^ polynomial; + else + entry >>= 1; + + table[i] = (ushort)entry; + } + else + { + for(uint i = 0; i < 256; i++) + { + uint entry = i << 8; + + for(uint j = 0; j < 8; j++) + { + if((entry & 0x8000) > 0) + entry = (entry << 1) ^ polynomial; + else + entry <<= 1; + + table[i] = (ushort)entry; + } + } + } + + return table; + } + + /// Gets the hash of a file in hexadecimal and as a byte array. + /// File path. + /// Byte array of the hash value. + /// CRC polynomial + /// CRC seed + /// CRC lookup table + /// Is CRC inverted? + public static string File(string filename, out byte[] hash, ushort polynomial, ushort seed, ushort[] table, + bool inverse) + { + var fileStream = new FileStream(filename, FileMode.Open); + + ushort localHashInt = seed; + + ushort[] localTable = table ?? GenerateTable(polynomial, inverse); + + for(int i = 0; i < fileStream.Length; i++) + if(inverse) + localHashInt = + (ushort)(localTable[(localHashInt >> 8) ^ fileStream.ReadByte()] ^ (localHashInt << 8)); + else + localHashInt = + (ushort)((localHashInt >> 8) ^ localTable[fileStream.ReadByte() ^ (localHashInt & 0xff)]); + + localHashInt ^= seed; + + if(inverse) + localHashInt = (ushort)~localHashInt; + + hash = BigEndianBitConverter.GetBytes(localHashInt); + + var crc16Output = new StringBuilder(); + + foreach(byte h in hash) + crc16Output.Append(h.ToString("x2")); + + fileStream.Close(); + + return crc16Output.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Length of the data buffer to hash. + /// Byte array of the hash value. + /// CRC polynomial + /// CRC seed + /// CRC lookup table + /// Is CRC inverted? + public static string Data(byte[] data, uint len, out byte[] hash, ushort polynomial, ushort seed, + ushort[] table, bool inverse) + { + ushort localHashInt = seed; + + ushort[] localTable = table ?? GenerateTable(polynomial, inverse); + + for(int i = 0; i < len; i++) + if(inverse) + localHashInt = (ushort)(localTable[(localHashInt >> 8) ^ data[i]] ^ (localHashInt << 8)); + else + localHashInt = (ushort)((localHashInt >> 8) ^ localTable[data[i] ^ (localHashInt & 0xff)]); + + localHashInt ^= seed; + + if(inverse) + localHashInt = (ushort)~localHashInt; + + hash = BigEndianBitConverter.GetBytes(localHashInt); + + var crc16Output = new StringBuilder(); + + foreach(byte h in hash) + crc16Output.Append(h.ToString("x2")); + + return crc16Output.ToString(); + } + + /// Calculates the CRC16 of the specified buffer with the specified parameters + /// Buffer + /// Polynomial + /// Seed + /// Pre-generated lookup table + /// Inverse CRC + /// CRC16 + public static ushort Calculate(byte[] buffer, ushort polynomial, ushort seed, ushort[] table, bool inverse) + { + ushort[] localTable = table ?? GenerateTable(polynomial, inverse); + + ushort crc16 = + buffer.Aggregate(0, + (current, b) => + inverse ? (ushort)(localTable[(current >> 8) ^ b] ^ (current << 8)) + : (ushort)((current >> 8) ^ localTable[b ^ (current & 0xff)])); + + crc16 ^= seed; + + if(inverse) + crc16 = (ushort)~crc16; + + return crc16; + } + } +} \ No newline at end of file diff --git a/Aaru.Checksums/CRC16IBMContext.cs b/Aaru.Checksums/CRC16IBMContext.cs new file mode 100644 index 000000000..00dd681d8 --- /dev/null +++ b/Aaru.Checksums/CRC16IBMContext.cs @@ -0,0 +1,102 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CRC16IBMContext.cs +// Author(s) : Natalia Portillo +// +// Component : Checksums. +// +// --[ Description ] ---------------------------------------------------------- +// +// Implements a CRC16 algorithm with the IBM polynomial. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.Checksums +{ + /// + /// Implements the CRC16 algorithm with IBM polynomial and seed + public sealed class CRC16IBMContext : Crc16Context + { + const ushort CRC16_IBM_POLY = 0xA001; + const ushort CRC16_IBM_SEED = 0x0000; + + static readonly ushort[] _ibmCrc16Table = + { + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, + 0xC5C1, 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, + 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, + 0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, + 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, + 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, + 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, + 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, + 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, + 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, + 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, + 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0xBE01, + 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, + 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, + 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, + 0x59C0, 0x5880, 0x9841, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, + 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, + 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 + }; + + /// Initializes an instance of the CRC16 with IBM polynomial and seed. + /// + public CRC16IBMContext() : base(CRC16_IBM_POLY, CRC16_IBM_SEED, _ibmCrc16Table, false) {} + + /// Gets the hash of a file + /// File path. + public static byte[] File(string filename) + { + File(filename, out byte[] hash); + + return hash; + } + + /// Gets the hash of a file in hexadecimal and as a byte array. + /// File path. + /// Byte array of the hash value. + public static string File(string filename, out byte[] hash) => + File(filename, out hash, CRC16_IBM_POLY, CRC16_IBM_SEED, _ibmCrc16Table, false); + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Length of the data buffer to hash. + /// Byte array of the hash value. + public static string Data(byte[] data, uint len, out byte[] hash) => + Data(data, len, out hash, CRC16_IBM_POLY, CRC16_IBM_SEED, _ibmCrc16Table, false); + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Byte array of the hash value. + public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); + + /// Calculates the IBM CRC16 of the specified buffer with the specified parameters + /// Buffer + public static ushort Calculate(byte[] buffer) => + Calculate(buffer, CRC16_IBM_POLY, CRC16_IBM_SEED, _ibmCrc16Table, false); + } +} \ No newline at end of file diff --git a/Aaru.Checksums/CRC32Context.cs b/Aaru.Checksums/CRC32Context.cs new file mode 100644 index 000000000..be917e26a --- /dev/null +++ b/Aaru.Checksums/CRC32Context.cs @@ -0,0 +1,234 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CRC32Context.cs +// Author(s) : Natalia Portillo +// +// Component : Checksums. +// +// --[ Description ] ---------------------------------------------------------- +// +// Implements a CRC32 algorithm. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.IO; +using System.Text; +using Aaru.CommonTypes.Interfaces; +using Aaru.Helpers; + +namespace Aaru.Checksums +{ + /// + /// Implements a CRC32 algorithm + public sealed class Crc32Context : IChecksum + { + const uint CRC32_ISO_POLY = 0xEDB88320; + const uint CRC32_ISO_SEED = 0xFFFFFFFF; + + readonly uint _finalSeed; + readonly uint[] _table; + uint _hashInt; + + /// Initializes the CRC32 table and seed as CRC32-ISO + public Crc32Context() + { + _hashInt = CRC32_ISO_SEED; + _finalSeed = CRC32_ISO_SEED; + + _table = new uint[256]; + + for(int i = 0; i < 256; i++) + { + uint entry = (uint)i; + + for(int j = 0; j < 8; j++) + if((entry & 1) == 1) + entry = (entry >> 1) ^ CRC32_ISO_POLY; + else + entry >>= 1; + + _table[i] = entry; + } + } + + /// Initializes the CRC32 table with a custom polynomial and seed + public Crc32Context(uint polynomial, uint seed) + { + _hashInt = seed; + _finalSeed = seed; + + _table = new uint[256]; + + for(int i = 0; i < 256; i++) + { + uint entry = (uint)i; + + for(int j = 0; j < 8; j++) + if((entry & 1) == 1) + entry = (entry >> 1) ^ polynomial; + else + entry >>= 1; + + _table[i] = entry; + } + } + + /// + /// Updates the hash with data. + /// Data buffer. + /// Length of buffer to hash. + public void Update(byte[] data, uint len) + { + for(int i = 0; i < len; i++) + _hashInt = (_hashInt >> 8) ^ _table[data[i] ^ (_hashInt & 0xff)]; + } + + /// + /// Updates the hash with data. + /// Data buffer. + public void Update(byte[] data) => Update(data, (uint)data.Length); + + /// + /// Returns a byte array of the hash value. + public byte[] Final() => BigEndianBitConverter.GetBytes(_hashInt ^ _finalSeed); + + /// + /// Returns a hexadecimal representation of the hash value. + public string End() + { + var crc32Output = new StringBuilder(); + + for(int i = 0; i < BigEndianBitConverter.GetBytes(_hashInt ^ _finalSeed).Length; i++) + crc32Output.Append(BigEndianBitConverter.GetBytes(_hashInt ^ _finalSeed)[i].ToString("x2")); + + return crc32Output.ToString(); + } + + /// Gets the hash of a file + /// File path. + public static byte[] File(string filename) + { + File(filename, out byte[] hash); + + return hash; + } + + /// Gets the hash of a file in hexadecimal and as a byte array. + /// File path. + /// Byte array of the hash value. + public static string File(string filename, out byte[] hash) => + File(filename, out hash, CRC32_ISO_POLY, CRC32_ISO_SEED); + + /// Gets the hash of a file in hexadecimal and as a byte array. + /// File path. + /// Byte array of the hash value. + /// CRC polynomial + /// CRC seed + public static string File(string filename, out byte[] hash, uint polynomial, uint seed) + { + var fileStream = new FileStream(filename, FileMode.Open); + + uint localHashInt = seed; + + uint[] localTable = new uint[256]; + + for(int i = 0; i < 256; i++) + { + uint entry = (uint)i; + + for(int j = 0; j < 8; j++) + if((entry & 1) == 1) + entry = (entry >> 1) ^ polynomial; + else + entry >>= 1; + + localTable[i] = entry; + } + + for(int i = 0; i < fileStream.Length; i++) + localHashInt = (localHashInt >> 8) ^ localTable[fileStream.ReadByte() ^ (localHashInt & 0xff)]; + + localHashInt ^= seed; + hash = BigEndianBitConverter.GetBytes(localHashInt); + + var crc32Output = new StringBuilder(); + + foreach(byte h in hash) + crc32Output.Append(h.ToString("x2")); + + fileStream.Close(); + + return crc32Output.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Length of the data buffer to hash. + /// Byte array of the hash value. + public static string Data(byte[] data, uint len, out byte[] hash) => + Data(data, len, out hash, CRC32_ISO_POLY, CRC32_ISO_SEED); + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Length of the data buffer to hash. + /// Byte array of the hash value. + /// CRC polynomial + /// CRC seed + public static string Data(byte[] data, uint len, out byte[] hash, uint polynomial, uint seed) + { + uint localHashInt = seed; + + uint[] localTable = new uint[256]; + + for(int i = 0; i < 256; i++) + { + uint entry = (uint)i; + + for(int j = 0; j < 8; j++) + if((entry & 1) == 1) + entry = (entry >> 1) ^ polynomial; + else + entry >>= 1; + + localTable[i] = entry; + } + + for(int i = 0; i < len; i++) + localHashInt = (localHashInt >> 8) ^ localTable[data[i] ^ (localHashInt & 0xff)]; + + localHashInt ^= seed; + hash = BigEndianBitConverter.GetBytes(localHashInt); + + var crc32Output = new StringBuilder(); + + foreach(byte h in hash) + crc32Output.Append(h.ToString("x2")); + + return crc32Output.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Byte array of the hash value. + public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); + } +} \ No newline at end of file diff --git a/Aaru.Checksums/CRC64Context.cs b/Aaru.Checksums/CRC64Context.cs new file mode 100644 index 000000000..8f1fae3aa --- /dev/null +++ b/Aaru.Checksums/CRC64Context.cs @@ -0,0 +1,240 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CRC64Context.cs +// Author(s) : Natalia Portillo +// +// Component : Checksums. +// +// --[ Description ] ---------------------------------------------------------- +// +// Implements a CRC64 algorithm. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.IO; +using System.Text; +using Aaru.CommonTypes.Interfaces; +using Aaru.Helpers; + +namespace Aaru.Checksums +{ + /// + /// Implements a CRC64 algorithm + public sealed class Crc64Context : IChecksum + { + /// ECMA CRC64 polynomial + public const ulong CRC64_ECMA_POLY = 0xC96C5795D7870F42; + /// ECMA CRC64 seed + public const ulong CRC64_ECMA_SEED = 0xFFFFFFFFFFFFFFFF; + + readonly ulong _finalSeed; + readonly ulong[] _table; + ulong _hashInt; + + /// Initializes the CRC64 table and seed as CRC64-ECMA + public Crc64Context() + { + _hashInt = CRC64_ECMA_SEED; + + _table = new ulong[256]; + + for(int i = 0; i < 256; i++) + { + ulong entry = (ulong)i; + + for(int j = 0; j < 8; j++) + if((entry & 1) == 1) + entry = (entry >> 1) ^ CRC64_ECMA_POLY; + else + entry >>= 1; + + _table[i] = entry; + } + + _finalSeed = CRC64_ECMA_SEED; + } + + /// Initializes the CRC16 table with a custom polynomial and seed + public Crc64Context(ulong polynomial, ulong seed) + { + _hashInt = seed; + + _table = new ulong[256]; + + for(int i = 0; i < 256; i++) + { + ulong entry = (ulong)i; + + for(int j = 0; j < 8; j++) + if((entry & 1) == 1) + entry = (entry >> 1) ^ polynomial; + else + entry >>= 1; + + _table[i] = entry; + } + + _finalSeed = seed; + } + + /// + /// Updates the hash with data. + /// Data buffer. + /// Length of buffer to hash. + public void Update(byte[] data, uint len) + { + for(int i = 0; i < len; i++) + _hashInt = (_hashInt >> 8) ^ _table[data[i] ^ (_hashInt & 0xff)]; + } + + /// + /// Updates the hash with data. + /// Data buffer. + public void Update(byte[] data) => Update(data, (uint)data.Length); + + /// + /// Returns a byte array of the hash value. + public byte[] Final() => BigEndianBitConverter.GetBytes(_hashInt ^= _finalSeed); + + /// + /// Returns a hexadecimal representation of the hash value. + public string End() + { + ulong crc = _hashInt ^ _finalSeed; + + var crc64Output = new StringBuilder(); + + for(int i = 0; i < BigEndianBitConverter.GetBytes(crc).Length; i++) + crc64Output.Append(BigEndianBitConverter.GetBytes(crc)[i].ToString("x2")); + + return crc64Output.ToString(); + } + + /// Gets the hash of a file + /// File path. + public static byte[] File(string filename) + { + File(filename, out byte[] localHash); + + return localHash; + } + + /// Gets the hash of a file in hexadecimal and as a byte array. + /// File path. + /// Byte array of the hash value. + public static string File(string filename, out byte[] hash) => + File(filename, out hash, CRC64_ECMA_POLY, CRC64_ECMA_SEED); + + /// Gets the hash of a file in hexadecimal and as a byte array. + /// File path. + /// Byte array of the hash value. + /// CRC polynomial + /// CRC seed + public static string File(string filename, out byte[] hash, ulong polynomial, ulong seed) + { + var fileStream = new FileStream(filename, FileMode.Open); + + ulong localHashInt = seed; + + ulong[] localTable = new ulong[256]; + + for(int i = 0; i < 256; i++) + { + ulong entry = (ulong)i; + + for(int j = 0; j < 8; j++) + if((entry & 1) == 1) + entry = (entry >> 1) ^ polynomial; + else + entry >>= 1; + + localTable[i] = entry; + } + + for(int i = 0; i < fileStream.Length; i++) + localHashInt = (localHashInt >> 8) ^ localTable[(ulong)fileStream.ReadByte() ^ (localHashInt & 0xffL)]; + + localHashInt ^= seed; + hash = BigEndianBitConverter.GetBytes(localHashInt); + + var crc64Output = new StringBuilder(); + + foreach(byte h in hash) + crc64Output.Append(h.ToString("x2")); + + fileStream.Close(); + + return crc64Output.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Length of the data buffer to hash. + /// Byte array of the hash value. + public static string Data(byte[] data, uint len, out byte[] hash) => + Data(data, len, out hash, CRC64_ECMA_POLY, CRC64_ECMA_SEED); + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Length of the data buffer to hash. + /// Byte array of the hash value. + /// CRC polynomial + /// CRC seed + public static string Data(byte[] data, uint len, out byte[] hash, ulong polynomial, ulong seed) + { + ulong localHashInt = seed; + + ulong[] localTable = new ulong[256]; + + for(int i = 0; i < 256; i++) + { + ulong entry = (ulong)i; + + for(int j = 0; j < 8; j++) + if((entry & 1) == 1) + entry = (entry >> 1) ^ polynomial; + else + entry >>= 1; + + localTable[i] = entry; + } + + for(int i = 0; i < len; i++) + localHashInt = (localHashInt >> 8) ^ localTable[data[i] ^ (localHashInt & 0xff)]; + + localHashInt ^= seed; + hash = BigEndianBitConverter.GetBytes(localHashInt); + + var crc64Output = new StringBuilder(); + + foreach(byte h in hash) + crc64Output.Append(h.ToString("x2")); + + return crc64Output.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Byte array of the hash value. + public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); + } +} \ No newline at end of file diff --git a/Aaru.Checksums/FletcherContext.cs b/Aaru.Checksums/FletcherContext.cs new file mode 100644 index 000000000..1b5d2fc0d --- /dev/null +++ b/Aaru.Checksums/FletcherContext.cs @@ -0,0 +1,292 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : FletcherContext.cs +// Author(s) : Natalia Portillo +// +// Component : Checksums. +// +// --[ Description ] ---------------------------------------------------------- +// +// Implements Fletcher-32 and Fletcher-16 algorithms. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +// Disabled because the speed is abnormally slow + +using System.IO; +using System.Text; +using Aaru.CommonTypes.Interfaces; +using Aaru.Helpers; + +namespace Aaru.Checksums +{ + /// Implements the Fletcher-32 algorithm + public sealed class Fletcher32Context : IChecksum + { + const ushort FLETCHER_MODULE = 0xFFFF; + ushort _sum1, _sum2; + + /// Initializes the Fletcher-32 sums + public Fletcher32Context() + { + _sum1 = 0xFFFF; + _sum2 = 0xFFFF; + } + + /// + /// Updates the hash with data. + /// Data buffer. + /// Length of buffer to hash. + public void Update(byte[] data, uint len) + { + for(int i = 0; i < len; i++) + { + _sum1 = (ushort)((_sum1 + data[i]) % FLETCHER_MODULE); + _sum2 = (ushort)((_sum2 + _sum1) % FLETCHER_MODULE); + } + } + + /// + /// Updates the hash with data. + /// Data buffer. + public void Update(byte[] data) => Update(data, (uint)data.Length); + + /// + /// Returns a byte array of the hash value. + public byte[] Final() + { + uint finalSum = (uint)((_sum2 << 16) | _sum1); + + return BigEndianBitConverter.GetBytes(finalSum); + } + + /// + /// Returns a hexadecimal representation of the hash value. + public string End() + { + uint finalSum = (uint)((_sum2 << 16) | _sum1); + var fletcherOutput = new StringBuilder(); + + for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++) + fletcherOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2")); + + return fletcherOutput.ToString(); + } + + /// Gets the hash of a file + /// File path. + public static byte[] File(string filename) + { + File(filename, out byte[] hash); + + return hash; + } + + /// Gets the hash of a file in hexadecimal and as a byte array. + /// File path. + /// Byte array of the hash value. + public static string File(string filename, out byte[] hash) + { + var fileStream = new FileStream(filename, FileMode.Open); + + ushort localSum1 = 0xFFFF; + ushort localSum2 = 0xFFFF; + + for(int i = 0; i < fileStream.Length; i++) + { + localSum1 = (ushort)((localSum1 + fileStream.ReadByte()) % FLETCHER_MODULE); + localSum2 = (ushort)((localSum2 + localSum1) % FLETCHER_MODULE); + } + + uint finalSum = (uint)((localSum2 << 16) | localSum1); + + hash = BigEndianBitConverter.GetBytes(finalSum); + + var fletcherOutput = new StringBuilder(); + + foreach(byte h in hash) + fletcherOutput.Append(h.ToString("x2")); + + fileStream.Close(); + + return fletcherOutput.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Length of the data buffer to hash. + /// Byte array of the hash value. + public static string Data(byte[] data, uint len, out byte[] hash) + { + ushort localSum1 = 0xFFFF; + ushort localSum2 = 0xFFFF; + + for(int i = 0; i < len; i++) + { + localSum1 = (ushort)((localSum1 + data[i]) % FLETCHER_MODULE); + localSum2 = (ushort)((localSum2 + localSum1) % FLETCHER_MODULE); + } + + uint finalSum = (uint)((localSum2 << 16) | localSum1); + + hash = BigEndianBitConverter.GetBytes(finalSum); + + var adlerOutput = new StringBuilder(); + + foreach(byte h in hash) + adlerOutput.Append(h.ToString("x2")); + + return adlerOutput.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Byte array of the hash value. + public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); + } + + /// + /// Implements the Fletcher-16 algorithm + public sealed class Fletcher16Context : IChecksum + { + const byte FLETCHER_MODULE = 0xFF; + byte _sum1, _sum2; + + /// Initializes the Fletcher-16 sums + public Fletcher16Context() + { + _sum1 = 0xFF; + _sum2 = 0xFF; + } + + /// + /// Updates the hash with data. + /// Data buffer. + /// Length of buffer to hash. + public void Update(byte[] data, uint len) + { + for(int i = 0; i < len; i++) + { + _sum1 = (byte)((_sum1 + data[i]) % FLETCHER_MODULE); + _sum2 = (byte)((_sum2 + _sum1) % FLETCHER_MODULE); + } + } + + /// + /// Updates the hash with data. + /// Data buffer. + public void Update(byte[] data) => Update(data, (uint)data.Length); + + /// + /// Returns a byte array of the hash value. + public byte[] Final() + { + ushort finalSum = (ushort)((_sum2 << 8) | _sum1); + + return BigEndianBitConverter.GetBytes(finalSum); + } + + /// + /// Returns a hexadecimal representation of the hash value. + public string End() + { + ushort finalSum = (ushort)((_sum2 << 8) | _sum1); + var fletcherOutput = new StringBuilder(); + + for(int i = 0; i < BigEndianBitConverter.GetBytes(finalSum).Length; i++) + fletcherOutput.Append(BigEndianBitConverter.GetBytes(finalSum)[i].ToString("x2")); + + return fletcherOutput.ToString(); + } + + /// Gets the hash of a file + /// File path. + public static byte[] File(string filename) + { + File(filename, out byte[] hash); + + return hash; + } + + /// Gets the hash of a file in hexadecimal and as a byte array. + /// File path. + /// Byte array of the hash value. + public static string File(string filename, out byte[] hash) + { + var fileStream = new FileStream(filename, FileMode.Open); + + byte localSum1 = 0xFF; + byte localSum2 = 0xFF; + + for(int i = 0; i < fileStream.Length; i++) + { + localSum1 = (byte)((localSum1 + fileStream.ReadByte()) % FLETCHER_MODULE); + localSum2 = (byte)((localSum2 + localSum1) % FLETCHER_MODULE); + } + + ushort finalSum = (ushort)((localSum2 << 8) | localSum1); + + hash = BigEndianBitConverter.GetBytes(finalSum); + + var fletcherOutput = new StringBuilder(); + + foreach(byte h in hash) + fletcherOutput.Append(h.ToString("x2")); + + fileStream.Close(); + + return fletcherOutput.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Length of the data buffer to hash. + /// Byte array of the hash value. + public static string Data(byte[] data, uint len, out byte[] hash) + { + byte localSum1 = 0xFF; + byte localSum2 = 0xFF; + + for(int i = 0; i < len; i++) + { + localSum1 = (byte)((localSum1 + data[i]) % FLETCHER_MODULE); + localSum2 = (byte)((localSum2 + localSum1) % FLETCHER_MODULE); + } + + ushort finalSum = (ushort)((localSum2 << 8) | localSum1); + + hash = BigEndianBitConverter.GetBytes(finalSum); + + var adlerOutput = new StringBuilder(); + + foreach(byte h in hash) + adlerOutput.Append(h.ToString("x2")); + + return adlerOutput.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Byte array of the hash value. + public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); + } +} \ No newline at end of file diff --git a/Aaru.Checksums/MD5Context.cs b/Aaru.Checksums/MD5Context.cs new file mode 100644 index 000000000..6f5b5d5d7 --- /dev/null +++ b/Aaru.Checksums/MD5Context.cs @@ -0,0 +1,133 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : MD5Context.cs +// Author(s) : Natalia Portillo +// +// Component : Checksums. +// +// --[ Description ] ---------------------------------------------------------- +// +// Wraps up .NET MD5 implementation to a Init(), Update(), Final() context. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using Aaru.CommonTypes.Interfaces; + +namespace Aaru.Checksums +{ + /// Wraps up .NET MD5 implementation to a Init(), Update(), Final() context. + public sealed class Md5Context : IChecksum + { + readonly MD5 _provider; + + /// Initializes the MD5 hash provider + public Md5Context() => _provider = MD5.Create(); + + /// + /// Updates the hash with data. + /// Data buffer. + /// Length of buffer to hash. + public void Update(byte[] data, uint len) => _provider.TransformBlock(data, 0, (int)len, data, 0); + + /// + /// Updates the hash with data. + /// Data buffer. + public void Update(byte[] data) => Update(data, (uint)data.Length); + + /// + /// Returns a byte array of the hash value. + public byte[] Final() + { + _provider.TransformFinalBlock(Array.Empty(), 0, 0); + + return _provider.Hash; + } + + /// + /// Returns a hexadecimal representation of the hash value. + public string End() + { + _provider.TransformFinalBlock(Array.Empty(), 0, 0); + var md5Output = new StringBuilder(); + + foreach(byte h in _provider.Hash) + md5Output.Append(h.ToString("x2")); + + return md5Output.ToString(); + } + + /// Gets the hash of a file + /// File path. + public static byte[] File(string filename) + { + var localMd5Provider = MD5.Create(); + var fileStream = new FileStream(filename, FileMode.Open); + byte[] result = localMd5Provider.ComputeHash(fileStream); + fileStream.Close(); + + return result; + } + + /// Gets the hash of a file in hexadecimal and as a byte array. + /// File path. + /// Byte array of the hash value. + public static string File(string filename, out byte[] hash) + { + var localMd5Provider = MD5.Create(); + var fileStream = new FileStream(filename, FileMode.Open); + hash = localMd5Provider.ComputeHash(fileStream); + var md5Output = new StringBuilder(); + + foreach(byte h in hash) + md5Output.Append(h.ToString("x2")); + + fileStream.Close(); + + return md5Output.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Length of the data buffer to hash. + /// Byte array of the hash value. + public static string Data(byte[] data, uint len, out byte[] hash) + { + var localMd5Provider = MD5.Create(); + hash = localMd5Provider.ComputeHash(data, 0, (int)len); + var md5Output = new StringBuilder(); + + foreach(byte h in hash) + md5Output.Append(h.ToString("x2")); + + return md5Output.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Byte array of the hash value. + public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); + } +} \ No newline at end of file diff --git a/Aaru.Checksums/ReedSolomon.cs b/Aaru.Checksums/ReedSolomon.cs new file mode 100644 index 000000000..96445414b --- /dev/null +++ b/Aaru.Checksums/ReedSolomon.cs @@ -0,0 +1,730 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ReedSolomon.cs +// Author(s) : Natalia Portillo +// +// Component : Checksums. +// +// --[ Description ] ---------------------------------------------------------- +// +// Calculates a Reed-Solomon. +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// Copyright (C) 1996 Phil Karn +// Copyright (C) 1995 Robert Morelos-Zaragoza +// Copyright (C) 1995 Hari Thirumoorthy +// ****************************************************************************/ + +/* + * Reed-Solomon coding and decoding + * Phil Karn (karn at ka9q.ampr.org) September 1996 + * + * This file is derived from the program "new_rs_erasures.c" by Robert + * Morelos-Zaragoza (robert at spectra.eng.hawaii.edu) and Hari Thirumoorthy + * (harit at spectra.eng.hawaii.edu), Aug 1995 + * + * I've made changes to improve performance, clean up the code and make it + * easier to follow. Data is now passed to the encoding and decoding functions + * through arguments rather than in global arrays. The decode function returns + * the number of corrected symbols, or -1 if the word is uncorrectable. + * + * This code supports a symbol size from 2 bits up to 16 bits, + * implying a block size of 3 2-bit symbols (6 bits) up to 65535 + * 16-bit symbols (1,048,560 bits). The code parameters are set in rs.h. + * + * Note that if symbols larger than 8 bits are used, the type of each + * data array element switches from unsigned char to unsigned int. The + * caller must ensure that elements larger than the symbol range are + * not passed to the encoder or decoder. + * + */ + +using System; +using Aaru.Console; + +namespace Aaru.Checksums +{ + /// Implements the Reed-Solomon algorithm + public class ReedSolomon + { + /// Alpha exponent for the first root of the generator polynomial + const int B0 = 1; + /// No legal value in index form represents zero, so we need a special value for this purpose + int _a0; + /// index->polynomial form conversion table + int[] _alphaTo; + /// Generator polynomial g(x) Degree of g(x) = 2*TT has roots @**B0, @**(B0+1), ... ,@^(B0+2*TT-1) + int[] _gg; + /// Polynomial->index form conversion table + int[] _indexOf; + bool _initialized; + int _mm, _kk, _nn; + /// + /// Primitive polynomials - see Lin & Costello, Error Control Coding Appendix A, and Lee & Messerschmitt, Digital + /// Communication p. 453. + /// + int[] _pp; + + /// Initializes the Reed-Solomon with RS(n,k) with GF(2^m) + public void InitRs(int n, int k, int m) + { + switch(m) + { + case 2: + _pp = new[] + { + 1, 1, 1 + }; + + break; + case 3: + _pp = new[] + { + 1, 1, 0, 1 + }; + + break; + case 4: + _pp = new[] + { + 1, 1, 0, 0, 1 + }; + + break; + case 5: + _pp = new[] + { + 1, 0, 1, 0, 0, 1 + }; + + break; + case 6: + _pp = new[] + { + 1, 1, 0, 0, 0, 0, 1 + }; + + break; + case 7: + _pp = new[] + { + 1, 0, 0, 1, 0, 0, 0, 1 + }; + + break; + case 8: + _pp = new[] + { + 1, 0, 1, 1, 1, 0, 0, 0, 1 + }; + + break; + case 9: + _pp = new[] + { + 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 + }; + + break; + case 10: + _pp = new[] + { + 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 + }; + + break; + case 11: + _pp = new[] + { + 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 + }; + + break; + case 12: + _pp = new[] + { + 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1 + }; + + break; + case 13: + _pp = new[] + { + 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 + }; + + break; + case 14: + _pp = new[] + { + 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 + }; + + break; + case 15: + _pp = new[] + { + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 + }; + + break; + case 16: + _pp = new[] + { + 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1 + }; + + break; + default: throw new ArgumentOutOfRangeException(nameof(m), "m must be between 2 and 16 inclusive"); + } + + _mm = m; + _kk = k; + _nn = n; + _a0 = n; + _alphaTo = new int[n + 1]; + _indexOf = new int[n + 1]; + + _gg = new int[_nn - _kk + 1]; + + generate_gf(); + gen_poly(); + + _initialized = true; + } + + int Modnn(int x) + { + while(x >= _nn) + { + x -= _nn; + x = (x >> _mm) + (x & _nn); + } + + return x; + } + + static int Min(int a, int b) => a < b ? a : b; + + static void Clear(ref int[] a, int n) + { + int ci; + + for(ci = n - 1; ci >= 0; ci--) + a[ci] = 0; + } + + static void Copy(ref int[] a, ref int[] b, int n) + { + int ci; + + for(ci = n - 1; ci >= 0; ci--) + a[ci] = b[ci]; + } + + static void Copydown(ref int[] a, ref int[] b, int n) + { + int ci; + + for(ci = n - 1; ci >= 0; ci--) + a[ci] = b[ci]; + } + + /* generate GF(2**m) from the irreducible polynomial p(X) in p[0]..p[m] + lookup tables: index->polynomial form alpha_to[] contains j=alpha**i; + polynomial form -> index form index_of[j=alpha**i] = i + alpha=2 is the primitive element of GF(2**m) + HARI's COMMENT: (4/13/94) alpha_to[] can be used as follows: + Let @ represent the primitive element commonly called "alpha" that + is the root of the primitive polynomial p(x). Then in GF(2^m), for any + 0 <= i <= 2^m-2, + @^i = a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1) + where the binary vector (a(0),a(1),a(2),...,a(m-1)) is the representation + of the integer "alpha_to[i]" with a(0) being the LSB and a(m-1) the MSB. Thus for + example the polynomial representation of @^5 would be given by the binary + representation of the integer "alpha_to[5]". + Similarily, index_of[] can be used as follows: + As above, let @ represent the primitive element of GF(2^m) that is + the root of the primitive polynomial p(x). In order to find the power + of @ (alpha) that has the polynomial representation + a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1) + we consider the integer "i" whose binary representation with a(0) being LSB + and a(m-1) MSB is (a(0),a(1),...,a(m-1)) and locate the entry + "index_of[i]". Now, @^index_of[i] is that element whose polynomial + representation is (a(0),a(1),a(2),...,a(m-1)). + NOTE: + The element alpha_to[2^m-1] = 0 always signifying that the + representation of "@^infinity" = 0 is (0,0,0,...,0). + Similarily, the element index_of[0] = A0 always signifying + that the power of alpha which has the polynomial representation + (0,0,...,0) is "infinity". + + */ + void generate_gf() + { + int i; + + int mask = 1; + _alphaTo[_mm] = 0; + + for(i = 0; i < _mm; i++) + { + _alphaTo[i] = mask; + _indexOf[_alphaTo[i]] = i; + + /* If Pp[i] == 1 then, term @^i occurs in poly-repr of @^MM */ + if(_pp[i] != 0) + _alphaTo[_mm] ^= mask; /* Bit-wise EXOR operation */ + + mask <<= 1; /* single left-shift */ + } + + _indexOf[_alphaTo[_mm]] = _mm; + /* + * Have obtained poly-repr of @^MM. Poly-repr of @^(i+1) is given by + * poly-repr of @^i shifted left one-bit and accounting for any @^MM + * term that may occur when poly-repr of @^i is shifted. + */ + mask >>= 1; + + for(i = _mm + 1; i < _nn; i++) + { + if(_alphaTo[i - 1] >= mask) + _alphaTo[i] = _alphaTo[_mm] ^ ((_alphaTo[i - 1] ^ mask) << 1); + else + _alphaTo[i] = _alphaTo[i - 1] << 1; + + _indexOf[_alphaTo[i]] = i; + } + + _indexOf[0] = _a0; + _alphaTo[_nn] = 0; + } + + /* + * Obtain the generator polynomial of the TT-error correcting, length + * NN=(2**MM -1) Reed Solomon code from the product of (X+@**(B0+i)), i = 0, + * ... ,(2*TT-1) + * + * Examples: + * + * If B0 = 1, TT = 1. deg(g(x)) = 2*TT = 2. + * g(x) = (x+@) (x+@**2) + * + * If B0 = 0, TT = 2. deg(g(x)) = 2*TT = 4. + * g(x) = (x+1) (x+@) (x+@**2) (x+@**3) + */ + void gen_poly() + { + int i; + + _gg[0] = _alphaTo[B0]; + _gg[1] = 1; /* g(x) = (X+@**B0) initially */ + + for(i = 2; i <= _nn - _kk; i++) + { + _gg[i] = 1; + + /* + * Below multiply (Gg[0]+Gg[1]*x + ... +Gg[i]x^i) by + * (@**(B0+i-1) + x) + */ + for(int j = i - 1; j > 0; j--) + if(_gg[j] != 0) + _gg[j] = _gg[j - 1] ^ _alphaTo[Modnn(_indexOf[_gg[j]] + B0 + i - 1)]; + else + _gg[j] = _gg[j - 1]; + + /* Gg[0] can never be zero */ + _gg[0] = _alphaTo[Modnn(_indexOf[_gg[0]] + B0 + i - 1)]; + } + + /* convert Gg[] to index form for quicker encoding */ + for(i = 0; i <= _nn - _kk; i++) + _gg[i] = _indexOf[_gg[i]]; + } + + /* + * take the string of symbols in data[i], i=0..(k-1) and encode + * systematically to produce NN-KK parity symbols in bb[0]..bb[NN-KK-1] data[] + * is input and bb[] is output in polynomial form. Encoding is done by using + * a feedback shift register with appropriate connections specified by the + * elements of Gg[], which was generated above. Codeword is c(X) = + * data(X)*X**(NN-KK)+ b(X) + */ + /// Takes the symbols in data to output parity in bb. + /// Returns -1 if an illegal symbol is found. + /// Data symbols. + /// Outs parity symbols. + public int encode_rs(int[] data, out int[] bb) + { + if(!_initialized) + throw new UnauthorizedAccessException("Trying to calculate RS without initializing!"); + + int i; + bb = new int[_nn - _kk]; + + Clear(ref bb, _nn - _kk); + + for(i = _kk - 1; i >= 0; i--) + { + if(_mm != 8) + if(data[i] > _nn) + return -1; /* Illegal symbol */ + + int feedback = _indexOf[data[i] ^ bb[_nn - _kk - 1]]; + + if(feedback != _a0) + { + /* feedback term is non-zero */ + for(int j = _nn - _kk - 1; j > 0; j--) + if(_gg[j] != _a0) + bb[j] = bb[j - 1] ^ _alphaTo[Modnn(_gg[j] + feedback)]; + else + bb[j] = bb[j - 1]; + + bb[0] = _alphaTo[Modnn(_gg[0] + feedback)]; + } + else + { + /* feedback term is zero. encoder becomes a + * single-byte shifter */ + for(int j = _nn - _kk - 1; j > 0; j--) + bb[j] = bb[j - 1]; + + bb[0] = 0; + } + } + + return 0; + } + + /* + * Performs ERRORS+ERASURES decoding of RS codes. If decoding is successful, + * writes the codeword into data[] itself. Otherwise data[] is unaltered. + * + * Return number of symbols corrected, or -1 if codeword is illegal + * or uncorrectable. + * + * First "no_eras" erasures are declared by the calling program. Then, the + * maximum # of errors correctable is t_after_eras = floor((NN-KK-no_eras)/2). + * If the number of channel errors is not greater than "t_after_eras" the + * transmitted codeword will be recovered. Details of algorithm can be found + * in R. Blahut's "Theory ... of Error-Correcting Codes". + */ + /// Decodes the RS. If decoding is successful outputs corrected data symbols. + /// Returns corrected symbols, -1 if illegal or uncorrectable + /// Data symbols. + /// Position of erasures. + /// Number of erasures. + public int eras_dec_rs(ref int[] data, out int[] erasPos, int noEras) + { + if(!_initialized) + throw new UnauthorizedAccessException("Trying to calculate RS without initializing!"); + + erasPos = new int[_nn - _kk]; + int i, j; + int q, tmp; + int[] recd = new int[_nn]; + int[] lambda = new int[_nn - _kk + 1]; /* Err+Eras Locator poly */ + int[] s = new int[_nn - _kk + 1]; /* syndrome poly */ + int[] b = new int[_nn - _kk + 1]; + int[] t = new int[_nn - _kk + 1]; + int[] omega = new int[_nn - _kk + 1]; + int[] root = new int[_nn - _kk]; + int[] reg = new int[_nn - _kk + 1]; + int[] loc = new int[_nn - _kk]; + int count; + + /* data[] is in polynomial form, copy and convert to index form */ + for(i = _nn - 1; i >= 0; i--) + { + if(_mm != 8) + if(data[i] > _nn) + return -1; /* Illegal symbol */ + + recd[i] = _indexOf[data[i]]; + } + + /* first form the syndromes; i.e., evaluate recd(x) at roots of g(x) + * namely @**(B0+i), i = 0, ... ,(NN-KK-1) + */ + int synError = 0; + + for(i = 1; i <= _nn - _kk; i++) + { + tmp = 0; + + for(j = 0; j < _nn; j++) + if(recd[j] != _a0) /* recd[j] in index form */ + tmp ^= _alphaTo[Modnn(recd[j] + ((B0 + i - 1) * j))]; + + synError |= tmp; /* set flag if non-zero syndrome => + * error */ + + /* store syndrome in index form */ + s[i] = _indexOf[tmp]; + } + + if(synError == 0) + return 0; + + Clear(ref lambda, _nn - _kk); + lambda[0] = 1; + + if(noEras > 0) + { + /* Init lambda to be the erasure locator polynomial */ + lambda[1] = _alphaTo[erasPos[0]]; + + for(i = 1; i < noEras; i++) + { + int u = erasPos[i]; + + for(j = i + 1; j > 0; j--) + { + tmp = _indexOf[lambda[j - 1]]; + + if(tmp != _a0) + lambda[j] ^= _alphaTo[Modnn(u + tmp)]; + } + } + + #if DEBUG + /* find roots of the erasure location polynomial */ + for(i = 1; i <= noEras; i++) + reg[i] = _indexOf[lambda[i]]; + + count = 0; + + for(i = 1; i <= _nn; i++) + { + q = 1; + + for(j = 1; j <= noEras; j++) + if(reg[j] != _a0) + { + reg[j] = Modnn(reg[j] + j); + q ^= _alphaTo[reg[j]]; + } + + if(q != 0) + continue; + + /* store root and error location + * number indices + */ + root[count] = i; + loc[count] = _nn - i; + count++; + } + + if(count != noEras) + { + AaruConsole.DebugWriteLine("Reed Solomon", "\n lambda(x) is WRONG\n"); + + return -1; + } + + AaruConsole.DebugWriteLine("Reed Solomon", + "\n Erasure positions as determined by roots of Eras Loc Poly:\n"); + + for(i = 0; i < count; i++) + AaruConsole.DebugWriteLine("Reed Solomon", "{0} ", loc[i]); + + AaruConsole.DebugWriteLine("Reed Solomon", "\n"); + #endif + } + + for(i = 0; i < _nn - _kk + 1; i++) + b[i] = _indexOf[lambda[i]]; + + /* + * Begin Berlekamp-Massey algorithm to determine error+erasure + * locator polynomial + */ + int r = noEras; + int el = noEras; + + while(++r <= _nn - _kk) + { + /* r is the step number */ + /* Compute discrepancy at the r-th step in poly-form */ + int discrR = 0; + + for(i = 0; i < r; i++) + if(lambda[i] != 0 && + s[r - i] != _a0) + discrR ^= _alphaTo[Modnn(_indexOf[lambda[i]] + s[r - i])]; + + discrR = _indexOf[discrR]; /* Index form */ + + if(discrR == _a0) + { + /* 2 lines below: B(x) <-- x*B(x) */ + Copydown(ref b, ref b, _nn - _kk); + b[0] = _a0; + } + else + { + /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */ + t[0] = lambda[0]; + + for(i = 0; i < _nn - _kk; i++) + if(b[i] != _a0) + t[i + 1] = lambda[i + 1] ^ _alphaTo[Modnn(discrR + b[i])]; + else + t[i + 1] = lambda[i + 1]; + + if(2 * el <= r + noEras - 1) + { + el = r + noEras - el; + + /* + * 2 lines below: B(x) <-- inv(discr_r) * + * lambda(x) + */ + for(i = 0; i <= _nn - _kk; i++) + b[i] = lambda[i] == 0 ? _a0 : Modnn(_indexOf[lambda[i]] - discrR + _nn); + } + else + { + /* 2 lines below: B(x) <-- x*B(x) */ + Copydown(ref b, ref b, _nn - _kk); + b[0] = _a0; + } + + Copy(ref lambda, ref t, _nn - _kk + 1); + } + } + + /* Convert lambda to index form and compute deg(lambda(x)) */ + int degLambda = 0; + + for(i = 0; i < _nn - _kk + 1; i++) + { + lambda[i] = _indexOf[lambda[i]]; + + if(lambda[i] != _a0) + degLambda = i; + } + + /* + * Find roots of the error+erasure locator polynomial. By Chien + * Search + */ + int temp = reg[0]; + Copy(ref reg, ref lambda, _nn - _kk); + reg[0] = temp; + count = 0; /* Number of roots of lambda(x) */ + + for(i = 1; i <= _nn; i++) + { + q = 1; + + for(j = degLambda; j > 0; j--) + if(reg[j] != _a0) + { + reg[j] = Modnn(reg[j] + j); + q ^= _alphaTo[reg[j]]; + } + + if(q != 0) + continue; + + /* store root (index-form) and error location number */ + root[count] = i; + loc[count] = _nn - i; + count++; + } + + #if DEBUG + AaruConsole.DebugWriteLine("Reed Solomon", "\n Final error positions:\t"); + + for(i = 0; i < count; i++) + AaruConsole.DebugWriteLine("Reed Solomon", "{0} ", loc[i]); + + AaruConsole.DebugWriteLine("Reed Solomon", "\n"); + #endif + + if(degLambda != count) + return -1; + + /* + * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo + * x**(NN-KK)). in index form. Also find deg(omega). + */ + int degOmega = 0; + + for(i = 0; i < _nn - _kk; i++) + { + tmp = 0; + j = degLambda < i ? degLambda : i; + + for(; j >= 0; j--) + if(s[i + 1 - j] != _a0 && + lambda[j] != _a0) + tmp ^= _alphaTo[Modnn(s[i + 1 - j] + lambda[j])]; + + if(tmp != 0) + degOmega = i; + + omega[i] = _indexOf[tmp]; + } + + omega[_nn - _kk] = _a0; + + /* + * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = + * inv(X(l))**(B0-1) and den = lambda_pr(inv(X(l))) all in poly-form + */ + for(j = count - 1; j >= 0; j--) + { + int num1 = 0; + + for(i = degOmega; i >= 0; i--) + if(omega[i] != _a0) + num1 ^= _alphaTo[Modnn(omega[i] + (i * root[j]))]; + + int num2 = _alphaTo[Modnn((root[j] * (B0 - 1)) + _nn)]; + int den = 0; + + /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ + for(i = Min(degLambda, _nn - _kk - 1) & ~1; i >= 0; i -= 2) + if(lambda[i + 1] != _a0) + den ^= _alphaTo[Modnn(lambda[i + 1] + (i * root[j]))]; + + if(den == 0) + { + AaruConsole.DebugWriteLine("Reed Solomon", "\n ERROR: denominator = 0\n"); + + return -1; + } + + /* Apply error to data */ + if(num1 != 0) + data[loc[j]] ^= _alphaTo[Modnn(_indexOf[num1] + _indexOf[num2] + _nn - _indexOf[den])]; + } + + return count; + } + } +} \ No newline at end of file diff --git a/Aaru.Checksums/Register.cs b/Aaru.Checksums/Register.cs new file mode 100644 index 000000000..32a9cc2fe --- /dev/null +++ b/Aaru.Checksums/Register.cs @@ -0,0 +1,82 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Register.cs +// Author(s) : Natalia Portillo +// +// Component : Core algorithms. +// +// --[ Description ] ---------------------------------------------------------- +// +// Registers all plugins in this assembly. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Aaru.CommonTypes.Interfaces; + +namespace Aaru.Checksums +{ + /// + public sealed class Register : IPluginRegister + { + /// + public List GetAllChecksumPlugins() => Assembly.GetExecutingAssembly().GetTypes(). + Where(t => t.GetInterfaces().Contains(typeof(IChecksum))). + Where(t => t.IsClass).ToList(); + + /// + public List GetAllFilesystemPlugins() => null; + + /// + public List GetAllFilterPlugins() => null; + + /// + public List GetAllFloppyImagePlugins() => null; + + /// + public List GetAllMediaImagePlugins() => null; + + /// + public List GetAllPartitionPlugins() => null; + + /// + public List GetAllReadOnlyFilesystemPlugins() => null; + + /// + public List GetAllWritableFloppyImagePlugins() => null; + + /// + public List GetAllWritableImagePlugins() => null; + + /// + public List GetAllArchivePlugins() => null; + } +} \ No newline at end of file diff --git a/Aaru.Checksums/SHA1Context.cs b/Aaru.Checksums/SHA1Context.cs new file mode 100644 index 000000000..96053e899 --- /dev/null +++ b/Aaru.Checksums/SHA1Context.cs @@ -0,0 +1,134 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : SHA1Context.cs +// Author(s) : Natalia Portillo +// +// Component : Checksums. +// +// --[ Description ] ---------------------------------------------------------- +// +// Wraps up .NET SHA1 implementation to a Init(), Update(), Final() context. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using Aaru.CommonTypes.Interfaces; + +namespace Aaru.Checksums +{ + /// + /// Wraps up .NET SHA1 implementation to a Init(), Update(), Final() context. + public sealed class Sha1Context : IChecksum + { + readonly SHA1 _provider; + + /// Initializes the SHA1 hash provider + public Sha1Context() => _provider = SHA1.Create(); + + /// + /// Updates the hash with data. + /// Data buffer. + /// Length of buffer to hash. + public void Update(byte[] data, uint len) => _provider.TransformBlock(data, 0, (int)len, data, 0); + + /// + /// Updates the hash with data. + /// Data buffer. + public void Update(byte[] data) => Update(data, (uint)data.Length); + + /// + /// Returns a byte array of the hash value. + public byte[] Final() + { + _provider.TransformFinalBlock(Array.Empty(), 0, 0); + + return _provider.Hash; + } + + /// + /// Returns a hexadecimal representation of the hash value. + public string End() + { + _provider.TransformFinalBlock(Array.Empty(), 0, 0); + var sha1Output = new StringBuilder(); + + foreach(byte h in _provider.Hash) + sha1Output.Append(h.ToString("x2")); + + return sha1Output.ToString(); + } + + /// Gets the hash of a file + /// File path. + public static byte[] File(string filename) + { + var localSha1Provider = SHA1.Create(); + var fileStream = new FileStream(filename, FileMode.Open); + byte[] result = localSha1Provider.ComputeHash(fileStream); + fileStream.Close(); + + return result; + } + + /// Gets the hash of a file in hexadecimal and as a byte array. + /// File path. + /// Byte array of the hash value. + public static string File(string filename, out byte[] hash) + { + var localSha1Provider = SHA1.Create(); + var fileStream = new FileStream(filename, FileMode.Open); + hash = localSha1Provider.ComputeHash(fileStream); + var sha1Output = new StringBuilder(); + + foreach(byte h in hash) + sha1Output.Append(h.ToString("x2")); + + fileStream.Close(); + + return sha1Output.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Length of the data buffer to hash. + /// Byte array of the hash value. + public static string Data(byte[] data, uint len, out byte[] hash) + { + var localSha1Provider = SHA1.Create(); + hash = localSha1Provider.ComputeHash(data, 0, (int)len); + var sha1Output = new StringBuilder(); + + foreach(byte h in hash) + sha1Output.Append(h.ToString("x2")); + + return sha1Output.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Byte array of the hash value. + public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); + } +} \ No newline at end of file diff --git a/Aaru.Checksums/SHA256Context.cs b/Aaru.Checksums/SHA256Context.cs new file mode 100644 index 000000000..591737fe9 --- /dev/null +++ b/Aaru.Checksums/SHA256Context.cs @@ -0,0 +1,134 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : SHA256Context.cs +// Author(s) : Natalia Portillo +// +// Component : Checksums. +// +// --[ Description ] ---------------------------------------------------------- +// +// Wraps up .NET SHA256 implementation to a Init(), Update(), Final() context. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using Aaru.CommonTypes.Interfaces; + +namespace Aaru.Checksums +{ + /// + /// Wraps up .NET SHA256 implementation to a Init(), Update(), Final() context. + public sealed class Sha256Context : IChecksum + { + readonly SHA256 _provider; + + /// Initializes the SHA256 hash provider + public Sha256Context() => _provider = SHA256.Create(); + + /// + /// Updates the hash with data. + /// Data buffer. + /// Length of buffer to hash. + public void Update(byte[] data, uint len) => _provider.TransformBlock(data, 0, (int)len, data, 0); + + /// + /// Updates the hash with data. + /// Data buffer. + public void Update(byte[] data) => Update(data, (uint)data.Length); + + /// + /// Returns a byte array of the hash value. + public byte[] Final() + { + _provider.TransformFinalBlock(Array.Empty(), 0, 0); + + return _provider.Hash; + } + + /// + /// Returns a hexadecimal representation of the hash value. + public string End() + { + _provider.TransformFinalBlock(Array.Empty(), 0, 0); + var sha256Output = new StringBuilder(); + + foreach(byte h in _provider.Hash) + sha256Output.Append(h.ToString("x2")); + + return sha256Output.ToString(); + } + + /// Gets the hash of a file + /// File path. + public static byte[] File(string filename) + { + var localSha256Provider = SHA256.Create(); + var fileStream = new FileStream(filename, FileMode.Open); + byte[] result = localSha256Provider.ComputeHash(fileStream); + fileStream.Close(); + + return result; + } + + /// Gets the hash of a file in hexadecimal and as a byte array. + /// File path. + /// Byte array of the hash value. + public static string File(string filename, out byte[] hash) + { + var localSha256Provider = SHA256.Create(); + var fileStream = new FileStream(filename, FileMode.Open); + hash = localSha256Provider.ComputeHash(fileStream); + var sha256Output = new StringBuilder(); + + foreach(byte h in hash) + sha256Output.Append(h.ToString("x2")); + + fileStream.Close(); + + return sha256Output.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Length of the data buffer to hash. + /// Byte array of the hash value. + public static string Data(byte[] data, uint len, out byte[] hash) + { + var localSha256Provider = SHA256.Create(); + hash = localSha256Provider.ComputeHash(data, 0, (int)len); + var sha256Output = new StringBuilder(); + + foreach(byte h in hash) + sha256Output.Append(h.ToString("x2")); + + return sha256Output.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Byte array of the hash value. + public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); + } +} \ No newline at end of file diff --git a/Aaru.Checksums/SHA384Context.cs b/Aaru.Checksums/SHA384Context.cs new file mode 100644 index 000000000..754789048 --- /dev/null +++ b/Aaru.Checksums/SHA384Context.cs @@ -0,0 +1,134 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : SHA384Context.cs +// Author(s) : Natalia Portillo +// +// Component : Checksums. +// +// --[ Description ] ---------------------------------------------------------- +// +// Wraps up .NET SHA384 implementation to a Init(), Update(), Final() context. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using Aaru.CommonTypes.Interfaces; + +namespace Aaru.Checksums +{ + /// + /// Wraps up .NET SHA384 implementation to a Init(), Update(), Final() context. + public sealed class Sha384Context : IChecksum + { + readonly SHA384 _provider; + + /// Initializes the SHA384 hash provider + public Sha384Context() => _provider = SHA384.Create(); + + /// + /// Updates the hash with data. + /// Data buffer. + /// Length of buffer to hash. + public void Update(byte[] data, uint len) => _provider.TransformBlock(data, 0, (int)len, data, 0); + + /// + /// Updates the hash with data. + /// Data buffer. + public void Update(byte[] data) => Update(data, (uint)data.Length); + + /// + /// Returns a byte array of the hash value. + public byte[] Final() + { + _provider.TransformFinalBlock(Array.Empty(), 0, 0); + + return _provider.Hash; + } + + /// + /// Returns a hexadecimal representation of the hash value. + public string End() + { + _provider.TransformFinalBlock(Array.Empty(), 0, 0); + var sha384Output = new StringBuilder(); + + foreach(byte h in _provider.Hash) + sha384Output.Append(h.ToString("x2")); + + return sha384Output.ToString(); + } + + /// Gets the hash of a file + /// File path. + public static byte[] File(string filename) + { + var localSha384Provider = SHA384.Create(); + var fileStream = new FileStream(filename, FileMode.Open); + byte[] result = localSha384Provider.ComputeHash(fileStream); + fileStream.Close(); + + return result; + } + + /// Gets the hash of a file in hexadecimal and as a byte array. + /// File path. + /// Byte array of the hash value. + public static string File(string filename, out byte[] hash) + { + var localSha384Provider = SHA384.Create(); + var fileStream = new FileStream(filename, FileMode.Open); + hash = localSha384Provider.ComputeHash(fileStream); + var sha384Output = new StringBuilder(); + + foreach(byte h in hash) + sha384Output.Append(h.ToString("x2")); + + fileStream.Close(); + + return sha384Output.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Length of the data buffer to hash. + /// Byte array of the hash value. + public static string Data(byte[] data, uint len, out byte[] hash) + { + var localSha384Provider = SHA384.Create(); + hash = localSha384Provider.ComputeHash(data, 0, (int)len); + var sha384Output = new StringBuilder(); + + foreach(byte h in hash) + sha384Output.Append(h.ToString("x2")); + + return sha384Output.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Byte array of the hash value. + public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); + } +} \ No newline at end of file diff --git a/Aaru.Checksums/SHA512Context.cs b/Aaru.Checksums/SHA512Context.cs new file mode 100644 index 000000000..9d5bae6d8 --- /dev/null +++ b/Aaru.Checksums/SHA512Context.cs @@ -0,0 +1,134 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : SHA512Context.cs +// Author(s) : Natalia Portillo +// +// Component : Checksums. +// +// --[ Description ] ---------------------------------------------------------- +// +// Wraps up .NET SHA512 implementation to a Init(), Update(), Final() context. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using Aaru.CommonTypes.Interfaces; + +namespace Aaru.Checksums +{ + /// + /// Wraps up .NET SHA512 implementation to a Init(), Update(), Final() context. + public sealed class Sha512Context : IChecksum + { + readonly SHA512 _provider; + + /// Initializes the SHA512 hash provider + public Sha512Context() => _provider = SHA512.Create(); + + /// + /// Updates the hash with data. + /// Data buffer. + /// Length of buffer to hash. + public void Update(byte[] data, uint len) => _provider.TransformBlock(data, 0, (int)len, data, 0); + + /// + /// Updates the hash with data. + /// Data buffer. + public void Update(byte[] data) => Update(data, (uint)data.Length); + + /// + /// Returns a byte array of the hash value. + public byte[] Final() + { + _provider.TransformFinalBlock(Array.Empty(), 0, 0); + + return _provider.Hash; + } + + /// + /// Returns a hexadecimal representation of the hash value. + public string End() + { + _provider.TransformFinalBlock(Array.Empty(), 0, 0); + var sha512Output = new StringBuilder(); + + foreach(byte h in _provider.Hash) + sha512Output.Append(h.ToString("x2")); + + return sha512Output.ToString(); + } + + /// Gets the hash of a file + /// File path. + public static byte[] File(string filename) + { + var localSha512Provider = SHA512.Create(); + var fileStream = new FileStream(filename, FileMode.Open); + byte[] result = localSha512Provider.ComputeHash(fileStream); + fileStream.Close(); + + return result; + } + + /// Gets the hash of a file in hexadecimal and as a byte array. + /// File path. + /// Byte array of the hash value. + public static string File(string filename, out byte[] hash) + { + var localSha512Provider = SHA512.Create(); + var fileStream = new FileStream(filename, FileMode.Open); + hash = localSha512Provider.ComputeHash(fileStream); + var sha512Output = new StringBuilder(); + + foreach(byte h in hash) + sha512Output.Append(h.ToString("x2")); + + fileStream.Close(); + + return sha512Output.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Length of the data buffer to hash. + /// Byte array of the hash value. + public static string Data(byte[] data, uint len, out byte[] hash) + { + var localSha512Provider = SHA512.Create(); + hash = localSha512Provider.ComputeHash(data, 0, (int)len); + var sha512Output = new StringBuilder(); + + foreach(byte h in hash) + sha512Output.Append(h.ToString("x2")); + + return sha512Output.ToString(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Byte array of the hash value. + public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); + } +} \ No newline at end of file diff --git a/Aaru.Checksums/SpamSumContext.cs b/Aaru.Checksums/SpamSumContext.cs new file mode 100644 index 000000000..b3fcd19ec --- /dev/null +++ b/Aaru.Checksums/SpamSumContext.cs @@ -0,0 +1,527 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : SpamSumContext.cs +// Author(s) : Natalia Portillo +// +// Component : Checksums. +// +// --[ Description ] ---------------------------------------------------------- +// +// Implements the SpamSum fuzzy hashing algorithm. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +// Based on ssdeep +// Copyright (C) 2002 Andrew Tridgell +// Copyright (C) 2006 ManTech International Corporation +// Copyright (C) 2013 Helmut Grohne +// +// Earlier versions of this code were named fuzzy.c and can be found at: +// http://www.samba.org/ftp/unpacked/junkcode/spamsum/ +// http://ssdeep.sf.net/ + +using System; +using System.Runtime.CompilerServices; +using System.Text; +using Aaru.CommonTypes.Interfaces; + +namespace Aaru.Checksums +{ + /// + /// Implements the SpamSum fuzzy hashing algorithm. + public sealed class SpamSumContext : IChecksum + { + const uint ROLLING_WINDOW = 7; + const uint MIN_BLOCKSIZE = 3; + const uint HASH_PRIME = 0x01000193; + const uint HASH_INIT = 0x28021967; + const uint NUM_BLOCKHASHES = 31; + const uint SPAMSUM_LENGTH = 64; + const uint FUZZY_MAX_RESULT = (2 * SPAMSUM_LENGTH) + 20; + + //"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + readonly byte[] _b64 = + { + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, + 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, + 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, + 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F + }; + + FuzzyState _self; + + /// Initializes the SpamSum structures + public SpamSumContext() + { + _self = new FuzzyState + { + Bh = new BlockhashContext[NUM_BLOCKHASHES] + }; + + for(int i = 0; i < NUM_BLOCKHASHES; i++) + _self.Bh[i].Digest = new byte[SPAMSUM_LENGTH]; + + _self.Bhstart = 0; + _self.Bhend = 1; + _self.Bh[0].H = HASH_INIT; + _self.Bh[0].Halfh = HASH_INIT; + _self.Bh[0].Digest[0] = 0; + _self.Bh[0].Halfdigest = 0; + _self.Bh[0].Dlen = 0; + _self.TotalSize = 0; + roll_init(); + } + + /// + /// Updates the hash with data. + /// Data buffer. + /// Length of buffer to hash. + public void Update(byte[] data, uint len) + { + _self.TotalSize += len; + + for(int i = 0; i < len; i++) + fuzzy_engine_step(data[i]); + } + + /// + /// Updates the hash with data. + /// Data buffer. + public void Update(byte[] data) => Update(data, (uint)data.Length); + + /// + /// Returns a byte array of the hash value. + public byte[] Final() => throw new NotImplementedException("SpamSum does not have a binary representation."); + + /// + /// Returns a base64 representation of the hash value. + public string End() + { + FuzzyDigest(out byte[] result); + + return CToString(result); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + void roll_init() => _self.Roll = new RollState + { + Window = new byte[ROLLING_WINDOW] + }; + + /* + * a rolling hash, based on the Adler checksum. By using a rolling hash + * we can perform auto resynchronisation after inserts/deletes + + * internally, h1 is the sum of the bytes in the window and h2 + * is the sum of the bytes times the index + + * h3 is a shift/xor based rolling hash, and is mostly needed to ensure that + * we can cope with large blocksize values + */ + [MethodImpl(MethodImplOptions.AggressiveInlining)] + void roll_hash(byte c) + { + _self.Roll.H2 -= _self.Roll.H1; + _self.Roll.H2 += ROLLING_WINDOW * c; + + _self.Roll.H1 += c; + _self.Roll.H1 -= _self.Roll.Window[_self.Roll.N % ROLLING_WINDOW]; + + _self.Roll.Window[_self.Roll.N % ROLLING_WINDOW] = c; + _self.Roll.N++; + + /* The original spamsum AND'ed this value with 0xFFFFFFFF which + * in theory should have no effect. This AND has been removed + * for performance (jk) */ + _self.Roll.H3 <<= 5; + _self.Roll.H3 ^= c; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + uint roll_sum() => _self.Roll.H1 + _self.Roll.H2 + _self.Roll.H3; + + /* A simple non-rolling hash, based on the FNV hash. */ + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static uint sum_hash(byte c, uint h) => (h * HASH_PRIME) ^ c; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static uint SSDEEP_BS(uint index) => MIN_BLOCKSIZE << (int)index; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + void fuzzy_try_fork_blockhash() + { + if(_self.Bhend >= NUM_BLOCKHASHES) + return; + + if(_self.Bhend == 0) // assert + throw new Exception("Assertion failed"); + + uint obh = _self.Bhend - 1; + uint nbh = _self.Bhend; + _self.Bh[nbh].H = _self.Bh[obh].H; + _self.Bh[nbh].Halfh = _self.Bh[obh].Halfh; + _self.Bh[nbh].Digest[0] = 0; + _self.Bh[nbh].Halfdigest = 0; + _self.Bh[nbh].Dlen = 0; + ++_self.Bhend; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + void fuzzy_try_reduce_blockhash() + { + if(_self.Bhstart >= _self.Bhend) + throw new Exception("Assertion failed"); + + if(_self.Bhend - _self.Bhstart < 2) + /* Need at least two working hashes. */ + return; + + if((ulong)SSDEEP_BS(_self.Bhstart) * SPAMSUM_LENGTH >= _self.TotalSize) + /* Initial blocksize estimate would select this or a smaller + * blocksize. */ + return; + + if(_self.Bh[_self.Bhstart + 1].Dlen < SPAMSUM_LENGTH / 2) + /* Estimate adjustment would select this blocksize. */ + return; + + /* At this point we are clearly no longer interested in the + * start_blocksize. Get rid of it. */ + ++_self.Bhstart; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + void fuzzy_engine_step(byte c) + { + uint i; + /* At each character we update the rolling hash and the normal hashes. + * When the rolling hash hits a reset value then we emit a normal hash + * as a element of the signature and reset the normal hash. */ + roll_hash(c); + ulong h = roll_sum(); + + for(i = _self.Bhstart; i < _self.Bhend; ++i) + { + _self.Bh[i].H = sum_hash(c, _self.Bh[i].H); + _self.Bh[i].Halfh = sum_hash(c, _self.Bh[i].Halfh); + } + + for(i = _self.Bhstart; i < _self.Bhend; ++i) + { + /* With growing blocksize almost no runs fail the next test. */ + if(h % SSDEEP_BS(i) != SSDEEP_BS(i) - 1) + /* Once this condition is false for one bs, it is + * automatically false for all further bs. I.e. if + * h === -1 (mod 2*bs) then h === -1 (mod bs). */ + break; + + /* We have hit a reset point. We now emit hashes which are + * based on all characters in the piece of the message between + * the last reset point and this one */ + if(0 == _self.Bh[i].Dlen) + fuzzy_try_fork_blockhash(); + + _self.Bh[i].Digest[_self.Bh[i].Dlen] = _b64[_self.Bh[i].H % 64]; + _self.Bh[i].Halfdigest = _b64[_self.Bh[i].Halfh % 64]; + + if(_self.Bh[i].Dlen < SPAMSUM_LENGTH - 1) + { + /* We can have a problem with the tail overflowing. The + * easiest way to cope with this is to only reset the + * normal hash if we have room for more characters in + * our signature. This has the effect of combining the + * last few pieces of the message into a single piece + * */ + _self.Bh[i].Digest[++_self.Bh[i].Dlen] = 0; + _self.Bh[i].H = HASH_INIT; + + if(_self.Bh[i].Dlen >= SPAMSUM_LENGTH / 2) + continue; + + _self.Bh[i].Halfh = HASH_INIT; + _self.Bh[i].Halfdigest = 0; + } + else + fuzzy_try_reduce_blockhash(); + } + } + + // CLAUNIA: Flags seems to never be used in ssdeep, so I just removed it for code simplicity + [MethodImpl(MethodImplOptions.AggressiveInlining)] + void FuzzyDigest(out byte[] result) + { + var sb = new StringBuilder(); + uint bi = _self.Bhstart; + uint h = roll_sum(); + int remain = (int)(FUZZY_MAX_RESULT - 1); /* Exclude terminating '\0'. */ + result = new byte[FUZZY_MAX_RESULT]; + + /* Verify that our elimination was not overeager. */ + if(!(bi == 0 || (ulong)SSDEEP_BS(bi) / 2 * SPAMSUM_LENGTH < _self.TotalSize)) + throw new Exception("Assertion failed"); + + int resultOff; + + /* Initial blocksize guess. */ + while((ulong)SSDEEP_BS(bi) * SPAMSUM_LENGTH < _self.TotalSize) + { + ++bi; + + if(bi >= NUM_BLOCKHASHES) + throw new OverflowException("The input exceeds data types."); + } + + /* Adapt blocksize guess to actual digest length. */ + while(bi >= _self.Bhend) + --bi; + + while(bi > _self.Bhstart && + _self.Bh[bi].Dlen < SPAMSUM_LENGTH / 2) + --bi; + + if(bi > 0 && + _self.Bh[bi].Dlen < SPAMSUM_LENGTH / 2) + throw new Exception("Assertion failed"); + + sb.AppendFormat("{0}:", SSDEEP_BS(bi)); + int i = Encoding.ASCII.GetBytes(sb.ToString()).Length; + + if(i <= 0) + /* Maybe snprintf has set errno here? */ + throw new OverflowException("The input exceeds data types."); + + if(i >= remain) + throw new Exception("Assertion failed"); + + remain -= i; + + Array.Copy(Encoding.ASCII.GetBytes(sb.ToString()), 0, result, 0, i); + + resultOff = i; + + i = (int)_self.Bh[bi].Dlen; + + if(i > remain) + throw new Exception("Assertion failed"); + + Array.Copy(_self.Bh[bi].Digest, 0, result, resultOff, i); + resultOff += i; + remain -= i; + + if(h != 0) + { + if(remain <= 0) + throw new Exception("Assertion failed"); + + result[resultOff] = _b64[_self.Bh[bi].H % 64]; + + if(i < 3 || + result[resultOff] != result[resultOff - 1] || + result[resultOff] != result[resultOff - 2] || + result[resultOff] != result[resultOff - 3]) + { + ++resultOff; + --remain; + } + } + else if(_self.Bh[bi].Digest[i] != 0) + { + if(remain <= 0) + throw new Exception("Assertion failed"); + + result[resultOff] = _self.Bh[bi].Digest[i]; + + if(i < 3 || + result[resultOff] != result[resultOff - 1] || + result[resultOff] != result[resultOff - 2] || + result[resultOff] != result[resultOff - 3]) + { + ++resultOff; + --remain; + } + } + + if(remain <= 0) + throw new Exception("Assertion failed"); + + result[resultOff++] = 0x3A; // ':' + --remain; + + if(bi < _self.Bhend - 1) + { + ++bi; + i = (int)_self.Bh[bi].Dlen; + + if(i > remain) + throw new Exception("Assertion failed"); + + Array.Copy(_self.Bh[bi].Digest, 0, result, resultOff, i); + resultOff += i; + remain -= i; + + if(h != 0) + { + if(remain <= 0) + throw new Exception("Assertion failed"); + + h = _self.Bh[bi].Halfh; + result[resultOff] = _b64[h % 64]; + + if(i < 3 || + result[resultOff] != result[resultOff - 1] || + result[resultOff] != result[resultOff - 2] || + result[resultOff] != result[resultOff - 3]) + { + ++resultOff; + --remain; + } + } + else + { + i = _self.Bh[bi].Halfdigest; + + if(i != 0) + { + if(remain <= 0) + throw new Exception("Assertion failed"); + + result[resultOff] = (byte)i; + + if(i < 3 || + result[resultOff] != result[resultOff - 1] || + result[resultOff] != result[resultOff - 2] || + result[resultOff] != result[resultOff - 3]) + { + ++resultOff; + --remain; + } + } + } + } + else if(h != 0) + { + if(_self.Bh[bi].Dlen != 0) + throw new Exception("Assertion failed"); + + if(remain <= 0) + throw new Exception("Assertion failed"); + + result[resultOff++] = _b64[_self.Bh[bi].H % 64]; + /* No need to bother with FUZZY_FLAG_ELIMSEQ, because this + * digest has length 1. */ + --remain; + } + + result[resultOff] = 0; + } + + /// Gets the hash of a file + /// File path. + public static byte[] File(string filename) => + throw new NotImplementedException("SpamSum does not have a binary representation."); + + /// Gets the hash of a file in hexadecimal and as a byte array. + /// File path. + /// Byte array of the hash value. + public static string File(string filename, out byte[] hash) => + throw new NotImplementedException("Not yet implemented."); + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// Length of the data buffer to hash. + /// null + /// Base64 representation of SpamSum $blocksize:$hash:$hash + public static string Data(byte[] data, uint len, out byte[] hash) + { + var fuzzyContext = new SpamSumContext(); + + fuzzyContext.Update(data, len); + + hash = null; + + return fuzzyContext.End(); + } + + /// Gets the hash of the specified data buffer. + /// Data buffer. + /// null + /// Base64 representation of SpamSum $blocksize:$hash:$hash + public static string Data(byte[] data, out byte[] hash) => Data(data, (uint)data.Length, out hash); + + // Converts an ASCII null-terminated string to .NET string + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static string CToString(byte[] cString) + { + int count = 0; + + // ReSharper disable once LoopCanBeConvertedToQuery + // LINQ is six times slower + foreach(byte c in cString) + { + if(c == 0) + break; + + count++; + } + + return Encoding.ASCII.GetString(cString, 0, count); + } + + struct RollState + { + public byte[] Window; + + // ROLLING_WINDOW + public uint H1; + public uint H2; + public uint H3; + public uint N; + } + + /* A blockhash contains a signature state for a specific (implicit) blocksize. + * The blocksize is given by SSDEEP_BS(index). The h and halfh members are the + * FNV hashes, where halfh stops to be reset after digest is SPAMSUM_LENGTH/2 + * long. The halfh hash is needed be able to truncate digest for the second + * output hash to stay compatible with ssdeep output. */ + struct BlockhashContext + { + public uint H; + public uint Halfh; + public byte[] Digest; + + // SPAMSUM_LENGTH + public byte Halfdigest; + public uint Dlen; + } + + struct FuzzyState + { + public uint Bhstart; + public uint Bhend; + public BlockhashContext[] Bh; + + //NUM_BLOCKHASHES + public ulong TotalSize; + public RollState Roll; + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes b/Aaru.CommonTypes deleted file mode 160000 index 3043d3762..000000000 --- a/Aaru.CommonTypes +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3043d3762fcbc4f06d239328563ae7ccff5a57b6 diff --git a/Aaru.CommonTypes/.editorconfig b/Aaru.CommonTypes/.editorconfig new file mode 100644 index 000000000..9181fe501 --- /dev/null +++ b/Aaru.CommonTypes/.editorconfig @@ -0,0 +1,632 @@ +root = true + +[*] +charset = utf-8 +next_line = crlf +insert_final_newline = false +indent_style = space +indent_size = 4 + +# Generic non-language specific ones for Resharper and friends +brace_style = next_line +int_align = true +keep_existing_arrangement = false +place_simple_blocks_on_single_line = true +place_simple_declaration_blocks_on_single_line = true +place_attribute_on_same_line = false +space_after_unary_operator = false +space_after_comma = true +space_around_ternary_operator = true +space_around_binary_operator = true +space_around_member_access_operator = false +space_before_open_square_brackets = false +space_after_keywords_in_control_flow_statements = true +space_before_comma = false +space_between_method_call_name_and_opening_parenthesis = false +space_between_method_declaration_name_and_open_parenthesis = false +space_between_square_brackets = false +space_between_parentheses_of_control_flow_statements = false +accessor_owner_declaration_braces = next_line +accessor_declaration_braces = next_line +case_block_braces = next_line +initializer_braces = next_line +other_braces = next_line +allow_comment_after_lbrace = false +empty_block_style = together_same_line +braces_for_ifelse = not_required +braces_for_for = not_required +braces_for_foreach = not_required +braces_for_while = not_required +braces_for_dowhile = not_required +braces_for_using = not_required +braces_for_lock = not_required +braces_for_fixed = not_required +method_or_operator_body = expression_body +local_function_body = expression_body +constructor_or_destructor_body = expression_body +accessor_owner_body = expression_body +force_attribute_style = join +function_braces = next_line +force_control_statements_braces = always_remove +space_in_singleline_accessorholder = true +type_declaration_braces = next_line +invocable_declaration_braces = next_line +anonymous_method_declaration_braces = next_line +space_between_accessors_in_singleline_property = true +indent_nested_usings_stmt = true +space_within_empty_braces = false +indent_nested_fixed_stmt = true +indent_nested_lock_stmt = true +indent_nested_for_stmt = true +indent_nested_foreach_stmt = true +indent_nested_while_stmt = true +use_continuous_indent_inside_parens = true +indent_method_decl_pars = inside +indent_invocation_pars = inside +indent_statement_pars = inside +indent_typeparam_angles = inside +indent_typearg_angles = inside +indent_pars = inside +indent_preprocessor_if = outdent +indent_preprocessor_region = usual_indent +indent_preprocessor_other = usual_indent +indent_switch_labels = true +indent_type_constraints = true +stick_comment = false +alignment_tab_fill_style = use_spaces +align_multiline_parameter = true +align_multiline_extends_list = true +align_linq_query = true +align_multiline_binary_expressions_chain = true +outdent_binary_ops = true +align_multiline_calls_chain = true +outdent_dots = true +align_multiline_array_and_object_initializer = false +indent_anonymous_method_block = false +align_first_arg_by_paren = true +align_multiline_argument = true +align_tuple_components = true +align_multiline_expression = true +align_multiline_for_stmt = true +align_multiple_declaration = true +align_multline_type_parameter_list = true +align_multline_type_parameter_constrains = true +int_align_fields = true +int_align_properties = true +int_align_methods = true +int_align_parameters = false +int_align_variables = true +int_align_assignments = true +int_align_nested_ternary = true +int_align_invocations = false +int_align_binary_expressions = true +int_align_comments = true +int_align_switch_sections = true +keep_user_linebreaks = false +keep_existing_arrangement = false +keep_existing_linebreaks = false +max_line_length = 120 +wrap_before_comma = false +special_else_if_treatment = true +place_type_attribute_on_same_line = never +place_method_attribute_on_same_line = never +place_accessorholder_attribute_on_same_line = never +place_attribute_on_same_line = never +place_accessor_attribute_on_same_line = never +place_attribute_on_same_line = never +place_field_attribute_on_same_line = never +place_attribute_on_same_line = never +wrap_parameters_style = wrap_if_long +keep_existing_declaration_parens_arrangement = false +wrap_before_declaration_lpar = false +wrap_after_declaration_lpar = false +wrap_before_declaration_rpar = false +place_constructor_initializer_on_same_line = true +keep_existing_expr_member_arrangement = false +place_expr_method_on_single_line = true +place_expr_property_on_single_line = true +place_expr_accessor_on_single_line = true +wrap_before_arrow_with_expressions = false +place_type_constraints_on_same_line = true +wrap_before_first_type_parameter_constraint = true +wrap_multiple_type_parameter_constraints_style = wrap_if_long +wrap_before_type_parameter_langle = true +wrap_before_extends_colon = false +wrap_extends_list_style = wrap_if_long +keep_existing_declaration_block_arrangement = false +place_abstract_accessorholder_on_single_line = true +place_simple_accessorholder_on_single_line = false +place_accessor_with_attrs_holder_on_single_line = false +place_simple_accessor_on_single_line = true +place_simple_method_on_single_line = false +keep_existing_enum_arrangement = false +place_simple_enum_on_single_line = false +wrap_enum_declaration = wrap_if_long +new_line_before_else = true +new_line_before_while = false +wrap_for_stmt_header_style = wrap_if_long +wrap_multiple_declaration_style = wrap_if_long +keep_existing_embedded_arrangement = false +place_simple_embedded_statement_on_same_line = false +place_simple_case_statement_on_same_line = true +keep_existing_embedded_block_arrangement = false +place_simple_embedded_block_on_same_line = false +place_simple_anonymousmethod_on_single_line = false +keep_existing_initializer_arrangement = false +place_simple_initializer_on_single_line = false +wrap_object_and_collection_initializer_style = chop_always +wrap_array_initializer_style = wrap_if_long +wrap_arguments_style = wrap_if_long +keep_existing_invocation_parens_arrangement = false +wrap_after_invocation_lpar = false +wrap_before_invocation_rpar = false +wrap_after_dot_in_method_calls = true +wrap_chained_method_calls = wrap_if_long +wrap_before_binary_opsign = false +wrap_chained_binary_expressions = wrap_if_long +force_chop_compound_if_expression = true +force_chop_compound_while_expression = true +force_chop_compound_do_expression = true +wrap_before_ternary_opsigns = true +wrap_ternary_expr_style = wrap_if_long +nested_ternary_style = expanded +wrap_linq_expressions = wrap_if_long +wrap_before_linq_expression = false +place_linq_into_on_new_line = false +wrap_verbatim_interpolated_strings = wrap_if_long +extra_spaces = remove_all +space_after_keywords_in_control_flow_statements = false +space_between_method_call_name_and_opening_parenthesis = false +space_between_method_declaration_name_and_open_parenthesis = false +space_before_typeof_parentheses = false +space_before_checked_parentheses = false +space_before_sizeof_parentheses = false +space_before_nameof_parentheses = false +space_between_keyword_and_expression = true +space_between_keyword_and_type = true +space_around_assignment_op = true +space_around_logical_op = true +space_around_binary_operator = true +space_around_equality_op = true +space_around_relational_op = true +space_around_bitwise_op = true +space_around_additive_op = true +space_around_multiplicative_op = true +space_around_shift_op = true +space_around_nullcoalescing_op = true +space_around_arrow_op = false +space_after_logical_not_op = false +space_after_unary_operator = false +space_after_cast = false +space_around_dot = false +space_around_lambda_arrow = true +space_before_pointer_asterik_declaration = false +space_before_nullable_mark = false +blank_lines_around_class_definition = 1 +namespace_indentation = all +space_within_template_argument = false +align_union_type_usage = true +space_in_singleline_method = true +space_in_singleline_anonymous_method = true +space_within_single_line_array_initializer_braces = true +space_around_arrow_op = false + +# These are for markup languages (HTML, XML, etc) +spaces_around_eq_in_pi_attribute = false +space_after_last_pi_attribute = true +pi_attributes_indent = align_by_first_attribute +blank_line_after_pi = true +spaces_around_eq_in_attribute = false +space_after_last_attribute = false +space_before_self_closing = true +attribute_style = on_single_line +attribute_indent = align_by_first_attribute +sort_attributes = true +sort_class_selectors = true +max_blank_lines_between_tags = 0 +linebreak_before_all_elements = true +linebreak_before_multiline_elements = true +quote_style = doublequoted +delete_quotes_from_solid_values = false +normalize_tag_names = true + + +[{.babelrc,.stylelintrc,jest.config,.eslintrc,.prettierrc,*.json,*.jsb3,*.jsb2,*.bowerrc}] +indent_size = 2 + +[*.js.map] +indent_size = 2 + +[*.{css,scss}] +indent_size = 2 +declarations_style = separate_lines_for_nonsingle +media_query_style = separate_lines +selector_style = same_line +properties_style = separate_lines_for_nonsingle +brace_style = next_line + +[{.analysis_options,*.yml,*.yaml}] +indent_size = 2 + +# Xml project files +[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] +indent_size = 2 + +# Xml files +[*.{xml,stylecop,resx,ruleset}] +indent_size = 2 + +# Xml config files +[*.{props,targets,config,nuspec}] +indent_size = 2 + +# .net files +[*.{cs,vb}] +# These set the this. / Me. +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning + +# These make it suggest Int32 instead of int, etc. +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# This controls implicit access modifiers +dotnet_style_require_accessibility_modifiers = never:suggestion + +# Prefer non modified fields to be marked readonly +dotnet_style_readonly_field = true:warning + +# Parenthesis settings +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_operators = always_for_clarity:warning + +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:error +dotnet_style_prefer_inferred_tuple_names = true:warning +dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning +dotnet_style_prefer_conditional_expression_over_return = true:warning +dotnet_style_coalesce_expression = true:warning +dotnet_style_null_propagation = true:error + +dotnet_sort_system_directives_first = true + +# Constants in C style, all-caps +dotnet_naming_rule.constant_fields_caps.symbols = constant_fields +dotnet_naming_rule.constant_fields_caps.severity = warning +dotnet_naming_rule.constant_fields_caps.style = caps_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.required_modifiers = const +dotnet_naming_style.caps_style.capitalization = all_upper + +# interfaces should be prefixed with I +dotnet_naming_rule.pascal_case_for_interface.severity = error +dotnet_naming_rule.pascal_case_for_interface.symbols = interfaces_fields +dotnet_naming_rule.pascal_case_for_interface.style = pascal_case_interface_style +dotnet_naming_symbols.interfaces_fields.applicable_kinds = interface +dotnet_naming_style.pascal_case_interface_style.required_prefix = I +dotnet_naming_style.pascal_case_interface_style.capitalization = pascal_case + +## internal and private fields should be _camelCase +dotnet_naming_rule.camel_case_for_private_internal_fields.severity = warning +dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields +dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style +dotnet_naming_symbols.private_internal_fields.applicable_kinds = field +dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal +dotnet_naming_style.camel_case_underscore_style.required_prefix = _ +dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case + +# 2018-12-07 NP: This is not yet working in VS2017 +# local variables should be camelCase +#dotnet_naming_rule.camel_case_for_locals.severity = suggestion +#dotnet_naming_rule.camel_case_for_locals.symbols = local_fields +#dotnet_naming_rule.camel_case_for_locals.style = camel_case_style +#dotnet_naming_symbols.local_fields.applicable_kinds = local +#dotnet_naming_style.camel_case_style.capitalization = camel_case + +[*.cs] +# var var var +csharp_style_var_for_built_in_types = false:warning +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = false:warning + +csharp_style_expression_bodied_methods = when_on_single_line:suggestion +csharp_style_expression_bodied_constructors = when_on_single_line:suggestion +csharp_style_expression_bodied_operators = when_on_single_line:suggestion +csharp_style_expression_bodied_properties = when_on_single_line:suggestion +csharp_style_expression_bodied_indexers = when_on_single_line:suggestion +csharp_style_expression_bodied_accessors = when_on_single_line:suggestion + +csharp_style_pattern_matching_over_is_with_cast_check = true:warning +csharp_style_pattern_matching_over_as_with_null_check = when_on_single_line:warning + +csharp_style_inlined_variable_declaration = true:warning + +csharp_prefer_simple_default_expression = true:warning +csharp_style_deconstructed_variable_declaration = false:warning + +csharp_style_throw_expression = true:warning +csharp_style_conditional_delegate_call = true:warning + +csharp_prefer_braces = false + +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true + +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = flush_left + +csharp_space_after_cast = false +csharp_space_after_keywords_in_control_flow_statements = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = none +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false + +csharp_preserve_single_line_statements = false +csharp_preserve_single_line_blocks = true + +csharp_blank_lines_around_region = 0 +csharp_blank_lines_inside_region = 0 +csharp_blank_lines_before_single_line_comment = 1 +csharp_keep_blank_lines_in_declarations = 1 +csharp_remove_blank_lines_near_braces_in_declarations = true +csharp_blank_lines_after_start_comment = false +csharp_blank_lines_between_using_groups = 0 +csharp_blank_lines_after_using_list = 1 +csharp_blank_lines_around_namespace = 1 +csharp_blank_lines_inside_namespace = 0 +csharp_blank_lines_around_type = 1 +csharp_blank_lines_inside_type = 0 +csharp_blank_lines_around_field = 0 +csharp_blank_lines_around_single_line_field = 0 +csharp_blank_lines_around_property = 1 +csharp_blank_lines_around_single_line_property = 0 +csharp_blank_lines_around_auto_property = 0 +csharp_blank_lines_around_single_line_auto_property = 0 +csharp_blank_lines_around_invocable = 1 +csharp_blank_lines_around_single_line_invocable = 1 +csharp_keep_blank_lines_in_code = 1 +csharp_remove_blank_lines_near_braces_in_code = true +csharp_blank_lines_around_local_method = 1 +csharp_blank_lines_around_single_line_local_method = 1 +csharp_blank_lines_before_control_transfer_statements = 1 +csharp_blank_lines_after_control_transfer_statements = 1 +csharp_blank_lines_before_block_statements = 1 +csharp_blank_lines_after_block_statements = 1 +csharp_blank_lines_before_multiline_statements = 1 +csharp_blank_lines_after_multiline_statements = 1 + +csharp_type_declaration_braces = next_line +csharp_brace_style = next_line +csharp_indent_inside_namespace = true +csharp_invocable_declaration_braces = next_line +csharp_anonymous_method_declaration_braces = next_line +csharp_accessor_owner_declaration_braces = next_line +csharp_accessor_declaration_braces = next_line +csharp_case_block_braces = next_line +csharp_initializer_braces = next_line +csharp_other_braces = next_line +csharp_allow_comment_after_lbrace = false +csharp_empty_block_style = together_same_line + +csharp_for_built_in_types = use_explicit_type +csharp_for_simple_types = use_var_when_evident +csharp_for_other_types = use_explicit_type +csharp_prefer_separate_deconstructed_variables_declaration = true +csharp_prefer_explicit_discard_declaration = false + +csharp_instance_members_qualify_members = none +csharp_builtin_type_reference_style = use_keyword +csharp_prefer_qualified_reference = false +csharp_add_imports_to_deepest_scope = false +csharp_allow_alias = true +csharp_default_private_modifier = implicit +csharp_default_internal_modifier = explicit +csharp_arguments_literal = positional +csharp_arguments_string_literal = positional +csharp_arguments_named = positional +csharp_arguments_anonymous_function = positional +csharp_arguments_other = positional +csharp_braces_for_ifelse = not_required +csharp_braces_for_for = not_required +csharp_braces_for_foreach = not_required +csharp_braces_for_while = not_required +csharp_braces_for_dowhile = not_required +csharp_braces_for_using = not_required +csharp_braces_for_lock = not_required +csharp_braces_for_fixed = not_required +csharp_method_or_operator_body = expression_body +csharp_local_function_body = expression_body +csharp_constructor_or_destructor_body = expression_body +csharp_accessor_owner_body = expression_body +csharp_force_attribute_style = join +csharp_indent_nested_usings_stmt = true + +csharp_builtin_type_reference_for_member_access_style = use_keyword +csharp_indent_nested_fixed_stmt = true +csharp_indent_nested_lock_stmt = true +csharp_indent_nested_for_stmt = true +csharp_indent_nested_foreach_stmt = true +csharp_indent_nested_while_stmt = true +csharp_use_continuous_indent_inside_parens = true +csharp_indent_method_decl_pars = inside +csharp_indent_invocation_pars = inside +csharp_indent_statement_pars = inside +csharp_indent_typeparam_angles = inside +csharp_indent_typearg_angles = inside +csharp_indent_pars = inside +csharp_indent_preprocessor_if = outdent +csharp_indent_preprocessor_region = usual_indent +csharp_indent_preprocessor_other = usual_indent +csharp_indent_switch_labels = true +csharp_indent_type_constraints = true +csharp_stick_comment = false +csharp_alignment_tab_fill_style = use_spaces +csharp_align_multiline_parameter = true +csharp_align_multiline_extends_list = true +csharp_align_linq_query = true +csharp_align_multiline_binary_expressions_chain = true +csharp_outdent_binary_ops = true +csharp_align_multiline_calls_chain = true +csharp_outdent_dots = true +csharp_align_multiline_array_and_object_initializer = false +csharp_indent_anonymous_method_block = false +csharp_align_first_arg_by_paren = true +csharp_align_multiline_argument = true +csharp_align_tuple_components = true +csharp_align_multiline_expression = true +csharp_align_multiline_for_stmt = true +csharp_align_multiple_declaration = true +csharp_align_multline_type_parameter_list = true +csharp_align_multline_type_parameter_constrains = true +csharp_int_align_fields = true +csharp_int_align_properties = true +csharp_int_align_methods = true +csharp_int_align_parameters = false +csharp_int_align_variables = true +csharp_int_align_assignments = true +csharp_int_align_nested_ternary = true +csharp_int_align_invocations = false +csharp_int_align_binary_expressions = true +csharp_int_align_comments = true +csharp_int_align_switch_sections = true +csharp_int_align = true +csharp_keep_user_linebreaks = false +csharp_keep_existing_arrangement = false +csharp_keep_existing_linebreaks = false +csharp_max_line_length = 120 +csharp_wrap_before_comma = false +csharp_special_else_if_treatment = true +csharp_insert_final_newline = false +csharp_place_type_attribute_on_same_line = never +csharp_place_method_attribute_on_same_line = never +csharp_place_accessorholder_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_place_accessor_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_place_field_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_wrap_parameters_style = wrap_if_long +csharp_keep_existing_declaration_parens_arrangement = false +csharp_wrap_before_declaration_lpar = false +csharp_wrap_after_declaration_lpar = false +csharp_wrap_before_declaration_rpar = false +csharp_place_constructor_initializer_on_same_line = true +csharp_keep_existing_expr_member_arrangement = false +csharp_place_expr_method_on_single_line = true +csharp_place_expr_property_on_single_line = true +csharp_place_expr_accessor_on_single_line = true +csharp_wrap_before_arrow_with_expressions = false +csharp_place_type_constraints_on_same_line = true +csharp_wrap_before_first_type_parameter_constraint = true +csharp_wrap_multiple_type_parameter_constraints_style = wrap_if_long +csharp_wrap_before_type_parameter_langle = true +csharp_wrap_before_extends_colon = false +csharp_wrap_extends_list_style = wrap_if_long +csharp_keep_existing_declaration_block_arrangement = false +csharp_place_abstract_accessorholder_on_single_line = true +csharp_place_simple_accessorholder_on_single_line = false +csharp_place_accessor_with_attrs_holder_on_single_line = false +csharp_place_simple_accessor_on_single_line = true +csharp_place_simple_method_on_single_line = false +csharp_keep_existing_enum_arrangement = false +csharp_place_simple_enum_on_single_line = false +csharp_wrap_enum_declaration = wrap_if_long +csharp_new_line_before_else = true +csharp_new_line_before_while = false +csharp_wrap_for_stmt_header_style = wrap_if_long +csharp_wrap_multiple_declaration_style = wrap_if_long +csharp_keep_existing_embedded_arrangement = false +csharp_place_simple_embedded_statement_on_same_line = false +csharp_place_simple_case_statement_on_same_line = true +csharp_keep_existing_embedded_block_arrangement = false +csharp_place_simple_embedded_block_on_same_line = false +csharp_place_simple_anonymousmethod_on_single_line = false +csharp_keep_existing_initializer_arrangement = false +csharp_place_simple_initializer_on_single_line = false +csharp_wrap_object_and_collection_initializer_style = chop_always +csharp_wrap_array_initializer_style = wrap_if_long +csharp_wrap_arguments_style = wrap_if_long +csharp_keep_existing_invocation_parens_arrangement = false +csharp_wrap_after_invocation_lpar = false +csharp_wrap_before_invocation_rpar = false +csharp_wrap_after_dot_in_method_calls = true +csharp_wrap_chained_method_calls = wrap_if_long +csharp_wrap_before_binary_opsign = false +csharp_wrap_chained_binary_expressions = wrap_if_long +csharp_force_chop_compound_if_expression = true +csharp_force_chop_compound_while_expression = true +csharp_force_chop_compound_do_expression = true +csharp_wrap_before_ternary_opsigns = true +csharp_wrap_ternary_expr_style = wrap_if_long +csharp_nested_ternary_style = expanded +csharp_wrap_linq_expressions = wrap_if_long +csharp_wrap_before_linq_expression = false +csharp_place_linq_into_on_new_line = false +csharp_wrap_verbatim_interpolated_strings = wrap_if_long +csharp_extra_spaces = remove_all +csharp_space_after_keywords_in_control_flow_statements = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_before_typeof_parentheses = false +csharp_space_before_checked_parentheses = false +csharp_space_before_sizeof_parentheses = false +csharp_space_before_nameof_parentheses = false +csharp_space_between_keyword_and_expression = true +csharp_space_between_keyword_and_type = true +csharp_space_around_assignment_op = true +csharp_space_around_logical_op = true +csharp_space_around_binary_operator = true +csharp_space_around_equality_op = true +csharp_space_around_relational_op = true +csharp_space_around_bitwise_op = true +csharp_space_around_additive_op = true +csharp_space_around_multiplicative_op = true +csharp_space_around_shift_op = true +csharp_space_around_nullcoalescing_op = true +csharp_space_around_arrow_op = false +csharp_space_after_logical_not_op = false +csharp_space_after_unary_operator = false +csharp_space_after_cast = false +csharp_space_around_dot = false +csharp_space_around_lambda_arrow = true +csharp_space_before_pointer_asterik_declaration = false +csharp_space_before_nullable_mark = false + +[*.cshtml] +linebreaks_around_razor_statements = true +blank_lines_around_razor_functions = true +blank_lines_around_razor_helpers = true +blank_lines_around_razor_sections = true + +# C++ +[*.{cc,cpp,cxx,h,hpp,hxx}] +cpp_indent_access_specifiers_from_class = true +cpp_indent_wrapped_function_names = false +cpp_align_multiline_type_argument = true + +# C, C++ and ObjectiveC +[*.{c,h,cc,cpp,cxx,m,hpp,hxx}] +indent_preprocessor_directives = normal +indent_type_constraints = true + +# Javascript and Typescript +[*.{js,js.map,ts}] +quote_style = doublequoted +termination_style = ensure_semicolon \ No newline at end of file diff --git a/Aaru.CommonTypes/.gitignore b/Aaru.CommonTypes/.gitignore new file mode 100644 index 000000000..05c540d38 --- /dev/null +++ b/Aaru.CommonTypes/.gitignore @@ -0,0 +1,595 @@ +### VisualStudio template +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ +### Linux template + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* +### Xcode template +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +### VisualStudioCode template +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +### C++ template +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o + +# Precompiled Headers +*.gch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +### MonoDevelop template +#User Specific +*.usertasks + +#Mono Project Files +*.resources +test-results/ +### GPG template +secring.* + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests +### CMake template +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +### C template +# Object files +*.ko +*.elf + +# Linker output +*.map +*.exp + +*.so.* + +# Executables +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf +### Windows template +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# NuGet Packages Directory +packages/ +## TODO: If the tool you use requires repositories.config uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +# This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented) +!packages/build/ + + +# Others +sql/ +*.Cache + +# Visual Studio 2017 +.vs + +workspace.xml +cmake-build-debug +### macOS template +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +pkg/**/pkg +pkg/**/src +pkg/**/*.asc +pkg/**/*.sig +pkg/**/*.tar.xz +pkg/**/*.zip +pkg/**/aaru + +.sonarqube \ No newline at end of file diff --git a/Aaru.CommonTypes/Aaru.CommonTypes.csproj b/Aaru.CommonTypes/Aaru.CommonTypes.csproj new file mode 100644 index 000000000..ec8cf9ebb --- /dev/null +++ b/Aaru.CommonTypes/Aaru.CommonTypes.csproj @@ -0,0 +1,121 @@ + + + + 2.0 + {F2B84194-26EB-4227-B1C5-6602517E85AE} + Library + Aaru.CommonTypes + Aaru.CommonTypes + $(Version) + false + true + 5.3.2 + Claunia.com + Copyright © 2011-2023 Natalia Portillo + Aaru Data Preservation Suite + Aaru.CommonTypes + $(Version) + netcoreapp3.1 + 8 + Contains common types defined by the Aaru Data Preservation Suite. + https://github.com/aaru-dps/ + MIT + https://github.com/aaru-dps/Aaru.CommonTypes + true + en-US + true + true + snupkg + Natalia Portillo <claunia@claunia.com> + + + $(Version)+{chash:8} + true + true + + + + + + + Metadata/cicm.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + LICENSE.MIT + + + + + + + diff --git a/Aaru.CommonTypes/Aaru.CommonTypes.csproj.DotSettings b/Aaru.CommonTypes/Aaru.CommonTypes.csproj.DotSettings new file mode 100644 index 000000000..b76a6bac6 --- /dev/null +++ b/Aaru.CommonTypes/Aaru.CommonTypes.csproj.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/Aaru.CommonTypes/Delegates.cs b/Aaru.CommonTypes/Delegates.cs new file mode 100644 index 000000000..bada37f51 --- /dev/null +++ b/Aaru.CommonTypes/Delegates.cs @@ -0,0 +1,90 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Delegates.cs +// Author(s) : Natalia Portillo +// +// Component : Common types. +// +// --[ Description ] ---------------------------------------------------------- +// +// Delegates to communicate with user interface. +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.CommonTypes +{ + /// Initializes a progress indicator (e.g. makes a progress bar visible) + public delegate void InitProgressHandler(); + + /// Updates a progress indicator with text + public delegate void UpdateProgressHandler(string text, long current, long maximum); + + /// Pulses a progress indicator with indeterminate boundaries + public delegate void PulseProgressHandler(string text); + + /// Uninitializes a progress indicator (e.g. adds a newline to the console) + public delegate void EndProgressHandler(); + + /// Initializes a secondary progress indicator (e.g. makes a progress bar visible) + public delegate void InitProgressHandler2(); + + /// Updates a secondary progress indicator with text + public delegate void UpdateProgressHandler2(string text, long current, long maximum); + + /// Pulses a secondary progress indicator with indeterminate boundaries + public delegate void PulseProgressHandler2(string text); + + /// Uninitializes a secondary progress indicator (e.g. adds a newline to the console) + public delegate void EndProgressHandler2(); + + /// Initializes two progress indicators (e.g. makes a progress bar visible) + public delegate void InitTwoProgressHandler(); + + /// Updates two progress indicators with text + public delegate void UpdateTwoProgressHandler(string text, long current, long maximum, string text2, long current2, + long maximum2); + + /// Pulses a progress indicator with indeterminate boundaries + public delegate void PulseTwoProgressHandler(string text, string text2); + + /// Uninitializes a progress indicator (e.g. adds a newline to the console) + public delegate void EndTwoProgressHandler(); + + /// Updates a status indicator + public delegate void UpdateStatusHandler(string text); + + /// Shows an error message + public delegate void ErrorMessageHandler(string text); + + /// Initializes a block map that's going to be filled with a media scan + public delegate void InitBlockMapHandler(ulong blocks, ulong blockSize, ulong blocksToRead, ushort currentProfile); + + /// Updates lists of time taken on scanning from the specified sector + /// Time in milliseconds + public delegate void ScanTimeHandler(ulong sector, double duration); + + /// Specified a number of blocks could not be read on scan + public delegate void ScanUnreadableHandler(ulong sector); + + /// Sends the speed of scanning a specific sector + public delegate void ScanSpeedHandler(ulong sector, double currentSpeed); +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Enums/DeviceType.cs b/Aaru.CommonTypes/Enums/DeviceType.cs new file mode 100644 index 000000000..9abec8fe5 --- /dev/null +++ b/Aaru.CommonTypes/Enums/DeviceType.cs @@ -0,0 +1,59 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : DeviceType.cs +// Author(s) : Natalia Portillo +// +// Component : Disc image plugins. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines enumerations of device types. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.CommonTypes.Enums +{ + /// Device types + public enum DeviceType + { + /// Unknown device type + Unknown = -1, + /// ATA device + ATA = 1, + /// ATA Packet device (aka SCSI over ATA) + ATAPI = 2, + /// SCSI device (or USB-MSC, SBP2, FC, UAS, etc) + SCSI = 3, + /// SecureDigital memory card + SecureDigital = 4, + /// MultiMediaCard memory card + MMC = 5, + /// NVMe device + NVMe = 6 + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Enums/ErrorNumber.cs b/Aaru.CommonTypes/Enums/ErrorNumber.cs new file mode 100644 index 000000000..a32240038 --- /dev/null +++ b/Aaru.CommonTypes/Enums/ErrorNumber.cs @@ -0,0 +1,115 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ErrorNumber.cs +// Author(s) : Natalia Portillo +// +// Component : Common types. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines enumerations of error numbers. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.CommonTypes.Enums +{ + /// Enumerates error codes. Positive for warnings or informative codes, negative for errors. + public enum ErrorNumber + { + /// No error + NoError = 0, + /// User requested help to be shown + HelpRequested = 1, + /// Command found nothing + NothingFound = 2, + /// Media has been already dumped completely + AlreadyDumped = 3, + /// Image and its sectors cannot be verified + NotVerifiable = 4, + /// There are bad sectors and image cannot be verified + BadSectorsImageNotVerified = 5, + /// All sectors are good and image cannot be verified + CorrectSectorsImageNotVerified = 6, + /// Image is bad and sectors cannot be verified + BadImageSectorsNotVerified = 7, + /// Image is bad and there are bad sectors + BadImageBadSectors = 8, + /// All sectors are good and image is bad + CorrectSectorsBadImage = 9, + /// Image is good and sectors cannot be verified + CorrectImageSectorsNotVerified = 10, + /// Image is good and there are bad sectors + CorrectImageBadSectors = 11, + /// Exception has been raised + UnexpectedException = -1, + /// The number of arguments is not as expected + UnexpectedArgumentCount = -2, + /// A required argument is not present + MissingArgument = -3, + /// A specified argument contains an invalid value + InvalidArgument = -4, + /// The specified file cannot be found + FileNotFound = -5, + /// The specified file cannot be opened + CannotOpenFile = -6, + /// The specified encoding cannot be found + EncodingUnknown = -7, + /// The image format has not been recognized + UnrecognizedFormat = -8, + /// The image format failed to open + CannotOpenFormat = -9, + /// The specified metadata sidecar does not have the correct format + InvalidSidecar = -10, + /// The specified resume map does not have the correct format + InvalidResume = -11, + /// The specified destination file/folder already exists + DestinationExists = -12, + /// The specified image format cannot be found + FormatNotFound = -13, + /// More than one format found for the specified search criteria + TooManyFormats = -14, + /// The specified format does not support the specified media + UnsupportedMedia = -15, + /// Data will be lost writing the specified format + DataWillBeLost = -16, + /// Cannot create destination format + CannotCreateFormat = -17, + /// Error writing data + WriteError = -18, + /// Argument expected a directory, but found a file + ExpectedDirectory = -19, + /// Argument expected a file, but found a directory + ExpectedFile = -20, + /// Cannot open device + CannotOpenDevice = -21, + /// The specified operation requires administrative privileges + NotEnoughPermissions = -22, + /// Cannot remove the existing database + CannotRemoveDatabase = -23 + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Enums/Images.cs b/Aaru.CommonTypes/Enums/Images.cs new file mode 100644 index 000000000..f867494b3 --- /dev/null +++ b/Aaru.CommonTypes/Enums/Images.cs @@ -0,0 +1,395 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Images.cs +// Author(s) : Natalia Portillo +// +// Component : Disc image plugins. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines enumerations to be used by disc image plugins. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// Copyright © 2020-2023 Rebecca Wallander +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; + +// ReSharper disable UnusedMember.Global + +namespace Aaru.CommonTypes.Enums +{ + /// Track (as partitioning element) types. + public enum TrackType : byte + { + /// Audio track + Audio = 0, + /// Data track (not any of the below defined ones) + Data = 1, + /// Data track, compact disc mode 1 + CdMode1 = 2, + /// Data track, compact disc mode 2, formless + CdMode2Formless = 3, + /// Data track, compact disc mode 2, form 1 + CdMode2Form1 = 4, + /// Data track, compact disc mode 2, form 2 + CdMode2Form2 = 5 + } + + /// Type of subchannel in track + public enum TrackSubchannelType : byte + { + /// Track does not has subchannel dumped, or it's not a CD + None = 0, + /// Subchannel is packed and error corrected + Packed = 1, + /// Subchannel is interleaved + Raw = 2, + /// Subchannel is packed and comes interleaved with main channel in same file + PackedInterleaved = 3, + /// Subchannel is interleaved and comes interleaved with main channel in same file + RawInterleaved = 4, + /// Only Q subchannel is stored as 16 bytes + Q16 = 5, + /// Only Q subchannel is stored as 16 bytes and comes interleaved with main channel in same file + Q16Interleaved = 6 + } + + /// Metadata present for each sector (aka, "tag"). + public enum SectorTagType + { + /// Apple's GCR sector tags, 12 bytes + AppleSectorTag = 0, + /// Sync frame from CD sector, 12 bytes + CdSectorSync = 1, + /// CD sector header, 4 bytes + CdSectorHeader = 2, + /// CD mode 2 sector subheader + CdSectorSubHeader = 3, + /// CD sector EDC, 4 bytes + CdSectorEdc = 4, + /// CD sector ECC P, 172 bytes + CdSectorEccP = 5, + /// CD sector ECC Q, 104 bytes + CdSectorEccQ = 6, + /// CD sector ECC (P and Q), 276 bytes + CdSectorEcc = 7, + /// CD sector subchannel, 96 bytes + CdSectorSubchannel = 8, + /// CD track ISRC, string, 12 bytes + CdTrackIsrc = 9, + /// CD track text, string, 13 bytes + CdTrackText = 10, + /// CD track flags, 1 byte + CdTrackFlags = 11, + /// DVD sector copyright information + DvdCmi = 12, + /// Floppy address mark (contents depend on underlying floppy format) + FloppyAddressMark = 13, + /// DVD sector title key, 5 bytes + DvdTitleKey = 14, + /// Decrypted DVD sector title key, 5 bytes + DvdTitleKeyDecrypted = 15 + } + + /// Metadata present for each media. + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum MediaTagType + { + /// CD table of contents + CD_TOC = 0, + /// CD session information + CD_SessionInfo = 1, + /// CD full table of contents + CD_FullTOC = 2, + /// CD PMA + CD_PMA = 3, + /// CD Address-Time-In-Pregroove + CD_ATIP = 4, + /// CD-Text + CD_TEXT = 5, + /// CD Media Catalogue Number + CD_MCN = 6, + /// DVD/HD DVD Physical Format Information + DVD_PFI = 7, + /// DVD Lead-in Copyright Management Information + DVD_CMI = 8, + /// DVD disc key + DVD_DiscKey = 9, + /// DVD/HD DVD Burst Cutting Area + DVD_BCA = 10, + /// DVD/HD DVD Lead-in Disc Manufacturer Information + DVD_DMI = 11, + /// Media identifier + DVD_MediaIdentifier = 12, + /// Media key block + DVD_MKB = 13, + /// DVD-RAM/HD DVD-RAM DDS information + DVDRAM_DDS = 14, + /// DVD-RAM/HD DVD-RAM Medium status + DVDRAM_MediumStatus = 15, + /// DVD-RAM/HD DVD-RAM Spare area information + DVDRAM_SpareArea = 16, + /// DVD-R/-RW/HD DVD-R RMD in last border-out + DVDR_RMD = 17, + /// Pre-recorded information from DVD-R/-RW lead-in + DVDR_PreRecordedInfo = 18, + /// DVD-R/-RW/HD DVD-R media identifier + DVDR_MediaIdentifier = 19, + /// DVD-R/-RW/HD DVD-R physical format information + DVDR_PFI = 20, + /// ADIP information + DVD_ADIP = 21, + /// HD DVD Lead-in copyright protection information + HDDVD_CPI = 22, + /// HD DVD-R Medium Status + HDDVD_MediumStatus = 23, + /// DVD+/-R DL Layer capacity + DVDDL_LayerCapacity = 24, + /// DVD-R DL Middle Zone start address + DVDDL_MiddleZoneAddress = 25, + /// DVD-R DL Jump Interval Size + DVDDL_JumpIntervalSize = 26, + /// DVD-R DL Start LBA of the manual layer jump + DVDDL_ManualLayerJumpLBA = 27, + /// Blu-ray Disc Information + BD_DI = 28, + /// Blu-ray Burst Cutting Area + BD_BCA = 29, + /// Blu-ray Disc Definition Structure + BD_DDS = 30, + /// Blu-ray Cartridge Status + BD_CartridgeStatus = 31, + /// Blu-ray Status of Spare Area + BD_SpareArea = 32, + /// AACS volume identifier + AACS_VolumeIdentifier = 33, + /// AACS pre-recorded media serial number + AACS_SerialNumber = 34, + /// AACS media identifier + AACS_MediaIdentifier = 35, + /// Lead-in AACS media key block + AACS_MKB = 36, + /// AACS data keys + AACS_DataKeys = 37, + /// LBA extents flagged for bus encryption by AACS + AACS_LBAExtents = 38, + /// CPRM media key block in Lead-in + AACS_CPRM_MKB = 39, + /// Recognized layer formats in hybrid discs + Hybrid_RecognizedLayers = 40, + /// Disc write protection status + MMC_WriteProtection = 41, + /// Disc standard information + MMC_DiscInformation = 42, + /// Disc track resources information + MMC_TrackResourcesInformation = 43, + /// BD-R Pseudo-overwrite information + MMC_POWResourcesInformation = 44, + /// SCSI INQUIRY response + SCSI_INQUIRY = 45, + /// SCSI MODE PAGE 2Ah + SCSI_MODEPAGE_2A = 46, + /// ATA IDENTIFY DEVICE response + ATA_IDENTIFY = 47, + /// ATA IDENTIFY PACKET DEVICE response + ATAPI_IDENTIFY = 48, + /// PCMCIA/CardBus Card Information Structure + PCMCIA_CIS = 49, + /// SecureDigital CID + SD_CID = 50, + /// SecureDigital CSD + SD_CSD = 51, + /// SecureDigital SCR + SD_SCR = 52, + /// SecureDigital OCR + SD_OCR = 53, + /// MultiMediaCard CID + MMC_CID = 54, + /// MultiMediaCard CSD + MMC_CSD = 55, + /// MultiMediaCard OCR + MMC_OCR = 56, + /// MultiMediaCard Extended CSD + MMC_ExtendedCSD = 57, + /// Xbox Security Sector + Xbox_SecuritySector = 58, + /// + /// On floppy disks, data in last cylinder usually in a different format that contains duplication or + /// manufacturing information + /// + Floppy_LeadOut = 59, + /// DVD Disc Control Blocks + DCB = 60, + /// Compact Disc First Track Pregap + CD_FirstTrackPregap = 61, + /// Compact Disc Lead-out + CD_LeadOut = 62, + /// SCSI MODE SENSE (6) + SCSI_MODESENSE_6 = 63, + /// SCSI MODE SENSE (10) + SCSI_MODESENSE_10 = 64, + /// USB descriptors + USB_Descriptors = 65, + /// XGD unlocked DMI + Xbox_DMI = 66, + /// XDG unlocked PFI + Xbox_PFI = 67, + /// Compact Disc Lead-in + CD_LeadIn = 68, + /// 8 bytes response that seems to define type of MiniDisc + MiniDiscType = 69, + /// 4 bytes response to vendor command D5h + MiniDiscD5 = 70, + /// User TOC, contains fragments, track names, and can be from 1 to 3 sectors of 2336 bytes + MiniDiscUTOC = 71, + /// Not entirely clear kind of TOC that only appears on MD-DATA discs + MiniDiscDTOC = 72, + /// Decrypted DVD disc key + DVD_DiscKey_Decrypted = 73 + } + + /// Enumeration of media types defined in CICM metadata + public enum XmlMediaType : byte + { + /// Purely optical discs + OpticalDisc = 0, + /// Media that is physically block-based or abstracted like that + BlockMedia = 1, + /// Media that can be accessed by-byte or by-bit, like chips + LinearMedia = 2, + /// Media that can only store data when it is modulated to audio + AudioMedia = 3 + } + + /// CD flags bitmask + [Flags] + public enum CdFlags : byte + { + /// Track is quadraphonic. + FourChannel = 0x08, + /// Track is non-audio (data). + DataTrack = 0x04, + /// Track is copy protected. + CopyPermitted = 0x02, + /// Track has pre-emphasis. + PreEmphasis = 0x01 + } + + /// Status of a requested floppy sector + [Flags] + public enum FloppySectorStatus : byte + { + /// Both address mark and data checksums are correct. + Correct = 0x01, + /// Data checksum is incorrect. + DataError = 0x02, + /// Address mark checksum is incorrect. + AddressMarkError = 0x04, + /// There is another sector in the same track/head with same sector id. + Duplicated = 0x08, + /// Sector data section is not magnetized. + Demagnetized = 0x10, + /// Sector data section has a physically visible hole. + Hole = 0x20, + /// There is no address mark containing the requested sector id in the track/head. + NotFound = 0x40 + } + + /// Types of floppy disks + public enum FloppyTypes : byte + { + /// 8" floppy + Floppy, + /// 5.25" floppy + MiniFloppy, + /// 3.5" floppy + MicroFloppy, + /// 3" floppy + CompactFloppy, + /// 5.25" twiggy + FileWare, + /// 2.5" quickdisk + QuickDisk + } + + /// Enumeration of floppy densities + public enum FloppyDensities : byte + { + /// Standard coercivity (about 300Oe as found in 8" and 5.25"-double-density disks). + Standard, + /// Double density coercivity (about 600Oe as found in 5.25" HD and 3.5" DD disks). + Double, + /// High density coercivity (about 700Oe as found in 3.5" HD disks). + High, + /// Extended density coercivity (about 750Oe as found in 3.5" ED disks). + Extended + } + + /// Capabilities for optical media image formats + [Flags] + public enum OpticalImageCapabilities : ulong + { + /// Can store Red Book audio tracks? + CanStoreAudioTracks = 0x01, + /// Can store CD-V analogue video tracks? + CanStoreVideoTracks = 0x02, + /// Can store Yellow Book data tracks? + CanStoreDataTracks = 0x03, + /// Can store pregaps without needing to interpret the subchannel? + CanStorePregaps = 0x04, + /// Can store indexes without needing to interpret the subchannel? + CanStoreIndexes = 0x08, + /// Can store raw P to W subchannel data? + CanStoreSubchannelRw = 0x10, + /// Can store more than one session? + CanStoreSessions = 0x20, + /// Can store track ISRCs without needing to interpret the subchannel? + CanStoreIsrc = 0x40, + /// Can store Lead-In's CD-TEXT? + CanStoreCdText = 0x80, + /// Can store the MCN without needing to interpret the subchannel? + CanStoreMcn = 0x100, + /// Can store the whole 2352 bytes of a sector? + CanStoreRawData = 0x200, + /// Can store more than 1 session in media that is not CD based (DVD et al)? + CanStoreNotCdSessions = 0x2000, + /// Can store more than 1 track in media that is not CD based (DVD et al)? + CanStoreNotCdTracks = 0x4000, + /// Can store hidden tracks with a type different from track 1? + CanStoreHiddenTracks = 0x8000, + + // TODO: Implement + /// Can store scrambled data? + CanStoreScrambledData = 0x400, + /// Can store only the user area of a sector (2048, 2324, etc)? + CanStoreCookedData = 0x800, + /// Can store more than 1 track? + CanStoreMultipleTracks = 0x1000 + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Exceptions/Images.cs b/Aaru.CommonTypes/Exceptions/Images.cs new file mode 100644 index 000000000..7063131ec --- /dev/null +++ b/Aaru.CommonTypes/Exceptions/Images.cs @@ -0,0 +1,179 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Images.cs +// Author(s) : Natalia Portillo +// +// Component : Disc image plugins. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines exceptions to be thrown by disc image plugins. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Runtime.Serialization; + +namespace Aaru.CommonTypes.Exceptions +{ + /// + /// Feature is supported by image but not implemented yet. + [Serializable] + public class FeatureSupportedButNotImplementedImageException : Exception + { + /// + /// Feature is supported by image but not implemented yet. + /// Message. + /// Inner. + public FeatureSupportedButNotImplementedImageException(string message, Exception inner) : + base(message, inner) {} + + /// + /// Feature is supported by image but not implemented yet. + /// Message. + public FeatureSupportedButNotImplementedImageException(string message) : base(message) {} + + /// + /// Feature is supported by image but not implemented yet. + /// Info. + /// Context. + protected FeatureSupportedButNotImplementedImageException(SerializationInfo info, StreamingContext context) + { + if(info == null) + throw new ArgumentNullException(nameof(info)); + } + } + + /// + /// Feature is not supported by image. + [Serializable] + public class FeatureUnsupportedImageException : Exception + { + /// + /// Feature is not supported by image. + /// Message. + /// Inner. + public FeatureUnsupportedImageException(string message, Exception inner) : base(message, inner) {} + + /// + /// Feature is not supported by image. + /// Message. + public FeatureUnsupportedImageException(string message) : base(message) {} + + /// + /// Feature is not supported by image. + /// Info. + /// Context. + protected FeatureUnsupportedImageException(SerializationInfo info, StreamingContext context) + { + if(info == null) + throw new ArgumentNullException(nameof(info)); + } + } + + /// + /// Feature is supported by image but not present on it. + [Serializable] + public class FeatureNotPresentImageException : Exception + { + /// + /// Feature is supported by image but not present on it. + /// Message. + /// Inner. + public FeatureNotPresentImageException(string message, Exception inner) : base(message, inner) {} + + /// + /// Feature is supported by image but not present on it. + /// Message. + public FeatureNotPresentImageException(string message) : base(message) {} + + /// + /// Feature is supported by image but not present on it. + /// Info. + /// Context. + protected FeatureNotPresentImageException(SerializationInfo info, StreamingContext context) + { + if(info == null) + throw new ArgumentNullException(nameof(info)); + } + } + + /// + /// Feature is supported by image but not by the disc it represents. + [Serializable] + public class FeaturedNotSupportedByDiscImageException : Exception + { + /// + /// Feature is supported by image but not by the disc it represents. + /// Message. + /// Inner. + public FeaturedNotSupportedByDiscImageException(string message, Exception inner) : base(message, inner) {} + + /// + /// Feature is supported by image but not by the disc it represents. + /// Message. + public FeaturedNotSupportedByDiscImageException(string message) : base(message) {} + + /// + /// Feature is supported by image but not by the disc it represents. + /// Info. + /// Context. + protected FeaturedNotSupportedByDiscImageException(SerializationInfo info, StreamingContext context) + { + if(info == null) + throw new ArgumentNullException(nameof(info)); + } + } + + /// + /// Corrupt, incorrect or unhandled feature found on image + [Serializable] + public class ImageNotSupportedException : Exception + { + /// + /// Corrupt, incorrect or unhandled feature found on image + /// Message. + /// Inner. + public ImageNotSupportedException(string message, Exception inner) : base(message, inner) {} + + /// + /// Corrupt, incorrect or unhandled feature found on image + /// Message. + public ImageNotSupportedException(string message) : base(message) {} + + /// + /// Corrupt, incorrect or unhandled feature found on image + /// Info. + /// Context. + protected ImageNotSupportedException(SerializationInfo info, StreamingContext context) + { + if(info == null) + throw new ArgumentNullException(nameof(info)); + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Extents/ExtentsByte.cs b/Aaru.CommonTypes/Extents/ExtentsByte.cs new file mode 100644 index 000000000..a5bad2e09 --- /dev/null +++ b/Aaru.CommonTypes/Extents/ExtentsByte.cs @@ -0,0 +1,254 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ExtentsByte.cs +// Author(s) : Natalia Portillo +// +// Component : Extent helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Provides extents for byte types. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Aaru.CommonTypes.Extents +{ + /// Implements extents for + public class ExtentsByte + { + List> _backend; + + /// Initialize an empty list of extents + public ExtentsByte() => _backend = new List>(); + + /// Initializes extents with an specific list + /// List of extents as tuples "start, end" + public ExtentsByte(IEnumerable> list) + { + _backend = new List>(); + + // This ensure no overlapping extents are added on creation + foreach(Tuple t in list) + Add(t.Item1, t.Item2); + } + + /// Gets a count of how many extents are stored + public int Count => _backend.Count; + + /// Adds the specified number to the corresponding extent, or creates a new one + /// + public void Add(byte item) + { + Tuple removeOne = null; + Tuple removeTwo = null; + Tuple itemToAdd = null; + + for(int i = 0; i < _backend.Count; i++) + { + // Already contained in an extent + if(item >= _backend[i].Item1 && + item <= _backend[i].Item2) + return; + + // Expands existing extent start + if(item == _backend[i].Item1 - 1) + { + removeOne = _backend[i]; + + if(i > 0 && + item == _backend[i - 1].Item2 + 1) + { + removeTwo = _backend[i - 1]; + itemToAdd = new Tuple(_backend[i - 1].Item1, _backend[i].Item2); + } + else + itemToAdd = new Tuple(item, _backend[i].Item2); + + break; + } + + // Expands existing extent end + if(item != _backend[i].Item2 + 1) + continue; + + removeOne = _backend[i]; + + if(i < _backend.Count - 1 && + item == _backend[i + 1].Item1 - 1) + { + removeTwo = _backend[i + 1]; + itemToAdd = new Tuple(_backend[i].Item1, _backend[i + 1].Item2); + } + else + itemToAdd = new Tuple(_backend[i].Item1, item); + + break; + } + + if(itemToAdd != null) + { + _backend.Remove(removeOne); + _backend.Remove(removeTwo); + _backend.Add(itemToAdd); + } + else + _backend.Add(new Tuple(item, item)); + + // Sort + _backend = _backend.OrderBy(t => t.Item1).ToList(); + } + + /// Adds a new extent + /// First element of the extent + /// + /// Last element of the extent or if is true how many elements the extent runs + /// for + /// + /// If set to true, indicates how many elements the extent runs for + public void Add(byte start, byte end, bool run = false) + { + byte realEnd; + + if(run) + realEnd = (byte)(start + end - 1); + else + realEnd = end; + + // TODO: Optimize this + for(byte t = start; t <= realEnd; t++) + Add(t); + } + + /// Checks if the specified item is contained by an extent on this instance + /// Item to search for + /// true if any of the extents on this instance contains the item + public bool Contains(byte item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2); + + /// Removes all extents from this instance + public void Clear() => _backend.Clear(); + + /// Removes an item from the extents in this instance + /// Item to remove + /// true if the item was contained in a known extent and removed, false otherwise + public bool Remove(byte item) + { + Tuple toRemove = null; + Tuple toAddOne = null; + Tuple toAddTwo = null; + + foreach(Tuple extent in _backend) + { + // Extent is contained and not a border + if(item > extent.Item1 && + item < extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(extent.Item1, (byte)(item - 1)); + toAddTwo = new Tuple((byte)(item + 1), extent.Item2); + + break; + } + + // Extent is left border, but not only element + if(item == extent.Item1 && + item != extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple((byte)(item + 1), extent.Item2); + + break; + } + + // Extent is right border, but not only element + if(item != extent.Item1 && + item == extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(extent.Item1, (byte)(item - 1)); + + break; + } + + // Extent is only element + if(item != extent.Item1 || + item != extent.Item2) + continue; + + toRemove = extent; + + break; + } + + // Item not found + if(toRemove == null) + return false; + + _backend.Remove(toRemove); + + if(toAddOne != null) + _backend.Add(toAddOne); + + if(toAddTwo != null) + _backend.Add(toAddTwo); + + // Sort + _backend = _backend.OrderBy(t => t.Item1).ToList(); + + return true; + } + + /// + /// Converts the list of extents to an array of where T1 is first element of the extent and + /// T2 is last element + /// + /// Array of + public Tuple[] ToArray() => _backend.ToArray(); + + /// Gets the first element of the extent that contains the specified item + /// Item + /// First element of extent + /// true if item was found in an extent, false otherwise + public bool GetStart(byte item, out byte start) + { + start = 0; + + foreach(Tuple extent in _backend.Where(extent => item >= extent.Item1 && item <= extent.Item2)) + { + start = extent.Item1; + + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Extents/ExtentsConverter.cs b/Aaru.CommonTypes/Extents/ExtentsConverter.cs new file mode 100644 index 000000000..e1444c61d --- /dev/null +++ b/Aaru.CommonTypes/Extents/ExtentsConverter.cs @@ -0,0 +1,84 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ExtentsConverter.cs +// Author(s) : Natalia Portillo +// +// Component : XML metadata. +// +// --[ Description ] ---------------------------------------------------------- +// +// Converts extents to/from XML. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using Schemas; + +namespace Aaru.CommonTypes.Extents +{ + /// Converts extents + public static class ExtentsConverter + { + /// Converts unsigned long integer extents into XML based extents + /// Extents + /// XML based extents + public static ExtentType[] ToMetadata(ExtentsULong extents) + { + if(extents == null) + return null; + + Tuple[] tuples = extents.ToArray(); + ExtentType[] array = new ExtentType[tuples.Length]; + + for(ulong i = 0; i < (ulong)array.LongLength; i++) + array[i] = new ExtentType + { + Start = tuples[i].Item1, + End = tuples[i].Item2 + }; + + return array; + } + + /// Converts XML based extents into unsigned long integer extents + /// XML based extents + /// Extents + public static ExtentsULong FromMetadata(ExtentType[] extents) + { + if(extents == null) + return null; + + List> tuples = + extents.Select(extent => new Tuple(extent.Start, extent.End)).ToList(); + + return new ExtentsULong(tuples); + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Extents/ExtentsInt.cs b/Aaru.CommonTypes/Extents/ExtentsInt.cs new file mode 100644 index 000000000..acfe6cc2e --- /dev/null +++ b/Aaru.CommonTypes/Extents/ExtentsInt.cs @@ -0,0 +1,254 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ExtentsInt.cs +// Author(s) : Natalia Portillo +// +// Component : Extent helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Provides extents for int types. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Aaru.CommonTypes.Extents +{ + /// Implements extents for + public class ExtentsInt + { + List> _backend; + + /// Initialize an empty list of extents + public ExtentsInt() => _backend = new List>(); + + /// Initializes extents with an specific list + /// List of extents as tuples "start, end" + public ExtentsInt(IEnumerable> list) + { + _backend = new List>(); + + // This ensure no overlapping extents are added on creation + foreach(Tuple t in list) + Add(t.Item1, t.Item2); + } + + /// Gets a count of how many extents are stored + public int Count => _backend.Count; + + /// Adds the specified number to the corresponding extent, or creates a new one + /// + public void Add(int item) + { + Tuple removeOne = null; + Tuple removeTwo = null; + Tuple itemToAdd = null; + + for(int i = 0; i < _backend.Count; i++) + { + // Already contained in an extent + if(item >= _backend[i].Item1 && + item <= _backend[i].Item2) + return; + + // Expands existing extent start + if(item == _backend[i].Item1 - 1) + { + removeOne = _backend[i]; + + if(i > 0 && + item == _backend[i - 1].Item2 + 1) + { + removeTwo = _backend[i - 1]; + itemToAdd = new Tuple(_backend[i - 1].Item1, _backend[i].Item2); + } + else + itemToAdd = new Tuple(item, _backend[i].Item2); + + break; + } + + // Expands existing extent end + if(item != _backend[i].Item2 + 1) + continue; + + removeOne = _backend[i]; + + if(i < _backend.Count - 1 && + item == _backend[i + 1].Item1 - 1) + { + removeTwo = _backend[i + 1]; + itemToAdd = new Tuple(_backend[i].Item1, _backend[i + 1].Item2); + } + else + itemToAdd = new Tuple(_backend[i].Item1, item); + + break; + } + + if(itemToAdd != null) + { + _backend.Remove(removeOne); + _backend.Remove(removeTwo); + _backend.Add(itemToAdd); + } + else + _backend.Add(new Tuple(item, item)); + + // Sort + _backend = _backend.OrderBy(t => t.Item1).ToList(); + } + + /// Adds a new extent + /// First element of the extent + /// + /// Last element of the extent or if is true how many elements the extent runs + /// for + /// + /// If set to true, indicates how many elements the extent runs for + public void Add(int start, int end, bool run = false) + { + int realEnd; + + if(run) + realEnd = start + end - 1; + else + realEnd = end; + + // TODO: Optimize this + for(int t = start; t <= realEnd; t++) + Add(t); + } + + /// Checks if the specified item is contained by an extent on this instance + /// Item to search for + /// true if any of the extents on this instance contains the item + public bool Contains(int item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2); + + /// Removes all extents from this instance + public void Clear() => _backend.Clear(); + + /// Removes an item from the extents in this instance + /// Item to remove + /// true if the item was contained in a known extent and removed, false otherwise + public bool Remove(int item) + { + Tuple toRemove = null; + Tuple toAddOne = null; + Tuple toAddTwo = null; + + foreach(Tuple extent in _backend) + { + // Extent is contained and not a border + if(item > extent.Item1 && + item < extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(extent.Item1, item - 1); + toAddTwo = new Tuple(item + 1, extent.Item2); + + break; + } + + // Extent is left border, but not only element + if(item == extent.Item1 && + item != extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(item + 1, extent.Item2); + + break; + } + + // Extent is right border, but not only element + if(item != extent.Item1 && + item == extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(extent.Item1, item - 1); + + break; + } + + // Extent is only element + if(item != extent.Item1 || + item != extent.Item2) + continue; + + toRemove = extent; + + break; + } + + // Item not found + if(toRemove == null) + return false; + + _backend.Remove(toRemove); + + if(toAddOne != null) + _backend.Add(toAddOne); + + if(toAddTwo != null) + _backend.Add(toAddTwo); + + // Sort + _backend = _backend.OrderBy(t => t.Item1).ToList(); + + return true; + } + + /// + /// Converts the list of extents to an array of where T1 is first element of the extent and + /// T2 is last element + /// + /// Array of + public Tuple[] ToArray() => _backend.ToArray(); + + /// Gets the first element of the extent that contains the specified item + /// Item + /// First element of extent + /// true if item was found in an extent, false otherwise + public bool GetStart(int item, out int start) + { + start = 0; + + foreach(Tuple extent in _backend.Where(extent => item >= extent.Item1 && item <= extent.Item2)) + { + start = extent.Item1; + + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Extents/ExtentsLong.cs b/Aaru.CommonTypes/Extents/ExtentsLong.cs new file mode 100644 index 000000000..7c6ea9d9b --- /dev/null +++ b/Aaru.CommonTypes/Extents/ExtentsLong.cs @@ -0,0 +1,254 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ExtentsLong.cs +// Author(s) : Natalia Portillo +// +// Component : Extent helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Provides extents for long types. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Aaru.CommonTypes.Extents +{ + /// Implements extents for + public class ExtentsLong + { + List> _backend; + + /// Initialize an empty list of extents + public ExtentsLong() => _backend = new List>(); + + /// Initializes extents with an specific list + /// List of extents as tuples "start, end" + public ExtentsLong(IEnumerable> list) + { + _backend = new List>(); + + // This ensure no overlapping extents are added on creation + foreach(Tuple t in list) + Add(t.Item1, t.Item2); + } + + /// Gets a count of how many extents are stored + public int Count => _backend.Count; + + /// Adds the specified number to the corresponding extent, or creates a new one + /// + public void Add(long item) + { + Tuple removeOne = null; + Tuple removeTwo = null; + Tuple itemToAdd = null; + + for(int i = 0; i < _backend.Count; i++) + { + // Already contained in an extent + if(item >= _backend[i].Item1 && + item <= _backend[i].Item2) + return; + + // Expands existing extent start + if(item == _backend[i].Item1 - 1) + { + removeOne = _backend[i]; + + if(i > 0 && + item == _backend[i - 1].Item2 + 1) + { + removeTwo = _backend[i - 1]; + itemToAdd = new Tuple(_backend[i - 1].Item1, _backend[i].Item2); + } + else + itemToAdd = new Tuple(item, _backend[i].Item2); + + break; + } + + // Expands existing extent end + if(item != _backend[i].Item2 + 1) + continue; + + removeOne = _backend[i]; + + if(i < _backend.Count - 1 && + item == _backend[i + 1].Item1 - 1) + { + removeTwo = _backend[i + 1]; + itemToAdd = new Tuple(_backend[i].Item1, _backend[i + 1].Item2); + } + else + itemToAdd = new Tuple(_backend[i].Item1, item); + + break; + } + + if(itemToAdd != null) + { + _backend.Remove(removeOne); + _backend.Remove(removeTwo); + _backend.Add(itemToAdd); + } + else + _backend.Add(new Tuple(item, item)); + + // Sort + _backend = _backend.OrderBy(t => t.Item1).ToList(); + } + + /// Adds a new extent + /// First element of the extent + /// + /// Last element of the extent or if is true how many elements the extent runs + /// for + /// + /// If set to true, indicates how many elements the extent runs for + public void Add(long start, long end, bool run = false) + { + long realEnd; + + if(run) + realEnd = start + end - 1; + else + realEnd = end; + + // TODO: Optimize this + for(long t = start; t <= realEnd; t++) + Add(t); + } + + /// Checks if the specified item is contained by an extent on this instance + /// Item to search for + /// true if any of the extents on this instance contains the item + public bool Contains(long item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2); + + /// Removes all extents from this instance + public void Clear() => _backend.Clear(); + + /// Removes an item from the extents in this instance + /// Item to remove + /// true if the item was contained in a known extent and removed, false otherwise + public bool Remove(long item) + { + Tuple toRemove = null; + Tuple toAddOne = null; + Tuple toAddTwo = null; + + foreach(Tuple extent in _backend) + { + // Extent is contained and not a border + if(item > extent.Item1 && + item < extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(extent.Item1, item - 1); + toAddTwo = new Tuple(item + 1, extent.Item2); + + break; + } + + // Extent is left border, but not only element + if(item == extent.Item1 && + item != extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(item + 1, extent.Item2); + + break; + } + + // Extent is right border, but not only element + if(item != extent.Item1 && + item == extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(extent.Item1, item - 1); + + break; + } + + // Extent is only element + if(item != extent.Item1 || + item != extent.Item2) + continue; + + toRemove = extent; + + break; + } + + // Item not found + if(toRemove == null) + return false; + + _backend.Remove(toRemove); + + if(toAddOne != null) + _backend.Add(toAddOne); + + if(toAddTwo != null) + _backend.Add(toAddTwo); + + // Sort + _backend = _backend.OrderBy(t => t.Item1).ToList(); + + return true; + } + + /// + /// Converts the list of extents to an array of where T1 is first element of the extent and + /// T2 is last element + /// + /// Array of + public Tuple[] ToArray() => _backend.ToArray(); + + /// Gets the first element of the extent that contains the specified item + /// Item + /// First element of extent + /// true if item was found in an extent, false otherwise + public bool GetStart(long item, out long start) + { + start = 0; + + foreach(Tuple extent in _backend.Where(extent => item >= extent.Item1 && item <= extent.Item2)) + { + start = extent.Item1; + + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Extents/ExtentsSByte.cs b/Aaru.CommonTypes/Extents/ExtentsSByte.cs new file mode 100644 index 000000000..66965fad6 --- /dev/null +++ b/Aaru.CommonTypes/Extents/ExtentsSByte.cs @@ -0,0 +1,255 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ExtentsSByte.cs +// Author(s) : Natalia Portillo +// +// Component : Extent helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Provides extents for sbyte types. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Aaru.CommonTypes.Extents +{ + /// Implements extents for + public class ExtentsSByte + { + List> _backend; + + /// Initialize an empty list of extents + public ExtentsSByte() => _backend = new List>(); + + /// Initializes extents with an specific list + /// List of extents as tuples "start, end" + public ExtentsSByte(IEnumerable> list) + { + _backend = new List>(); + + // This ensure no overlapping extents are added on creation + foreach(Tuple t in list) + Add(t.Item1, t.Item2); + } + + /// Gets a count of how many extents are stored + public int Count => _backend.Count; + + /// Adds the specified number to the corresponding extent, or creates a new one + /// + public void Add(sbyte item) + { + Tuple removeOne = null; + Tuple removeTwo = null; + Tuple itemToAdd = null; + + for(int i = 0; i < _backend.Count; i++) + { + // Already contained in an extent + if(item >= _backend[i].Item1 && + item <= _backend[i].Item2) + return; + + // Expands existing extent start + if(item == _backend[i].Item1 - 1) + { + removeOne = _backend[i]; + + if(i > 0 && + item == _backend[i - 1].Item2 + 1) + { + removeTwo = _backend[i - 1]; + itemToAdd = new Tuple(_backend[i - 1].Item1, _backend[i].Item2); + } + else + itemToAdd = new Tuple(item, _backend[i].Item2); + + break; + } + + // Expands existing extent end + if(item != _backend[i].Item2 + 1) + continue; + + removeOne = _backend[i]; + + if(i < _backend.Count - 1 && + item == _backend[i + 1].Item1 - 1) + { + removeTwo = _backend[i + 1]; + itemToAdd = new Tuple(_backend[i].Item1, _backend[i + 1].Item2); + } + else + itemToAdd = new Tuple(_backend[i].Item1, item); + + break; + } + + if(itemToAdd != null) + { + _backend.Remove(removeOne); + _backend.Remove(removeTwo); + _backend.Add(itemToAdd); + } + else + _backend.Add(new Tuple(item, item)); + + // Sort + _backend = _backend.OrderBy(t => t.Item1).ToList(); + } + + /// Adds a new extent + /// First element of the extent + /// + /// Last element of the extent or if is true how many elements the extent runs + /// for + /// + /// If set to true, indicates how many elements the extent runs for + public void Add(sbyte start, sbyte end, bool run = false) + { + sbyte realEnd; + + if(run) + realEnd = (sbyte)(start + end - 1); + else + realEnd = end; + + // TODO: Optimize this + for(sbyte t = start; t <= realEnd; t++) + Add(t); + } + + /// Checks if the specified item is contained by an extent on this instance + /// Item to search for + /// true if any of the extents on this instance contains the item + public bool Contains(sbyte item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2); + + /// Removes all extents from this instance + public void Clear() => _backend.Clear(); + + /// Removes an item from the extents in this instance + /// Item to remove + /// true if the item was contained in a known extent and removed, false otherwise + public bool Remove(sbyte item) + { + Tuple toRemove = null; + Tuple toAddOne = null; + Tuple toAddTwo = null; + + foreach(Tuple extent in _backend) + { + // Extent is contained and not a border + if(item > extent.Item1 && + item < extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(extent.Item1, (sbyte)(item - 1)); + toAddTwo = new Tuple((sbyte)(item + 1), extent.Item2); + + break; + } + + // Extent is left border, but not only element + if(item == extent.Item1 && + item != extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple((sbyte)(item + 1), extent.Item2); + + break; + } + + // Extent is right border, but not only element + if(item != extent.Item1 && + item == extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(extent.Item1, (sbyte)(item - 1)); + + break; + } + + // Extent is only element + if(item != extent.Item1 || + item != extent.Item2) + continue; + + toRemove = extent; + + break; + } + + // Item not found + if(toRemove == null) + return false; + + _backend.Remove(toRemove); + + if(toAddOne != null) + _backend.Add(toAddOne); + + if(toAddTwo != null) + _backend.Add(toAddTwo); + + // Sort + _backend = _backend.OrderBy(t => t.Item1).ToList(); + + return true; + } + + /// + /// Converts the list of extents to an array of where T1 is first element of the extent and + /// T2 is last element + /// + /// Array of + public Tuple[] ToArray() => _backend.ToArray(); + + /// Gets the first element of the extent that contains the specified item + /// Item + /// First element of extent + /// true if item was found in an extent, false otherwise + public bool GetStart(sbyte item, out sbyte start) + { + start = 0; + + foreach(Tuple extent in + _backend.Where(extent => item >= extent.Item1 && item <= extent.Item2)) + { + start = extent.Item1; + + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Extents/ExtentsShort.cs b/Aaru.CommonTypes/Extents/ExtentsShort.cs new file mode 100644 index 000000000..8663e6bf1 --- /dev/null +++ b/Aaru.CommonTypes/Extents/ExtentsShort.cs @@ -0,0 +1,255 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ExtentsShort.cs +// Author(s) : Natalia Portillo +// +// Component : Extent helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Provides extents for short types. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Aaru.CommonTypes.Extents +{ + /// Implements extents for + public class ExtentsShort + { + List> _backend; + + /// Initialize an empty list of extents + public ExtentsShort() => _backend = new List>(); + + /// Initializes extents with an specific list + /// List of extents as tuples "start, end" + public ExtentsShort(IEnumerable> list) + { + _backend = new List>(); + + // This ensure no overlapping extents are added on creation + foreach(Tuple t in list) + Add(t.Item1, t.Item2); + } + + /// Gets a count of how many extents are stored + public int Count => _backend.Count; + + /// Adds the specified number to the corresponding extent, or creates a new one + /// + public void Add(short item) + { + Tuple removeOne = null; + Tuple removeTwo = null; + Tuple itemToAdd = null; + + for(int i = 0; i < _backend.Count; i++) + { + // Already contained in an extent + if(item >= _backend[i].Item1 && + item <= _backend[i].Item2) + return; + + // Expands existing extent start + if(item == _backend[i].Item1 - 1) + { + removeOne = _backend[i]; + + if(i > 0 && + item == _backend[i - 1].Item2 + 1) + { + removeTwo = _backend[i - 1]; + itemToAdd = new Tuple(_backend[i - 1].Item1, _backend[i].Item2); + } + else + itemToAdd = new Tuple(item, _backend[i].Item2); + + break; + } + + // Expands existing extent end + if(item != _backend[i].Item2 + 1) + continue; + + removeOne = _backend[i]; + + if(i < _backend.Count - 1 && + item == _backend[i + 1].Item1 - 1) + { + removeTwo = _backend[i + 1]; + itemToAdd = new Tuple(_backend[i].Item1, _backend[i + 1].Item2); + } + else + itemToAdd = new Tuple(_backend[i].Item1, item); + + break; + } + + if(itemToAdd != null) + { + _backend.Remove(removeOne); + _backend.Remove(removeTwo); + _backend.Add(itemToAdd); + } + else + _backend.Add(new Tuple(item, item)); + + // Sort + _backend = _backend.OrderBy(t => t.Item1).ToList(); + } + + /// Adds a new extent + /// First element of the extent + /// + /// Last element of the extent or if is true how many elements the extent runs + /// for + /// + /// If set to true, indicates how many elements the extent runs for + public void Add(short start, short end, bool run = false) + { + short realEnd; + + if(run) + realEnd = (short)(start + end - 1); + else + realEnd = end; + + // TODO: Optimize this + for(short t = start; t <= realEnd; t++) + Add(t); + } + + /// Checks if the specified item is contained by an extent on this instance + /// Item to search for + /// true if any of the extents on this instance contains the item + public bool Contains(short item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2); + + /// Removes all extents from this instance + public void Clear() => _backend.Clear(); + + /// Removes an item from the extents in this instance + /// Item to remove + /// true if the item was contained in a known extent and removed, false otherwise + public bool Remove(short item) + { + Tuple toRemove = null; + Tuple toAddOne = null; + Tuple toAddTwo = null; + + foreach(Tuple extent in _backend) + { + // Extent is contained and not a border + if(item > extent.Item1 && + item < extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(extent.Item1, (short)(item - 1)); + toAddTwo = new Tuple((short)(item + 1), extent.Item2); + + break; + } + + // Extent is left border, but not only element + if(item == extent.Item1 && + item != extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple((short)(item + 1), extent.Item2); + + break; + } + + // Extent is right border, but not only element + if(item != extent.Item1 && + item == extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(extent.Item1, (short)(item - 1)); + + break; + } + + // Extent is only element + if(item != extent.Item1 || + item != extent.Item2) + continue; + + toRemove = extent; + + break; + } + + // Item not found + if(toRemove == null) + return false; + + _backend.Remove(toRemove); + + if(toAddOne != null) + _backend.Add(toAddOne); + + if(toAddTwo != null) + _backend.Add(toAddTwo); + + // Sort + _backend = _backend.OrderBy(t => t.Item1).ToList(); + + return true; + } + + /// + /// Converts the list of extents to an array of where T1 is first element of the extent and + /// T2 is last element + /// + /// Array of + public Tuple[] ToArray() => _backend.ToArray(); + + /// Gets the first element of the extent that contains the specified item + /// Item + /// First element of extent + /// true if item was found in an extent, false otherwise + public bool GetStart(short item, out short start) + { + start = 0; + + foreach(Tuple extent in + _backend.Where(extent => item >= extent.Item1 && item <= extent.Item2)) + { + start = extent.Item1; + + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Extents/ExtentsUInt.cs b/Aaru.CommonTypes/Extents/ExtentsUInt.cs new file mode 100644 index 000000000..1bd62147e --- /dev/null +++ b/Aaru.CommonTypes/Extents/ExtentsUInt.cs @@ -0,0 +1,254 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ExtentsUInt.cs +// Author(s) : Natalia Portillo +// +// Component : Extent helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Provides extents for uint types. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Aaru.CommonTypes.Extents +{ + /// Implements extents for + public class ExtentsUInt + { + List> _backend; + + /// Initialize an empty list of extents + public ExtentsUInt() => _backend = new List>(); + + /// Initializes extents with an specific list + /// List of extents as tuples "start, end" + public ExtentsUInt(IEnumerable> list) + { + _backend = new List>(); + + // This ensure no overlapping extents are added on creation + foreach(Tuple t in list) + Add(t.Item1, t.Item2); + } + + /// Gets a count of how many extents are stored + public int Count => _backend.Count; + + /// Adds the specified number to the corresponding extent, or creates a new one + /// + public void Add(uint item) + { + Tuple removeOne = null; + Tuple removeTwo = null; + Tuple itemToAdd = null; + + for(int i = 0; i < _backend.Count; i++) + { + // Already contained in an extent + if(item >= _backend[i].Item1 && + item <= _backend[i].Item2) + return; + + // Expands existing extent start + if(item == _backend[i].Item1 - 1) + { + removeOne = _backend[i]; + + if(i > 0 && + item == _backend[i - 1].Item2 + 1) + { + removeTwo = _backend[i - 1]; + itemToAdd = new Tuple(_backend[i - 1].Item1, _backend[i].Item2); + } + else + itemToAdd = new Tuple(item, _backend[i].Item2); + + break; + } + + // Expands existing extent end + if(item != _backend[i].Item2 + 1) + continue; + + removeOne = _backend[i]; + + if(i < _backend.Count - 1 && + item == _backend[i + 1].Item1 - 1) + { + removeTwo = _backend[i + 1]; + itemToAdd = new Tuple(_backend[i].Item1, _backend[i + 1].Item2); + } + else + itemToAdd = new Tuple(_backend[i].Item1, item); + + break; + } + + if(itemToAdd != null) + { + _backend.Remove(removeOne); + _backend.Remove(removeTwo); + _backend.Add(itemToAdd); + } + else + _backend.Add(new Tuple(item, item)); + + // Sort + _backend = _backend.OrderBy(t => t.Item1).ToList(); + } + + /// Adds a new extent + /// First element of the extent + /// + /// Last element of the extent or if is true how many elements the extent runs + /// for + /// + /// If set to true, indicates how many elements the extent runs for + public void Add(uint start, uint end, bool run = false) + { + uint realEnd; + + if(run) + realEnd = start + end - 1; + else + realEnd = end; + + // TODO: Optimize this + for(uint t = start; t <= realEnd; t++) + Add(t); + } + + /// Checks if the specified item is contained by an extent on this instance + /// Item to search for + /// true if any of the extents on this instance contains the item + public bool Contains(uint item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2); + + /// Removes all extents from this instance + public void Clear() => _backend.Clear(); + + /// Removes an item from the extents in this instance + /// Item to remove + /// true if the item was contained in a known extent and removed, false otherwise + public bool Remove(uint item) + { + Tuple toRemove = null; + Tuple toAddOne = null; + Tuple toAddTwo = null; + + foreach(Tuple extent in _backend) + { + // Extent is contained and not a border + if(item > extent.Item1 && + item < extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(extent.Item1, item - 1); + toAddTwo = new Tuple(item + 1, extent.Item2); + + break; + } + + // Extent is left border, but not only element + if(item == extent.Item1 && + item != extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(item + 1, extent.Item2); + + break; + } + + // Extent is right border, but not only element + if(item != extent.Item1 && + item == extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(extent.Item1, item - 1); + + break; + } + + // Extent is only element + if(item != extent.Item1 || + item != extent.Item2) + continue; + + toRemove = extent; + + break; + } + + // Item not found + if(toRemove == null) + return false; + + _backend.Remove(toRemove); + + if(toAddOne != null) + _backend.Add(toAddOne); + + if(toAddTwo != null) + _backend.Add(toAddTwo); + + // Sort + _backend = _backend.OrderBy(t => t.Item1).ToList(); + + return true; + } + + /// + /// Converts the list of extents to an array of where T1 is first element of the extent and + /// T2 is last element + /// + /// Array of + public Tuple[] ToArray() => _backend.ToArray(); + + /// Gets the first element of the extent that contains the specified item + /// Item + /// First element of extent + /// true if item was found in an extent, false otherwise + public bool GetStart(uint item, out uint start) + { + start = 0; + + foreach(Tuple extent in _backend.Where(extent => item >= extent.Item1 && item <= extent.Item2)) + { + start = extent.Item1; + + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Extents/ExtentsULong.cs b/Aaru.CommonTypes/Extents/ExtentsULong.cs new file mode 100644 index 000000000..3c79883dc --- /dev/null +++ b/Aaru.CommonTypes/Extents/ExtentsULong.cs @@ -0,0 +1,255 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ExtentsULong.cs +// Author(s) : Natalia Portillo +// +// Component : Extent helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Provides extents for ulong types. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Aaru.CommonTypes.Extents +{ + /// Implements extents for + public class ExtentsULong + { + List> _backend; + + /// Initialize an empty list of extents + public ExtentsULong() => _backend = new List>(); + + /// Initializes extents with an specific list + /// List of extents as tuples "start, end" + public ExtentsULong(IEnumerable> list) + { + _backend = new List>(); + + // This ensure no overlapping extents are added on creation + foreach(Tuple t in list) + Add(t.Item1, t.Item2); + } + + /// Gets a count of how many extents are stored + public int Count => _backend.Count; + + /// Adds the specified number to the corresponding extent, or creates a new one + /// + public void Add(ulong item) + { + Tuple removeOne = null; + Tuple removeTwo = null; + Tuple itemToAdd = null; + + for(int i = 0; i < _backend.Count; i++) + { + // Already contained in an extent + if(item >= _backend[i].Item1 && + item <= _backend[i].Item2) + return; + + // Expands existing extent start + if(item == _backend[i].Item1 - 1) + { + removeOne = _backend[i]; + + if(i > 0 && + item == _backend[i - 1].Item2 + 1) + { + removeTwo = _backend[i - 1]; + itemToAdd = new Tuple(_backend[i - 1].Item1, _backend[i].Item2); + } + else + itemToAdd = new Tuple(item, _backend[i].Item2); + + break; + } + + // Expands existing extent end + if(item != _backend[i].Item2 + 1) + continue; + + removeOne = _backend[i]; + + if(i < _backend.Count - 1 && + item == _backend[i + 1].Item1 - 1) + { + removeTwo = _backend[i + 1]; + itemToAdd = new Tuple(_backend[i].Item1, _backend[i + 1].Item2); + } + else + itemToAdd = new Tuple(_backend[i].Item1, item); + + break; + } + + if(itemToAdd != null) + { + _backend.Remove(removeOne); + _backend.Remove(removeTwo); + _backend.Add(itemToAdd); + } + else + _backend.Add(new Tuple(item, item)); + + // Sort + _backend = _backend.OrderBy(t => t.Item1).ToList(); + } + + /// Adds a new extent + /// First element of the extent + /// + /// Last element of the extent or if is true how many elements the extent runs + /// for + /// + /// If set to true, indicates how many elements the extent runs for + public void Add(ulong start, ulong end, bool run = false) + { + ulong realEnd; + + if(run) + realEnd = start + end - 1; + else + realEnd = end; + + // TODO: Optimize this + for(ulong t = start; t <= realEnd; t++) + Add(t); + } + + /// Checks if the specified item is contained by an extent on this instance + /// Item to search for + /// true if any of the extents on this instance contains the item + public bool Contains(ulong item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2); + + /// Removes all extents from this instance + public void Clear() => _backend.Clear(); + + /// Removes an item from the extents in this instance + /// Item to remove + /// true if the item was contained in a known extent and removed, false otherwise + public bool Remove(ulong item) + { + Tuple toRemove = null; + Tuple toAddOne = null; + Tuple toAddTwo = null; + + foreach(Tuple extent in _backend) + { + // Extent is contained and not a border + if(item > extent.Item1 && + item < extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(extent.Item1, item - 1); + toAddTwo = new Tuple(item + 1, extent.Item2); + + break; + } + + // Extent is left border, but not only element + if(item == extent.Item1 && + item != extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(item + 1, extent.Item2); + + break; + } + + // Extent is right border, but not only element + if(item != extent.Item1 && + item == extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(extent.Item1, item - 1); + + break; + } + + // Extent is only element + if(item != extent.Item1 || + item != extent.Item2) + continue; + + toRemove = extent; + + break; + } + + // Item not found + if(toRemove == null) + return false; + + _backend.Remove(toRemove); + + if(toAddOne != null) + _backend.Add(toAddOne); + + if(toAddTwo != null) + _backend.Add(toAddTwo); + + // Sort + _backend = _backend.OrderBy(t => t.Item1).ToList(); + + return true; + } + + /// + /// Converts the list of extents to an array of where T1 is first element of the extent and + /// T2 is last element + /// + /// Array of + public Tuple[] ToArray() => _backend.ToArray(); + + /// Gets the first element of the extent that contains the specified item + /// Item + /// First element of extent + /// true if item was found in an extent, false otherwise + public bool GetStart(ulong item, out ulong start) + { + start = 0; + + foreach(Tuple extent in + _backend.Where(extent => item >= extent.Item1 && item <= extent.Item2)) + { + start = extent.Item1; + + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Extents/ExtentsUShort.cs b/Aaru.CommonTypes/Extents/ExtentsUShort.cs new file mode 100644 index 000000000..c8d09bd87 --- /dev/null +++ b/Aaru.CommonTypes/Extents/ExtentsUShort.cs @@ -0,0 +1,255 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ExtentsUShort.cs +// Author(s) : Natalia Portillo +// +// Component : Extent helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Provides extents for ushort types. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Aaru.CommonTypes.Extents +{ + /// Implements extents for + public class ExtentsUShort + { + List> _backend; + + /// Initialize an empty list of extents + public ExtentsUShort() => _backend = new List>(); + + /// Initializes extents with an specific list + /// List of extents as tuples "start, end" + public ExtentsUShort(IEnumerable> list) + { + _backend = new List>(); + + // This ensure no overlapping extents are added on creation + foreach(Tuple t in list) + Add(t.Item1, t.Item2); + } + + /// Gets a count of how many extents are stored + public int Count => _backend.Count; + + /// Adds the specified number to the corresponding extent, or creates a new one + /// + public void Add(ushort item) + { + Tuple removeOne = null; + Tuple removeTwo = null; + Tuple itemToAdd = null; + + for(int i = 0; i < _backend.Count; i++) + { + // Already contained in an extent + if(item >= _backend[i].Item1 && + item <= _backend[i].Item2) + return; + + // Expands existing extent start + if(item == _backend[i].Item1 - 1) + { + removeOne = _backend[i]; + + if(i > 0 && + item == _backend[i - 1].Item2 + 1) + { + removeTwo = _backend[i - 1]; + itemToAdd = new Tuple(_backend[i - 1].Item1, _backend[i].Item2); + } + else + itemToAdd = new Tuple(item, _backend[i].Item2); + + break; + } + + // Expands existing extent end + if(item != _backend[i].Item2 + 1) + continue; + + removeOne = _backend[i]; + + if(i < _backend.Count - 1 && + item == _backend[i + 1].Item1 - 1) + { + removeTwo = _backend[i + 1]; + itemToAdd = new Tuple(_backend[i].Item1, _backend[i + 1].Item2); + } + else + itemToAdd = new Tuple(_backend[i].Item1, item); + + break; + } + + if(itemToAdd != null) + { + _backend.Remove(removeOne); + _backend.Remove(removeTwo); + _backend.Add(itemToAdd); + } + else + _backend.Add(new Tuple(item, item)); + + // Sort + _backend = _backend.OrderBy(t => t.Item1).ToList(); + } + + /// Adds a new extent + /// First element of the extent + /// + /// Last element of the extent or if is true how many elements the extent runs + /// for + /// + /// If set to true, indicates how many elements the extent runs for + public void Add(ushort start, ushort end, bool run = false) + { + ushort realEnd; + + if(run) + realEnd = (ushort)(start + end - 1); + else + realEnd = end; + + // TODO: Optimize this + for(ushort t = start; t <= realEnd; t++) + Add(t); + } + + /// Checks if the specified item is contained by an extent on this instance + /// Item to search for + /// true if any of the extents on this instance contains the item + public bool Contains(ushort item) => _backend.Any(extent => item >= extent.Item1 && item <= extent.Item2); + + /// Removes all extents from this instance + public void Clear() => _backend.Clear(); + + /// Removes an item from the extents in this instance + /// Item to remove + /// true if the item was contained in a known extent and removed, false otherwise + public bool Remove(ushort item) + { + Tuple toRemove = null; + Tuple toAddOne = null; + Tuple toAddTwo = null; + + foreach(Tuple extent in _backend) + { + // Extent is contained and not a border + if(item > extent.Item1 && + item < extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(extent.Item1, (ushort)(item - 1)); + toAddTwo = new Tuple((ushort)(item + 1), extent.Item2); + + break; + } + + // Extent is left border, but not only element + if(item == extent.Item1 && + item != extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple((ushort)(item + 1), extent.Item2); + + break; + } + + // Extent is right border, but not only element + if(item != extent.Item1 && + item == extent.Item2) + { + toRemove = extent; + toAddOne = new Tuple(extent.Item1, (ushort)(item - 1)); + + break; + } + + // Extent is only element + if(item != extent.Item1 || + item != extent.Item2) + continue; + + toRemove = extent; + + break; + } + + // Item not found + if(toRemove == null) + return false; + + _backend.Remove(toRemove); + + if(toAddOne != null) + _backend.Add(toAddOne); + + if(toAddTwo != null) + _backend.Add(toAddTwo); + + // Sort + _backend = _backend.OrderBy(t => t.Item1).ToList(); + + return true; + } + + /// + /// Converts the list of extents to an array of where T1 is first element of the extent and + /// T2 is last element + /// + /// Array of + public Tuple[] ToArray() => _backend.ToArray(); + + /// Gets the first element of the extent that contains the specified item + /// Item + /// First element of extent + /// true if item was found in an extent, false otherwise + public bool GetStart(ushort item, out ushort start) + { + start = 0; + + foreach(Tuple extent in _backend.Where(extent => item >= extent.Item1 && + item <= extent.Item2)) + { + start = extent.Item1; + + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Filters.cs b/Aaru.CommonTypes/Filters.cs new file mode 100644 index 000000000..737239a7a --- /dev/null +++ b/Aaru.CommonTypes/Filters.cs @@ -0,0 +1,118 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Filters.cs +// Author(s) : Natalia Portillo +// +// Component : Filters. +// +// --[ Description ] ---------------------------------------------------------- +// +// Enumerates all filters and instantiates the correct one. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using Aaru.CommonTypes.Interfaces; +using Aaru.Console; + +namespace Aaru.CommonTypes +{ + /// Manages the known filters + public sealed class FiltersList + { + /// List of known filters + public readonly SortedDictionary Filters; + + /// Fills the list of all known filters + public FiltersList() + { + var assembly = Assembly.Load("Aaru.Filters"); + Filters = new SortedDictionary(); + + foreach(Type type in assembly.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IFilter)))) + try + { + var filter = (IFilter)type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] + {}); + + if(filter != null && + !Filters.ContainsKey(filter.Name.ToLower())) + Filters.Add(filter.Name.ToLower(), filter); + } + catch(Exception exception) + { + AaruConsole.ErrorWriteLine("Exception {0}", exception); + } + } + + /// Gets the filter that allows to read the specified path + /// Path + /// The filter that allows reading the specified path + public IFilter GetFilter(string path) + { + IFilter noFilter = null; + + foreach(IFilter filter in Filters.Values) + { + try + { + if(filter.Id != new Guid("12345678-AAAA-BBBB-CCCC-123456789000")) + { + if(!filter.Identify(path)) + continue; + + var foundFilter = (IFilter)filter.GetType().GetConstructor(Type.EmptyTypes)?.Invoke(new object[] + {}); + + foundFilter?.Open(path); + + if(foundFilter?.IsOpened() == true) + return foundFilter; + } + else + noFilter = filter; + } + catch(IOException) + { + // Ignore and continue + } + } + + if(!noFilter?.Identify(path) == true) + return null; + + noFilter?.Open(path); + + return noFilter; + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Geometry.cs b/Aaru.CommonTypes/Geometry.cs new file mode 100644 index 000000000..bf6537cc6 --- /dev/null +++ b/Aaru.CommonTypes/Geometry.cs @@ -0,0 +1,145 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Geometry.cs +// Author(s) : Natalia Portillo +// +// Component : CommonTypes. +// +// --[ Description ] ---------------------------------------------------------- +// +// Includes geometry for several medias. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Linq; + +namespace Aaru.CommonTypes +{ + /// Handles CHS geometries + public static class Geometry + { + /// List of known disk geometries + public static readonly (ushort cylinders, byte heads, ushort sectorsPerTrack, uint bytesPerSector, MediaEncoding + encoding, bool variableSectorsPerTrack, MediaType type)[] KnownGeometries = + { + (32, 1, 8, 319, MediaEncoding.FM, false, MediaType.IBM23FD), + (35, 1, 9, 256, MediaEncoding.FM, false, MediaType.ECMA_66), + (35, 1, 13, 256, MediaEncoding.AppleGCR, false, MediaType.Apple32SS), + (35, 1, 16, 256, MediaEncoding.MFM, false, MediaType.MetaFloppy_Mod_I), + (35, 1, 16, 256, MediaEncoding.AppleGCR, false, MediaType.Apple33SS), + (35, 1, 19, 256, MediaEncoding.CommodoreGCR, false, MediaType.CBM_1540), + (35, 2, 13, 256, MediaEncoding.AppleGCR, false, MediaType.Apple32DS), + (35, 2, 16, 256, MediaEncoding.AppleGCR, false, MediaType.Apple33DS), + (35, 2, 19, 256, MediaEncoding.CommodoreGCR, false, MediaType.CBM_1571), + (40, 1, 8, 512, MediaEncoding.MFM, false, MediaType.DOS_525_SS_DD_8), + (40, 1, 9, 512, MediaEncoding.MFM, false, MediaType.DOS_525_SS_DD_9), + (40, 1, 10, 256, MediaEncoding.FM, false, MediaType.ACORN_525_SS_SD_40), + (40, 1, 16, 256, MediaEncoding.MFM, false, MediaType.ACORN_525_SS_DD_40), + (40, 1, 18, 128, MediaEncoding.FM, false, MediaType.ATARI_525_SD), + (40, 1, 18, 256, MediaEncoding.MFM, false, MediaType.ATARI_525_DD), + (40, 1, 19, 256, MediaEncoding.CommodoreGCR, false, MediaType.CBM_1540_Ext), + (40, 1, 26, 128, MediaEncoding.MFM, false, MediaType.ATARI_525_ED), + (40, 2, 8, 512, MediaEncoding.MFM, false, MediaType.DOS_525_DS_DD_8), + (40, 2, 9, 512, MediaEncoding.MFM, false, MediaType.DOS_525_DS_DD_9), + (40, 2, 16, 256, MediaEncoding.FM, false, MediaType.ECMA_70), + (70, 2, 9, 512, MediaEncoding.MFM, false, MediaType.Apricot_35), + (74, 1, 8, 512, MediaEncoding.FM, false, MediaType.IBM33FD_512), + (74, 1, 15, 256, MediaEncoding.FM, false, MediaType.IBM33FD_256), + (74, 1, 26, 128, MediaEncoding.FM, false, MediaType.IBM33FD_128), + (74, 2, 8, 1024, MediaEncoding.MFM, false, MediaType.IBM53FD_1024), + (74, 2, 15, 256, MediaEncoding.FM, false, MediaType.IBM43FD_256), + (74, 2, 15, 512, MediaEncoding.MFM, false, MediaType.IBM53FD_512), + (74, 2, 26, 128, MediaEncoding.FM, false, MediaType.IBM43FD_128), + (74, 2, 26, 256, MediaEncoding.MFM, false, MediaType.IBM53FD_256), + (77, 1, 16, 256, MediaEncoding.MFM, false, MediaType.MetaFloppy_Mod_II), + (77, 1, 26, 128, MediaEncoding.FM, false, MediaType.RX01), + (77, 1, 26, 256, MediaEncoding.MFM, false, MediaType.RX02), + (77, 2, 8, 1024, MediaEncoding.MFM, false, MediaType.NEC_525_HD), + (77, 2, 15, 512, MediaEncoding.MFM, false, MediaType.ECMA_99_15), + (77, 2, 26, 128, MediaEncoding.FM, false, MediaType.NEC_8_SD), + (77, 2, 26, 256, MediaEncoding.MFM, false, MediaType.RX03), + (80, 1, 8, 512, MediaEncoding.MFM, false, MediaType.DOS_35_SS_DD_8), + (80, 1, 9, 512, MediaEncoding.MFM, false, MediaType.DOS_35_SS_DD_9), + (80, 1, 10, 256, MediaEncoding.FM, false, MediaType.ACORN_525_SS_SD_80), + (80, 1, 10, 512, MediaEncoding.AppleGCR, true, MediaType.AppleSonySS), + (80, 1, 10, 512, MediaEncoding.MFM, false, MediaType.RX50), + (80, 1, 11, 512, MediaEncoding.MFM, false, MediaType.ATARI_35_SS_DD_11), + (80, 1, 16, 256, MediaEncoding.MFM, false, MediaType.ACORN_525_SS_DD_80), + (80, 2, 5, 1024, MediaEncoding.MFM, false, MediaType.ACORN_35_DS_DD), + (80, 2, 8, 512, MediaEncoding.MFM, false, MediaType.DOS_35_DS_DD_8), + (80, 2, 9, 512, MediaEncoding.MFM, false, MediaType.DOS_35_DS_DD_9), + (80, 2, 10, 512, MediaEncoding.AppleGCR, true, MediaType.AppleSonyDS), + (80, 2, 10, 512, MediaEncoding.MFM, false, MediaType.CBM_35_DD), + (80, 2, 10, 1024, MediaEncoding.MFM, false, MediaType.ACORN_35_DS_HD), + (80, 2, 11, 512, MediaEncoding.MFM, false, MediaType.CBM_AMIGA_35_DD), + (80, 2, 15, 512, MediaEncoding.MFM, false, MediaType.DOS_525_HD), + (80, 2, 16, 256, MediaEncoding.FM, false, MediaType.ECMA_78), + (80, 2, 16, 256, MediaEncoding.MFM, false, MediaType.ACORN_525_DS_DD), + (80, 2, 18, 512, MediaEncoding.MFM, false, MediaType.DOS_35_HD), + (80, 2, 19, 512, MediaEncoding.MFM, false, MediaType.XDF_525), + (80, 2, 21, 512, MediaEncoding.MFM, false, MediaType.DMF), + (80, 2, 22, 512, MediaEncoding.MFM, false, MediaType.CBM_AMIGA_35_HD), + (80, 2, 23, 512, MediaEncoding.MFM, false, MediaType.XDF_35), + (80, 2, 36, 512, MediaEncoding.MFM, false, MediaType.DOS_35_ED), + (82, 2, 10, 512, MediaEncoding.MFM, false, MediaType.FDFORMAT_35_DD), + (82, 2, 17, 512, MediaEncoding.MFM, false, MediaType.FDFORMAT_525_HD), + (82, 2, 21, 512, MediaEncoding.MFM, false, MediaType.FDFORMAT_35_HD), + (240, 2, 38, 512, MediaEncoding.MFM, false, MediaType.NEC_35_TD), + (753, 2, 27, 512, MediaEncoding.MFM, false, MediaType.Floptical), + + // Following ones are what the device itself report, not the physical geometry + (154, 16, 32, 512, MediaEncoding.MFM, false, MediaType.PocketZip), + (262, 32, 56, 512, MediaEncoding.MFM, false, MediaType.LS240), + (963, 8, 32, 512, MediaEncoding.MFM, false, MediaType.LS120), + (1021, 64, 32, 512, MediaEncoding.MFM, false, MediaType.Jaz), + (1024, 2, 32, 512, MediaEncoding.MFM, false, MediaType.FD32MB) + }; + + /// Gets the media type for a given geometry + /// Geometry + /// Media type + public static MediaType GetMediaType( + (ushort cylinders, byte heads, ushort sectorsPerTrack, uint bytesPerSector, MediaEncoding encoding, bool + variableSectorsPerTrack) geometry) => (from geom in KnownGeometries + where geom.cylinders == geometry.cylinders && + geom.heads == geometry.heads && + geom.sectorsPerTrack == geometry.sectorsPerTrack && + geom.bytesPerSector == geometry.bytesPerSector && + geom.encoding == geometry.encoding && + geom.variableSectorsPerTrack == + geometry.variableSectorsPerTrack select geom.type). + FirstOrDefault(); + + /// Gets the geometry for a given media type + /// Media type + /// Geometry + public static (ushort cylinders, byte heads, ushort sectorsPerTrack, uint bytesPerSector, MediaEncoding encoding + , bool variableSectorsPerTrack, MediaType type) GetGeometry(MediaType mediaType) => + (from geom in KnownGeometries where geom.type == mediaType select geom).FirstOrDefault(); + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interfaces/IChecksum.cs b/Aaru.CommonTypes/Interfaces/IChecksum.cs new file mode 100644 index 000000000..1ee7dff02 --- /dev/null +++ b/Aaru.CommonTypes/Interfaces/IChecksum.cs @@ -0,0 +1,59 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : IChecksum.cs +// Author(s) : Natalia Portillo +// +// Component : Checksums. +// +// --[ Description ] ---------------------------------------------------------- +// +// Provides an interface for implementing checksums and hashes. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.CommonTypes.Interfaces +{ + /// Defines the interface to implement a checksum or hashing algorithm + public interface IChecksum + { + /// Updates the hash with data. + /// Data buffer. + /// Length of buffer to hash. + void Update(byte[] data, uint len); + + /// Updates the hash with data. + /// Data buffer. + void Update(byte[] data); + + /// Returns a byte array of the hash value. + byte[] Final(); + + /// Returns a hexadecimal representation of the hash value. + string End(); + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interfaces/IFilesystem.cs b/Aaru.CommonTypes/Interfaces/IFilesystem.cs new file mode 100644 index 000000000..2f4e028ee --- /dev/null +++ b/Aaru.CommonTypes/Interfaces/IFilesystem.cs @@ -0,0 +1,73 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : IFilesystem.cs +// Author(s) : Natalia Portillo +// +// Component : Filesystem plugins. +// +// --[ Description ] ---------------------------------------------------------- +// +// Interface for filesystem plugins. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Text; +using Schemas; + +namespace Aaru.CommonTypes.Interfaces +{ + /// Interface to implement filesystem plugins. + public interface IFilesystem + { + /// Defines the encoding used to interpret strings in the filesystem + Encoding Encoding { get; } + /// Plugin name. + string Name { get; } + /// Plugin UUID. + Guid Id { get; } + /// Information about the filesystem as expected by CICM Metadata XML + /// Information about the filesystem as expected by CICM Metadata XML + FileSystemType XmlFsType { get; } + /// Plugin author + string Author { get; } + + /// Identifies the filesystem in the specified LBA + /// Disk image. + /// Partition. + /// true, if the filesystem is recognized, false otherwise. + bool Identify(IMediaImage imagePlugin, Partition partition); + + /// Gets information about the identified filesystem. + /// Disk image. + /// Partition. + /// Filesystem information. + /// Which encoding to use for this filesystem. + void GetInformation(IMediaImage imagePlugin, Partition partition, out string information, Encoding encoding); + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interfaces/IFilter.cs b/Aaru.CommonTypes/Interfaces/IFilter.cs new file mode 100644 index 000000000..fa182ed79 --- /dev/null +++ b/Aaru.CommonTypes/Interfaces/IFilter.cs @@ -0,0 +1,152 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : IFilter.cs +// Author(s) : Natalia Portillo +// +// Component : Filters. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines the interface for a Filter. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.IO; + +namespace Aaru.CommonTypes.Interfaces +{ + /// + /// Defines a filter, that is, a transformation of the data from a file, like, for example, a compressor (e.g. + /// GZIP), or a container (e.g. AppleDouble) + /// + public interface IFilter + { + /// Descriptive name of the plugin + string Name { get; } + /// Unique UUID of the plugin + Guid Id { get; } + /// Plugin author + string Author { get; } + + /// Closes all opened streams. + void Close(); + + /// + /// Gets the path used to open this filter.
UNIX: /path/to/archive.zip/path/to/file.bin => + /// /path/to/archive.zip/path/to/file.bin
Windows: C:\path\to\archive.zip\path\to\file.bin => + /// C:\path\to\archive.zip\path\to\file.bin + ///
+ /// Path used to open this filter. + string GetBasePath(); + + /// Gets creation time of file referenced by this filter. + /// The creation time. + DateTime GetCreationTime(); + + /// Gets length of this filter's data fork. + /// The data fork length. + long GetDataForkLength(); + + /// Gets a stream to access the data fork contents. + /// The data fork stream. + Stream GetDataForkStream(); + + /// + /// Gets the filename for the file referenced by this filter.
UNIX: /path/to/archive.zip/path/to/file.bin = + /// > file.bin
Windows: C:\path\to\archive.zip\path\to\file.bin => file.bin + ///
+ /// The filename. + string GetFilename(); + + /// Gets last write time of file referenced by this filter. + /// The last write time. + DateTime GetLastWriteTime(); + + /// Gets length of file referenced by ths filter. + /// The length. + long GetLength(); + + /// + /// Gets full path to file referenced by this filter. If it's an archive, it's the path inside the archive.
+ /// UNIX: /path/to/archive.zip/path/to/file.bin => /path/to/file.bin
Windows: + /// C:\path\to\archive.zip\path\to\file.bin => \path\to\file.bin + ///
+ /// The path. + string GetPath(); + + /// + /// Gets path to parent folder to the file referenced by this filter. If it's an archive, it's the full path to + /// the archive itself.
UNIX: /path/to/archive.zip/path/to/file.bin => /path/to/archive.zip
Windows: + /// C:\path\to\archive.zip\path\to\file.bin => C:\path\to\archive.zip + ///
+ /// The parent folder. + string GetParentFolder(); + + /// Gets length of this filter's resource fork. + /// The resource fork length. + long GetResourceForkLength(); + + /// Gets a stream to access the resource fork contents. + /// The resource fork stream. + Stream GetResourceForkStream(); + + /// Returns true if the file referenced by this filter has a resource fork + bool HasResourceFork(); + + /// Identifies if the specified path contains data recognizable by this filter instance + /// Path. + bool Identify(string path); + + /// Identifies if the specified stream contains data recognizable by this filter instance + /// Stream. + bool Identify(Stream stream); + + /// Identifies if the specified buffer contains data recognizable by this filter instance + /// Buffer. + bool Identify(byte[] buffer); + + /// + /// Returns true if the filter has a file/stream/buffer currently opened and no + /// has been issued. + /// + bool IsOpened(); + + /// Opens the specified path with this filter instance + /// Path. + void Open(string path); + + /// Opens the specified stream with this filter instance + /// Stream. + void Open(Stream stream); + + /// Opens the specified buffer with this filter instance + /// Buffer. + void Open(byte[] buffer); + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interfaces/IFloppyImage.cs b/Aaru.CommonTypes/Interfaces/IFloppyImage.cs new file mode 100644 index 000000000..ce172ee78 --- /dev/null +++ b/Aaru.CommonTypes/Interfaces/IFloppyImage.cs @@ -0,0 +1,121 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : IFloppyImage.cs +// Author(s) : Natalia Portillo +// +// Component : Disc image plugins. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines the interface to be implemented by floppy image plugins. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Structs; + +namespace Aaru.CommonTypes.Interfaces +{ + /// + /// + /// Abstract class to implement disk image reading plugins that can contain floppy images. This interface is + /// needed because floppy formatting characteristics are not necesarily compatible with the whole. LBA-oriented + /// interface is defined by . All data returned by these + /// methods is already decoded from its corresponding bitstream. + /// + public interface IFloppyImage : IMediaImage + { + /// + /// Floppy info, contains information about physical characteristics of floppy, like size, bitrate, track density, + /// etc... + /// + FloppyInfo FloppyInfo { get; } + + /// Reads a sector's user data. + /// + /// If is one of the duplicates is returned + /// randomly. If is or + /// random data is returned. If is + /// null is returned. Otherwise, whatever is in the sector is + /// returned. + /// + /// Physical track (position of the heads over the floppy media, 0-based). + /// Physical head (0-based). + /// Logical sector ID. + /// Status of request. + byte[] ReadSector(ushort track, byte head, ushort sector, out FloppySectorStatus status); + + /// Reads a sector's tag. + /// + /// If is one of the duplicates is returned + /// randomly. If is or + /// random data is returned. If is + /// null is returned. Otherwise, whatever tag is in the sector is + /// returned. + /// + /// Physical track (position of the heads over the floppy media, 0-based). + /// Physical head (0-based). + /// Logical sector ID. + /// Status of request. + /// Sector tag + byte[] ReadSectorTag(ushort track, byte head, ushort sector, out FloppySectorStatus status, SectorTagType tag); + + /// Reads a whole track. It includes all gaps, address marks, sectors data, etc. + /// The track data. + /// Physical track (position of the heads over the floppy media, 0-based). + /// Physical head (0-based). + byte[] ReadTrack(ushort track, byte head); + + /// Reads a sector's data including all tags, address mark, and so, in a format dependent of represented media. + /// + /// If is one of the duplicates is returned + /// randomly. If is or + /// random data is returned. If is + /// null is returned. Otherwise, whatever is in the sector is + /// returned. + /// + /// Physical track (position of the heads over the floppy media, 0-based). + /// Physical head (0-based). + /// Logical sector ID. + /// Status of request. + byte[] ReadSectorLong(ushort track, byte head, ushort sector, out FloppySectorStatus status); + + /// Verifies a track. + /// True if correct, false if incorrect, null if uncheckable. + /// Physical track (position of the heads over the floppy media, 0-based). + /// Physical head (0-based). + bool? VerifyTrack(ushort track, byte head); + + /// Verifies a sector, relative to track. + /// True if correct, false if incorrect, null if uncheckable. + /// Physical track (position of the heads over the floppy media, 0-based). + /// Physical head (0-based). + /// Logical sector ID. + bool? VerifySector(ushort track, byte head, ushort sector); + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interfaces/IMediaImage.cs b/Aaru.CommonTypes/Interfaces/IMediaImage.cs new file mode 100644 index 000000000..96881ebb8 --- /dev/null +++ b/Aaru.CommonTypes/Interfaces/IMediaImage.cs @@ -0,0 +1,117 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : IMediaImage.cs +// Author(s) : Natalia Portillo +// +// Component : Disc image plugins. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines interface to be implemented by block addressable disk image +// plugins. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Structs; +using Schemas; + +namespace Aaru.CommonTypes.Interfaces +{ + /// Abstract class to implement disk image reading plugins. + public interface IMediaImage + { + /// Image information + ImageInfo Info { get; } + /// Plugin name. + string Name { get; } + /// Plugin UUID. + Guid Id { get; } + /// Plugin author + string Author { get; } + /// Gets the image format. + /// The image format. + string Format { get; } + /// List of dump hardware used to create the image from real media + List DumpHardware { get; } + /// Gets the CICM XML metadata for the image + CICMMetadataType CicmMetadata { get; } + + /// Identifies the image. + /// true, if image was identified, false otherwise. + /// Image filter. + bool Identify(IFilter imageFilter); + + /// Opens the image. + /// true, if image was opened, false otherwise. + /// Image filter. + bool Open(IFilter imageFilter); + + /// Reads a disk tag. + /// Disk tag + /// Tag type to read. + byte[] ReadDiskTag(MediaTagType tag); + + /// Reads a sector's user data. + /// The sector's user data. + /// Sector address (LBA). + byte[] ReadSector(ulong sectorAddress); + + /// Reads a sector's tag. + /// The sector's tag. + /// Sector address (LBA). + /// Tag type. + byte[] ReadSectorTag(ulong sectorAddress, SectorTagType tag); + + /// Reads user data from several sectors. + /// The sectors user data. + /// Starting sector address (LBA). + /// How many sectors to read. + byte[] ReadSectors(ulong sectorAddress, uint length); + + /// Reads tag from several sectors. + /// The sectors tag. + /// Starting sector address (LBA). + /// How many sectors to read. + /// Tag type. + byte[] ReadSectorsTag(ulong sectorAddress, uint length, SectorTagType tag); + + /// Reads a complete sector (user data + all tags). + /// The complete sector. Format depends on disk type. + /// Sector address (LBA). + byte[] ReadSectorLong(ulong sectorAddress); + + /// Reads several complete sector (user data + all tags). + /// The complete sectors. Format depends on disk type. + /// Starting sector address (LBA). + /// How many sectors to read. + byte[] ReadSectorsLong(ulong sectorAddress, uint length); + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interfaces/IOpticalMediaImage.cs b/Aaru.CommonTypes/Interfaces/IOpticalMediaImage.cs new file mode 100644 index 000000000..128ac136a --- /dev/null +++ b/Aaru.CommonTypes/Interfaces/IOpticalMediaImage.cs @@ -0,0 +1,117 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : IOpticalMediaImage.cs +// Author(s) : Natalia Portillo +// +// Component : Disc image plugins. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines the interface to be implemented by optical disc image plugins. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Collections.Generic; +using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Structs; + +namespace Aaru.CommonTypes.Interfaces +{ + /// + /// Abstract class to implement disk image reading plugins. + public interface IOpticalMediaImage : IMediaImage, IPartitionableMediaImage, IVerifiableSectorsImage + { + /// Gets the disc track extents (start, length). + /// The track extents. + List Tracks { get; } + /// Gets the sessions (optical discs only). + /// The sessions. + List Sessions { get; } + + /// Reads a sector's user data, relative to track. + /// The sector's user data. + /// Sector address (relative LBA). + /// Track. + byte[] ReadSector(ulong sectorAddress, uint track); + + /// Reads a sector's tag, relative to track. + /// The sector's tag. + /// Sector address (relative LBA). + /// Track. + /// Tag type. + byte[] ReadSectorTag(ulong sectorAddress, uint track, SectorTagType tag); + + /// Reads user data from several sectors, relative to track. + /// The sectors user data. + /// Starting sector address (relative LBA). + /// How many sectors to read. + /// Track. + byte[] ReadSectors(ulong sectorAddress, uint length, uint track); + + /// Reads tag from several sectors, relative to track. + /// The sectors tag. + /// Starting sector address (relative LBA). + /// How many sectors to read. + /// Track. + /// Tag type. + byte[] ReadSectorsTag(ulong sectorAddress, uint length, uint track, SectorTagType tag); + + /// Reads a complete sector (user data + all tags), relative to track. + /// The complete sector. Format depends on disk type. + /// Sector address (relative LBA). + /// Track. + byte[] ReadSectorLong(ulong sectorAddress, uint track); + + /// Reads several complete sector (user data + all tags), relative to track. + /// The complete sectors. Format depends on disk type. + /// Starting sector address (relative LBA). + /// How many sectors to read. + /// Track. + byte[] ReadSectorsLong(ulong sectorAddress, uint length, uint track); + + /// Gets the disc track extents for a specified session. + /// The track extents for that session. + /// Session. + List GetSessionTracks(Session session); + + /// Gets the disc track extents for a specified session. + /// The track extents for that session. + /// Session. + List GetSessionTracks(ushort session); + + /// Verifies several sectors, relative to track. + /// True if all are correct, false if any is incorrect, null if any is uncheckable. + /// Starting sector address (relative LBA). + /// How many sectors to read. + /// Track. + /// List of incorrect sectors + /// List of uncheckable sectors + bool? VerifySectors(ulong sectorAddress, uint length, uint track, out List failingLbas, + out List unknownLbas); + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interfaces/IPartition.cs b/Aaru.CommonTypes/Interfaces/IPartition.cs new file mode 100644 index 000000000..bff93f432 --- /dev/null +++ b/Aaru.CommonTypes/Interfaces/IPartition.cs @@ -0,0 +1,62 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : IPartition.cs +// Author(s) : Natalia Portillo +// +// Component : Partitioning scheme plugins. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines methods to be used by partitioning scheme plugins and several +// constants. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; + +namespace Aaru.CommonTypes.Interfaces +{ + /// Abstract class to implement partitioning schemes interpreting plugins. + public interface IPartition + { + /// Plugin name. + string Name { get; } + /// Plugin UUID. + Guid Id { get; } + /// Plugin author + string Author { get; } + + /// Interprets a partitioning scheme. + /// true, if partitioning scheme is recognized, false otherwise. + /// Disk image. + /// Returns list of partitions. + /// At which sector to start searching for the partition scheme. + bool GetInformation(IMediaImage imagePlugin, out List partitions, ulong sectorOffset); + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interfaces/IPartitionableMediaImage.cs b/Aaru.CommonTypes/Interfaces/IPartitionableMediaImage.cs new file mode 100644 index 000000000..2e424b4bf --- /dev/null +++ b/Aaru.CommonTypes/Interfaces/IPartitionableMediaImage.cs @@ -0,0 +1,54 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : IPartitionableMediaImage.cs +// Author(s) : Natalia Portillo +// +// Component : Media image plugins. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines the interface to be implemented by image plugins that can +// contain partitioned medias, usually optical discs and some newer tapes. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Collections.Generic; + +namespace Aaru.CommonTypes.Interfaces +{ + /// Defines an image that can contain partitions + public interface IPartitionableMediaImage + { + /// + /// Gets an array partitions. Typically only useful for optical disc images where each track and index means a + /// different partition, as reads can be relative to them. + /// + /// The partitions. + List Partitions { get; } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interfaces/IPluginRegister.cs b/Aaru.CommonTypes/Interfaces/IPluginRegister.cs new file mode 100644 index 000000000..73efa0592 --- /dev/null +++ b/Aaru.CommonTypes/Interfaces/IPluginRegister.cs @@ -0,0 +1,83 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : IPluginsRegister.cs +// Author(s) : Natalia Portillo +// +// Component : Interfaces. +// +// --[ Description ] ---------------------------------------------------------- +// +// Interface that declares class and methods to call to register plugins. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; + +namespace Aaru.CommonTypes.Interfaces +{ + /// Defines a register of all known plugins + public interface IPluginRegister + { + /// Gets all checksum plugins + /// List of checksum plugins + List GetAllChecksumPlugins(); + + /// Gets all filesystem plugins + /// List of filesystem plugins + List GetAllFilesystemPlugins(); + + /// Gets all filter plugins + /// List of filter plugins + List GetAllFilterPlugins(); + + /// Gets all floppy image plugins + /// List of floppy image plugins + List GetAllFloppyImagePlugins(); + + /// Gets all media image plugins + /// List of media image plugins + List GetAllMediaImagePlugins(); + + /// Gets all partition plugins + /// List of partition plugins + List GetAllPartitionPlugins(); + + /// Gets all read-only filesystem plugins + /// List of read-only filesystem plugins + List GetAllReadOnlyFilesystemPlugins(); + + /// Gets all writable floppy image plugins + /// List of writable floppy image plugins + List GetAllWritableFloppyImagePlugins(); + + /// Gets all writable media image plugins + /// List of writable media image plugins + List GetAllWritableImagePlugins(); + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interfaces/IReadOnlyFilesystem.cs b/Aaru.CommonTypes/Interfaces/IReadOnlyFilesystem.cs new file mode 100644 index 000000000..77ee5c9cd --- /dev/null +++ b/Aaru.CommonTypes/Interfaces/IReadOnlyFilesystem.cs @@ -0,0 +1,124 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : IReadOnlyFilesystem.cs +// Author(s) : Natalia Portillo +// +// Component : Filesystem plugins. +// +// --[ Description ] ---------------------------------------------------------- +// +// Interface for filesystem plugins that offer read-only support of their +// contents. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Text; +using Aaru.CommonTypes.Structs; + +namespace Aaru.CommonTypes.Interfaces +{ + /// + /// Defines the interface to implement reading the contents of a filesystem + public interface IReadOnlyFilesystem : IFilesystem + { + /// Retrieves a list of options supported by the filesystem, with name, type and description + IEnumerable<(string name, Type type, string description)> SupportedOptions { get; } + + /// Supported namespaces + Dictionary Namespaces { get; } + + /// + /// Initializes whatever internal structures the filesystem plugin needs to be able to read files and directories + /// from the filesystem. + /// + /// + /// + /// Which encoding to use for this filesystem. + /// Dictionary of key=value pairs containing options to pass to the filesystem + /// Filename namespace + Errno Mount(IMediaImage imagePlugin, Partition partition, Encoding encoding, Dictionary options, + string @namespace); + + /// Frees all internal structures created by + Errno Unmount(); + + /// Maps a filesystem block from a file to a block from the underlying device. + /// Error number. + /// File path. + /// File block. + /// Device block. + Errno MapBlock(string path, long fileBlock, out long deviceBlock); + + /// Gets the attributes of a file or directory + /// Error number. + /// File path. + /// File attributes. + Errno GetAttributes(string path, out FileAttributes attributes); + + /// Lists all extended attributes, alternate data streams and forks of the given file. + /// Error number. + /// Path. + /// List of extended attributes, alternate data streams and forks. + Errno ListXAttr(string path, out List xattrs); + + /// Reads an extended attribute, alternate data stream or fork from the given file. + /// Error number. + /// File path. + /// Extended attribute, alternate data stream or fork name. + /// Buffer. + Errno GetXattr(string path, string xattr, ref byte[] buf); + + /// Reads data from a file (main/only data stream or data fork). + /// File path. + /// Offset. + /// Bytes to read. + /// Buffer. + Errno Read(string path, long offset, long size, ref byte[] buf); + + /// Lists contents from a directory. + /// Directory path. + /// Directory contents. + Errno ReadDir(string path, out List contents); + + /// Gets information about the mounted volume. + /// Information about the mounted volume. + Errno StatFs(out FileSystemInfo stat); + + /// Gets information about a file or directory. + /// File path. + /// File information. + Errno Stat(string path, out FileEntryInfo stat); + + /// Solves a symbolic link. + /// Link path. + /// Link destination. + Errno ReadLink(string path, out string dest); + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interfaces/ITapeImage.cs b/Aaru.CommonTypes/Interfaces/ITapeImage.cs new file mode 100644 index 000000000..7d7260880 --- /dev/null +++ b/Aaru.CommonTypes/Interfaces/ITapeImage.cs @@ -0,0 +1,56 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ITapeImage.cs +// Author(s) : Natalia Portillo +// +// Component : Disc image plugins. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines the interface to be implemented by block addressable sequential +// tape image plugins. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Collections.Generic; +using Aaru.CommonTypes.Structs; + +namespace Aaru.CommonTypes.Interfaces +{ + /// + /// Defines an image that can store the information from streaming, digital, tapes + public interface ITapeImage : IMediaImage + { + /// Gets a list of all the files registered in the image + List Files { get; } + /// Gets a list of all the partitions registered in the image + List TapePartitions { get; } + /// If the media is a really a tape, as some formats can store non-tapes + bool IsTape { get; } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interfaces/IVerifiableImage.cs b/Aaru.CommonTypes/Interfaces/IVerifiableImage.cs new file mode 100644 index 000000000..b450b8d20 --- /dev/null +++ b/Aaru.CommonTypes/Interfaces/IVerifiableImage.cs @@ -0,0 +1,49 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : IVerifiableImage.cs +// Author(s) : Natalia Portillo +// +// Component : Disc image plugins. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines interface to be implemented by image plugins that can verify the +// image itself. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.CommonTypes.Interfaces +{ + /// Defines an image that can verify the integrity of the image itself, but not its contents + public interface IVerifiableImage + { + /// Verifies media image internal checksum. + /// True if correct, false if incorrect, null if there is no internal checksum available + bool? VerifyMediaImage(); + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interfaces/IVerifiableSectorsImage.cs b/Aaru.CommonTypes/Interfaces/IVerifiableSectorsImage.cs new file mode 100644 index 000000000..2b2cfb135 --- /dev/null +++ b/Aaru.CommonTypes/Interfaces/IVerifiableSectorsImage.cs @@ -0,0 +1,60 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : IVerifiableSectorsImage.cs +// Author(s) : Natalia Portillo +// +// Component : Disc image plugins. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines interface to be implemented by image plugins that can verify the +// sectors contained in the image. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Collections.Generic; + +namespace Aaru.CommonTypes.Interfaces +{ + /// Defines an image that can verify the integrity of the sectors it contains + public interface IVerifiableSectorsImage + { + /// Verifies a sector. + /// True if correct, false if incorrect, null if uncheckable. + /// Sector address (LBA). + bool? VerifySector(ulong sectorAddress); + + /// Verifies several sectors. + /// True if all are correct, false if any is incorrect, null if any is uncheckable. + /// Starting sector address (LBA). + /// How many sectors to read. + /// List of incorrect sectors + /// List of uncheckable sectors + bool? VerifySectors(ulong sectorAddress, uint length, out List failingLbas, out List unknownLbas); + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interfaces/IWritableFloppyImage.cs b/Aaru.CommonTypes/Interfaces/IWritableFloppyImage.cs new file mode 100644 index 000000000..86f38aed5 --- /dev/null +++ b/Aaru.CommonTypes/Interfaces/IWritableFloppyImage.cs @@ -0,0 +1,97 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : IFloppyImage.cs +// Author(s) : Natalia Portillo +// +// Component : Disc image plugins. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines the interface to be implemented by floppy image plugins. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Structs; + +namespace Aaru.CommonTypes.Interfaces +{ + /// + /// + /// Abstract class to implement disk image reading plugins that can contain floppy images. This interface is + /// needed because floppy formatting characteristics are not necessarily compatible with the whole LBA-oriented + /// interface defined by . All data expected by these methods + /// is already decoded from its corresponding bitstream. + /// + public interface IWritableFloppyImage : IFloppyImage, IWritableImage + { + /// + /// Indicates the image plugin the floppy physical characteristics and must be called before following methods are + /// called. Once this is called, LBA-based methods should not be used. + /// + /// + /// Floppy info, contains information about physical characteristics of floppy, like size, bitrate, + /// track density, etc... + /// + /// true if operating completed successfully, false otherwise + bool SetFloppyCharacteristics(FloppyInfo info); + + /// Writes a sector's user data. + /// + /// If is one of the duplicates. If + /// is , , + /// it will be ignored. Otherwise, whatever data should be in the sector. + /// + /// Physical track (position of the heads over the floppy media, 0-based). + /// Physical head (0-based). + /// Logical sector ID. + /// Status of sector. + /// true if operating completed successfully, false otherwise + bool WriteSector(byte[] data, ushort track, byte head, ushort sector, FloppySectorStatus status); + + /// Writes a whole track, including all gaps, address marks, sectors data, etc. + /// The track data. + /// Physical track (position of the heads over the floppy media, 0-based). + /// Physical head (0-based). + /// true if operating completed successfully, false otherwise + bool WriteTrack(byte[] data, ushort track, byte head); + + /// Writes a sector's data including all tags, address mark, and so, in a format dependent of represented media. + /// + /// If is one of the duplicates. If + /// is , , + /// it will be ignored. Otherwise, whatever data should be in the sector. + /// + /// Physical track (position of the heads over the floppy media, 0-based). + /// Physical head (0-based). + /// Logical sector ID. + /// Status of request. + /// true if operating completed successfully, false otherwise + bool WriteSectorLong(byte[] data, ushort track, byte head, ushort sector, out FloppySectorStatus status); + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interfaces/IWritableImage.cs b/Aaru.CommonTypes/Interfaces/IWritableImage.cs new file mode 100644 index 000000000..09e0f27e1 --- /dev/null +++ b/Aaru.CommonTypes/Interfaces/IWritableImage.cs @@ -0,0 +1,154 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : IWritableImage.cs +// Author(s) : Natalia Portillo +// +// Component : Disc image plugins. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines the interface to be implemented by writable image plugins. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Structs; +using Schemas; + +namespace Aaru.CommonTypes.Interfaces +{ + /// + /// + /// Abstract class to implement disk image writing plugins. TODO: This interface is subject to change until + /// notice. + /// + public interface IWritableImage : IMediaImage + { + /// Gets a list of that are supported by the media image format + IEnumerable SupportedMediaTags { get; } + /// Gets a list of that are supported by the media image format + IEnumerable SupportedSectorTags { get; } + /// Gets a list of that are supported by the media image format + IEnumerable SupportedMediaTypes { get; } + /// Retrieves a list of options supported by the filesystem, with name, type and description + IEnumerable<(string name, Type type, string description, object @default)> SupportedOptions { get; } + /// Gets a list of known extensions for format auto-choosing + IEnumerable KnownExtensions { get; } + + /// If set to true means the image is opened for writing + bool IsWriting { get; } + /// Contains a description of the last error + string ErrorMessage { get; } + + /// + /// Creates a new image in the specified path, for the specified , with the specified + /// options to hold a media with the specified number of sectors + /// + /// Path to the new image, with extension + /// that will be written in the image + /// Options to be used when creating new image + /// How many sectors the media has. + /// + /// true if operating completed successfully, false otherwise + bool Create(string path, MediaType mediaType, Dictionary options, ulong sectors, + uint sectorSize); + + /// Writes a media tag to the image + /// Media tag + /// + /// + /// + /// true if operating completed successfully, false otherwise + bool WriteMediaTag(byte[] data, MediaTagType tag); + + /// Writes a sector to the image + /// Sector data + /// Sector address + /// true if operating completed successfully, false otherwise + bool WriteSector(byte[] data, ulong sectorAddress); + + /// Writes several sectors to the image + /// Sectors data + /// Sector starting address + /// How many sectors to write + /// true if operating completed successfully, false otherwise + bool WriteSectors(byte[] data, ulong sectorAddress, uint length); + + /// Writes a sector to the image with main channel tags attached + /// Sector data with its main channel tags attached + /// Sector address + /// true if operating completed successfully, false otherwise + bool WriteSectorLong(byte[] data, ulong sectorAddress); + + /// Writes several sectors to the image + /// Sector data with their main channel tags attached + /// Sector starting address + /// How many sectors to write + /// true if operating completed successfully, false otherwise + bool WriteSectorsLong(byte[] data, ulong sectorAddress, uint length); + + /// Closes and flushes to disk the image + /// true if operating completed successfully, false otherwise + bool Close(); + + /// Sets image metadata + /// containing image metadata + /// true if operating completed successfully, false otherwise + bool SetMetadata(ImageInfo metadata); + + /// Sets media geometry + /// Cylinders + /// Heads + /// Sectors per track + /// true if operating completed successfully, false otherwise + bool SetGeometry(uint cylinders, uint heads, uint sectorsPerTrack); + + /// Writes parallel or subchannel sector tag for one sector + /// Tag data to write + /// Sector address + /// Tag type + /// true if operating completed successfully, false otherwise + bool WriteSectorTag(byte[] data, ulong sectorAddress, SectorTagType tag); + + /// Writes parallel or subchannel sector tag for several sector + /// Tag data to write + /// Starting sector address + /// How many sectors to write + /// Tag type + /// true if operating completed successfully, false otherwise + bool WriteSectorsTag(byte[] data, ulong sectorAddress, uint length, SectorTagType tag); + + /// Sets the list of dump hardware used to create the image from real media + bool SetDumpHardware(List dumpHardware); + + /// Sets the CICM XML metadata for the image + bool SetCicmMetadata(CICMMetadataType metadata); + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interfaces/IWritableOpticalImage.cs b/Aaru.CommonTypes/Interfaces/IWritableOpticalImage.cs new file mode 100644 index 000000000..73c9b5571 --- /dev/null +++ b/Aaru.CommonTypes/Interfaces/IWritableOpticalImage.cs @@ -0,0 +1,56 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : IWritableOpticalImage.cs +// Author(s) : Natalia Portillo +// +// Component : Disc image plugins. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines the interface to be implemented by writable image plugins. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Collections.Generic; +using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Structs; + +namespace Aaru.CommonTypes.Interfaces +{ + /// Defines an image that is writable and can store an optical disc (CD, DVD, etc) + public interface IWritableOpticalImage : IWritableImage, IOpticalMediaImage + { + /// Image format capabilities + OpticalImageCapabilities OpticalCapabilities { get; } + + /// Sets tracks for optical media + /// List of tracks + /// true if operating completed successfully, false otherwise + bool SetTracks(List tracks); + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interfaces/IWritableTapeImage.cs b/Aaru.CommonTypes/Interfaces/IWritableTapeImage.cs new file mode 100644 index 000000000..cde66efc1 --- /dev/null +++ b/Aaru.CommonTypes/Interfaces/IWritableTapeImage.cs @@ -0,0 +1,64 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : IWritableTapeImage.cs +// Author(s) : Natalia Portillo +// +// Component : Disc image plugins. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines the interface to be implemented by writable block addressable +// sequential tape image plugins. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using Aaru.CommonTypes.Structs; + +namespace Aaru.CommonTypes.Interfaces +{ + /// Defines an image that is writable and can store information about a streaming, digital, tape + public interface IWritableTapeImage : ITapeImage, IWritableImage + { + /// Registers a new file in the image + /// Tape file descriptor + /// true if successful, false otherwise + bool AddFile(TapeFile file); + + /// Registers a new partition + /// Tape partition descriptor + /// true if successful, false otherwise + bool AddPartition(TapePartition partition); + + /// + /// Tells the image plugin to set the internal structures to expect a tape (e.g. unknown block count and size). + /// Must be called before + /// + /// true if successful, false otherwise + bool SetTape(); + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interop/DetectOS.cs b/Aaru.CommonTypes/Interop/DetectOS.cs new file mode 100644 index 000000000..a46fb2a26 --- /dev/null +++ b/Aaru.CommonTypes/Interop/DetectOS.cs @@ -0,0 +1,390 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : DetectOS.cs +// Author(s) : Natalia Portillo +// +// Component : Interop services. +// +// --[ Description ] ---------------------------------------------------------- +// +// Detects underlying operating system. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using System.Security.Principal; + +namespace Aaru.CommonTypes.Interop +{ + /// Detects the underlying execution framework and operating system + public static class DetectOS + { + /// Are we running under Mono? + public static readonly bool IsMono = + RuntimeInformation.FrameworkDescription.StartsWith("Mono", StringComparison.Ordinal); + /// Are we running under .NET Framework? + public static readonly bool IsNetFramework = + RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework", StringComparison.Ordinal); + /// Are we running under .NET Core? + public static readonly bool IsNetCore = + RuntimeInformation.FrameworkDescription.StartsWith(".NET Core", StringComparison.Ordinal); + /// Are we running under .NET Native? + public static readonly bool IsNetNative = + RuntimeInformation.FrameworkDescription.StartsWith(".NET Native", StringComparison.Ordinal); + + /// Checks if the underlying runtime runs in 64-bit mode + public static readonly bool Is64Bit = IntPtr.Size == 8; + + /// Checks if the underlying runtime runs in 32-bit mode + public static readonly bool Is32Bit = IntPtr.Size == 4; + + /// Are we running under Windows? + public static bool IsWindows => GetRealPlatformID() == PlatformID.Win32NT || + GetRealPlatformID() == PlatformID.Win32S || + GetRealPlatformID() == PlatformID.Win32Windows || + GetRealPlatformID() == PlatformID.WinCE || + GetRealPlatformID() == PlatformID.WindowsPhone || + GetRealPlatformID() == PlatformID.Xbox; + + /// Are we running with administrative (root) privileges? + public static bool IsAdmin + { + get + { + if(!IsWindows) + return Environment.UserName == "root"; + + bool isAdmin; + WindowsIdentity user = null; + + try + { + user = WindowsIdentity.GetCurrent(); + var principal = new WindowsPrincipal(user); + isAdmin = principal.IsInRole(WindowsBuiltInRole.Administrator); + } + catch(UnauthorizedAccessException) + { + isAdmin = false; + } + catch(Exception) + { + isAdmin = false; + } + finally + { + user?.Dispose(); + } + + return isAdmin; + } + } + + [DllImport("libc", SetLastError = true)] + static extern int uname(out utsname name); + + [DllImport("libc", SetLastError = true, EntryPoint = "sysctlbyname", CharSet = CharSet.Ansi)] + static extern int OSX_sysctlbyname(string name, IntPtr oldp, IntPtr oldlenp, IntPtr newp, uint newlen); + + /// Gets the real platform ID, not the incomplete .NET framework one + /// Platform ID + /// Unhandled exception + public static PlatformID GetRealPlatformID() + { + if((int)Environment.OSVersion.Platform < 4 || + (int)Environment.OSVersion.Platform == 5) + return (PlatformID)(int)Environment.OSVersion.Platform; + + int error = uname(out utsname unixname); + + if(error != 0) + throw new Exception($"Unhandled exception calling uname: {Marshal.GetLastWin32Error()}"); + + switch(unixname.sysname) + { + // TODO: Differentiate Linux, Android, Tizen + case "Linux": + { + #if __ANDROID__ + return PlatformID.Android; + #else + return PlatformID.Linux; + #endif + } + + case "Darwin": + { + IntPtr pLen = Marshal.AllocHGlobal(sizeof(int)); + int osxError = OSX_sysctlbyname("hw.machine", IntPtr.Zero, pLen, IntPtr.Zero, 0); + + if(osxError != 0) + { + Marshal.FreeHGlobal(pLen); + + throw new Exception($"Unhandled exception calling uname: {Marshal.GetLastWin32Error()}"); + } + + int length = Marshal.ReadInt32(pLen); + IntPtr pStr = Marshal.AllocHGlobal(length); + osxError = OSX_sysctlbyname("hw.machine", pStr, pLen, IntPtr.Zero, 0); + + if(osxError != 0) + { + Marshal.FreeHGlobal(pStr); + Marshal.FreeHGlobal(pLen); + + throw new Exception($"Unhandled exception calling uname: {Marshal.GetLastWin32Error()}"); + } + + string machine = Marshal.PtrToStringAnsi(pStr); + + Marshal.FreeHGlobal(pStr); + Marshal.FreeHGlobal(pLen); + + if(machine != null && + (machine.StartsWith("iPad", StringComparison.Ordinal) || + machine.StartsWith("iPod", StringComparison.Ordinal) || + machine.StartsWith("iPhone", StringComparison.Ordinal))) + return PlatformID.iOS; + + return PlatformID.MacOSX; + } + + case "GNU": return PlatformID.Hurd; + case "FreeBSD": + case "GNU/kFreeBSD": return PlatformID.FreeBSD; + case "DragonFly": return PlatformID.DragonFly; + case "Haiku": return PlatformID.Haiku; + case "HP-UX": return PlatformID.HPUX; + case "AIX": return PlatformID.AIX; + case "OS400": return PlatformID.OS400; + case "IRIX": + case "IRIX64": return PlatformID.IRIX; + case "Minix": return PlatformID.Minix; + case "NetBSD": return PlatformID.NetBSD; + case "NONSTOP_KERNEL": return PlatformID.NonStop; + case "OpenBSD": return PlatformID.OpenBSD; + case "QNX": return PlatformID.QNX; + case "SINIX-Y": return PlatformID.SINIX; + case "SunOS": return PlatformID.Solaris; + case "OSF1": return PlatformID.Tru64; + case "ULTRIX": return PlatformID.Ultrix; + case "SCO_SV": return PlatformID.OpenServer; + case "UnixWare": return PlatformID.UnixWare; + case "Interix": + case "UWIN-W7": return PlatformID.Win32NT; + default: + { + if(unixname.sysname.StartsWith("CYGWIN_NT", StringComparison.Ordinal) || + unixname.sysname.StartsWith("MINGW32_NT", StringComparison.Ordinal) || + unixname.sysname.StartsWith("MSYS_NT", StringComparison.Ordinal) || + unixname.sysname.StartsWith("UWIN", StringComparison.Ordinal)) + return PlatformID.Win32NT; + + return PlatformID.Unknown; + } + } + } + + /// Gets a string for the current operating system REAL version (handles Darwin 1.4 and Windows 10 falsifying) + /// Current operating system version + public static string GetVersion() + { + string environ = Environment.OSVersion.Version.ToString(); + + switch(GetRealPlatformID()) + { + case PlatformID.MacOSX: + if(Environment.OSVersion.Version.Major != 1) + return $"10.{Environment.OSVersion.Version.Major - 4}.{Environment.OSVersion.Version.Minor}"; + + switch(Environment.OSVersion.Version.Minor) + { + case 3: return "10.0"; + case 4: return "10.1"; + } + + goto default; + case PlatformID.Win32NT: + // From Windows 8.1 the reported version is simply falsified... + if((Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Major >= 2) || + Environment.OSVersion.Version.Major > 6) + return FileVersionInfo. + GetVersionInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), + "KERNEL32.DLL")).ProductVersion; + + return environ; + default: return environ; + } + } + + /// From a platform ID and version returns a human-readable version + /// Platform ID + /// Version number + /// Operating system name + public static string GetPlatformName(PlatformID id, string version = null) + { + switch(id) + { + case PlatformID.AIX: return "AIX"; + case PlatformID.Android: return "Android"; + case PlatformID.DragonFly: return "DragonFly BSD"; + case PlatformID.FreeBSD: return "FreeBSD"; + case PlatformID.Haiku: return "Haiku"; + case PlatformID.HPUX: return "HP/UX"; + case PlatformID.Hurd: return "Hurd"; + case PlatformID.iOS: return "iOS"; + case PlatformID.IRIX: return "IRIX"; + case PlatformID.Linux: + if(!File.Exists("/proc/version")) + return "Linux"; + + string s = File.ReadAllText("/proc/version"); + + return s.Contains("Microsoft") || s.Contains("WSL") ? "Windows Subsystem for Linux" : "Linux"; + + case PlatformID.MacOSX: + if(string.IsNullOrEmpty(version)) + return "macOS"; + + string[] pieces = version.Split('.'); + + if(pieces.Length < 2 || + !int.TryParse(pieces[1], out int minor)) + return "macOS"; + + if(minor >= 12) + return "macOS"; + + if(minor >= 8) + return "OS X"; + + return "Mac OS X"; + + case PlatformID.Minix: return "MINIX"; + case PlatformID.NetBSD: return "NetBSD"; + case PlatformID.NonStop: return "NonStop OS"; + case PlatformID.OpenBSD: return "OpenBSD"; + case PlatformID.OpenServer: return "SCO OpenServer"; + case PlatformID.OS400: return "OS/400"; + case PlatformID.PlayStation3: return "Sony CellOS"; + case PlatformID.PlayStation4: return "Sony Orbis OS"; + case PlatformID.QNX: return "QNX"; + case PlatformID.SINIX: return "SINIX"; + case PlatformID.Solaris: return "Sun Solaris"; + case PlatformID.Tizen: return "Samsung Tizen"; + case PlatformID.Tru64: return "Tru64 UNIX"; + case PlatformID.Ultrix: return "Ultrix"; + case PlatformID.Unix: return "UNIX"; + case PlatformID.UnixWare: return "SCO UnixWare"; + case PlatformID.Wii: return "Nintendo Wii"; + case PlatformID.WiiU: return "Nintendo Wii U"; + case PlatformID.Win32NT: + if(string.IsNullOrEmpty(version)) + return "Windows NT/2000/XP/Vista/7/10"; + + if(version.StartsWith("3.", StringComparison.Ordinal) || + version.StartsWith("4.", StringComparison.Ordinal)) + return "Windows NT"; + + if(version.StartsWith("5.0", StringComparison.Ordinal)) + return "Windows 2000"; + + if(version.StartsWith("5.1", StringComparison.Ordinal)) + return "Windows XP"; + + if(version.StartsWith("5.2", StringComparison.Ordinal)) + return "Windows 2003"; + + if(version.StartsWith("6.0", StringComparison.Ordinal)) + return "Windows Vista"; + + if(version.StartsWith("6.1", StringComparison.Ordinal)) + return "Windows 7"; + + if(version.StartsWith("6.2", StringComparison.Ordinal)) + return "Windows 8"; + + if(version.StartsWith("6.3", StringComparison.Ordinal)) + return "Windows 8.1"; + + if(version.StartsWith("10.0", StringComparison.Ordinal)) + return "Windows 10"; + + return "Windows NT/2000/XP/Vista/7/10"; + case PlatformID.Win32S: return "Windows 3.x with win32s"; + case PlatformID.Win32Windows: + if(string.IsNullOrEmpty(version)) + return "Windows 9x/Me"; + + if(version.StartsWith("4.0", StringComparison.Ordinal)) + return "Windows 95"; + + if(version.StartsWith("4.10.2222", StringComparison.Ordinal)) + return "Windows 98 SE"; + + if(version.StartsWith("4.1", StringComparison.Ordinal)) + return "Windows 98"; + + if(version.StartsWith("4.9", StringComparison.Ordinal)) + return "Windows Me"; + + return "Windows 9x/Me"; + case PlatformID.WinCE: return "Windows CE/Mobile"; + case PlatformID.WindowsPhone: return "Windows Phone"; + case PlatformID.Xbox: return "Xbox OS"; + case PlatformID.zOS: return "z/OS"; + default: return id.ToString(); + } + } + + /// POSIX uname structure, size from OSX, big enough to handle extra fields + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + struct utsname + { + /// System name + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public readonly string sysname; + /// Node name + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public readonly string nodename; + /// Release level + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public readonly string release; + /// Version level + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public readonly string version; + /// Hardware level + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public readonly string machine; + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interop/PlatformID.cs b/Aaru.CommonTypes/Interop/PlatformID.cs new file mode 100644 index 000000000..0e885323f --- /dev/null +++ b/Aaru.CommonTypes/Interop/PlatformID.cs @@ -0,0 +1,122 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : PlatformID.cs +// Author(s) : Natalia Portillo +// +// Component : Interop services. +// +// --[ Description ] ---------------------------------------------------------- +// +// Contains an enhanced PlatformID enumeration. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.CommonTypes.Interop +{ + /// Contains an arbitrary list of OSes, even if .NET does not run on them + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum PlatformID + { + /// Win32s + Win32S = 0, + /// Win32 (Windows 9x) + Win32Windows = 1, + /// Windows NT + Win32NT = 2, + /// Windows Mobile + WinCE = 3, + /// UNIX (do not use, too generic) + Unix = 4, + /// Xbox 360 + Xbox = 5, + /// OS X + MacOSX = 6, + /// iOS is not OS X + iOS = 7, + /// Linux + Linux = 8, + /// Sun Solaris + Solaris = 9, + /// NetBSD + NetBSD = 10, + /// OpenBSD + OpenBSD = 11, + /// FreeBSD + FreeBSD = 12, + /// DragonFly BSD + DragonFly = 13, + /// Nintendo Wii + Wii = 14, + /// Nintendo Wii U + WiiU = 15, + /// Sony PlayStation 3 + PlayStation3 = 16, + /// Sony Playstation 4 + PlayStation4 = 17, + /// Google Android + Android = 18, + /// Samsung Tizen + Tizen = 19, + /// Windows Phone + WindowsPhone = 20, + /// GNU/Hurd + Hurd = 21, + /// Haiku + Haiku = 22, + /// HP-UX + HPUX = 23, + /// AIX + AIX = 24, + /// OS/400 + OS400 = 25, + /// IRIX + IRIX = 26, + /// Minix + Minix = 27, + /// NonStop + NonStop = 28, + /// QNX + QNX = 29, + /// SINIX + SINIX = 30, + /// Tru64 UNIX + Tru64 = 31, + /// Ultrix + Ultrix = 32, + /// SCO OpenServer / SCO UNIX + OpenServer = 33, + /// SCO UnixWare + UnixWare = 34, + /// IBM z/OS + zOS = 35, + /// Unknown + Unknown = -1 + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Interop/Version.cs b/Aaru.CommonTypes/Interop/Version.cs new file mode 100644 index 000000000..419ef5726 --- /dev/null +++ b/Aaru.CommonTypes/Interop/Version.cs @@ -0,0 +1,91 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Version.cs +// Author(s) : Natalia Portillo +// +// Component : Interop services. +// +// --[ Description ] ---------------------------------------------------------- +// +// Returns Aaru version. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Reflection; +using System.Runtime; + +namespace Aaru.CommonTypes.Interop +{ + /// Gets our own, or the runtime's version + public static class Version + { + /// Gets version string + /// Version + public static string GetVersion() => typeof(Version).Assembly.GetName().Version?.ToString(); + + /// Gets .NET Core version + /// Version + public static string GetNetCoreVersion() + { + Assembly assembly = typeof(GCSettings).Assembly; + + string[] assemblyPath = assembly.CodeBase?.Split(new[] + { + '/', '\\' + }, StringSplitOptions.RemoveEmptyEntries); + + if(assemblyPath is null) + return null; + + int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App"); + + if(netCoreAppIndex > 0 && + netCoreAppIndex < assemblyPath.Length - 2) + return assemblyPath[netCoreAppIndex + 1]; + + return null; + } + + /// Gets Mono version + /// Version + public static string GetMonoVersion() + { + if(!DetectOS.IsMono) + return null; + + MethodInfo monoDisplayName = Type.GetType("Mono.Runtime")?. + GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static); + + if(monoDisplayName != null) + return (string)monoDisplayName.Invoke(null, null); + + return null; + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/MediaType.cs b/Aaru.CommonTypes/MediaType.cs new file mode 100644 index 000000000..2604cd783 --- /dev/null +++ b/Aaru.CommonTypes/MediaType.cs @@ -0,0 +1,1045 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : MediaType.cs +// Author(s) : Natalia Portillo +// +// Component : Aaru common types. +// +// --[ Description ] ---------------------------------------------------------- +// +// Contains common media types. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +// ReSharper disable InconsistentNaming +// TODO: Rename contents + +using System; + +#pragma warning disable 1591 + +// ReSharper disable UnusedMember.Global +// ReSharper disable IdentifierTypo + +namespace Aaru.CommonTypes +{ + public enum MediaEncoding + { + Unknown, FM, MFM, + M2FM, AppleGCR, CommodoreGCR + } + + /// Contains an enumeration of all known types of media. + public enum MediaType : uint + { + #region Generics, types 0 to 9 + /// Unknown disk type + Unknown = 0, + /// Unknown magneto-optical + UnknownMO = 1, + /// Generic hard disk + GENERIC_HDD = 2, + /// Microdrive type hard disk + Microdrive = 3, + /// Zoned hard disk + Zone_HDD = 4, + /// USB flash drives + FlashDrive = 5, + /// Unknown data tape + UnknownTape = 6, + #endregion Generics, types 0 to 9 + + #region Somewhat standard Compact Disc formats, types 10 to 39 + /// Any unknown or standard violating CD + CD = 10, + /// CD Digital Audio (Red Book) + CDDA = 11, + /// CD+G (Red Book) + CDG = 12, + /// CD+EG (Red Book) + CDEG = 13, + /// CD-i (Green Book) + CDI = 14, + /// CD-ROM (Yellow Book) + CDROM = 15, + /// CD-ROM XA (Yellow Book) + CDROMXA = 16, + /// CD+ (Blue Book) + CDPLUS = 17, + /// CD-MO (Orange Book) + CDMO = 18, + /// CD-Recordable (Orange Book) + CDR = 19, + /// CD-ReWritable (Orange Book) + CDRW = 20, + /// Mount-Rainier CD-RW + CDMRW = 21, + /// Video CD (White Book) + VCD = 22, + /// Super Video CD (White Book) + SVCD = 23, + /// Photo CD (Beige Book) + PCD = 24, + /// Super Audio CD (Scarlet Book) + SACD = 25, + /// Double-Density CD-ROM (Purple Book) + DDCD = 26, + /// DD CD-R (Purple Book) + DDCDR = 27, + /// DD CD-RW (Purple Book) + DDCDRW = 28, + /// DTS audio CD (non-standard) + DTSCD = 29, + /// CD-MIDI (Red Book) + CDMIDI = 30, + /// CD-Video (ISO/IEC 61104) + CDV = 31, + /// 120mm, Phase-Change, 1298496 sectors, 512 bytes/sector, PD650, ECMA-240, ISO 15485 + PD650 = 32, + /// 120mm, Write-Once, 1281856 sectors, 512 bytes/sector, PD650, ECMA-240, ISO 15485 + PD650_WORM = 33, + /// + /// CD-i Ready, contains a track before the first TOC track, in mode 2, and all TOC tracks are Audio. Subchannel + /// marks track as audio pause. + /// + CDIREADY = 34, FMTOWNS = 35, + #endregion Somewhat standard Compact Disc formats, types 10 to 39 + + #region Standard DVD formats, types 40 to 50 + /// DVD-ROM (applies to DVD Video and DVD Audio) + DVDROM = 40, + /// DVD-R + DVDR = 41, + /// DVD-RW + DVDRW = 42, + /// DVD+R + DVDPR = 43, + /// DVD+RW + DVDPRW = 44, + /// DVD+RW DL + DVDPRWDL = 45, + /// DVD-R DL + DVDRDL = 46, + /// DVD+R DL + DVDPRDL = 47, + /// DVD-RAM + DVDRAM = 48, + /// DVD-RW DL + DVDRWDL = 49, + /// DVD-Download + DVDDownload = 50, + #endregion Standard DVD formats, types 40 to 50 + + #region Standard HD-DVD formats, types 51 to 59 + /// HD DVD-ROM (applies to HD DVD Video) + HDDVDROM = 51, + /// HD DVD-RAM + HDDVDRAM = 52, + /// HD DVD-R + HDDVDR = 53, + /// HD DVD-RW + HDDVDRW = 54, + /// HD DVD-R DL + HDDVDRDL = 55, + /// HD DVD-RW DL + HDDVDRWDL = 56, + #endregion Standard HD-DVD formats, types 51 to 59 + + #region Standard Blu-ray formats, types 60 to 69 + /// BD-ROM (and BD Video) + BDROM = 60, + /// BD-R + BDR = 61, + /// BD-RE + BDRE = 62, + /// BD-R XL + BDRXL = 63, + /// BD-RE XL + BDREXL = 64, + /// Ultra HD Blu-ray + UHDBD = 65, + #endregion Standard Blu-ray formats, types 60 to 69 + + #region Rare or uncommon optical standards, types 70 to 79 + /// Enhanced Versatile Disc + EVD = 70, + /// Forward Versatile Disc + FVD = 71, + /// Holographic Versatile Disc + HVD = 72, + /// China Blue High Definition + CBHD = 73, + /// High Definition Versatile Multilayer Disc + HDVMD = 74, + /// Versatile Compact Disc High Density + VCDHD = 75, + /// Stacked Volumetric Optical Disc + SVOD = 76, + /// Five Dimensional disc + FDDVD = 77, + /// China Video Disc + CVD = 78, + #endregion Rare or uncommon optical standards, types 70 to 79 + + #region LaserDisc based, types 80 to 89 + /// Pioneer LaserDisc + LD = 80, + /// Pioneer LaserDisc data + LDROM = 81, LDROM2 = 82, LVROM = 83, MegaLD = 84, + /// Writable LaserDisc with support for component video + CRVdisc = 85, + #endregion LaserDisc based, types 80 to 89 + + #region MiniDisc based, types 90 to 99 + /// Sony Hi-MD + HiMD = 90, + /// Sony MiniDisc + MD = 91, + /// Sony MD-Data + MDData = 92, + /// Sony MD-Data2 + MDData2 = 93, + /// Sony MiniDisc, 60 minutes, formatted with Hi-MD format + MD60 = 94, + /// Sony MiniDisc, 74 minutes, formatted with Hi-MD format + MD74 = 95, + /// Sony MiniDisc, 80 minutes, formatted with Hi-MD format + MD80 = 96, + #endregion MiniDisc based, types 90 to 99 + + #region Plasmon UDO, types 100 to 109 + /// 5.25", Phase-Change, 1834348 sectors, 8192 bytes/sector, Ultra Density Optical, ECMA-350, ISO 17345 + UDO = 100, + /// 5.25", Phase-Change, 3669724 sectors, 8192 bytes/sector, Ultra Density Optical 2, ECMA-380, ISO 11976 + UDO2 = 101, + /// 5.25", Write-Once, 3668759 sectors, 8192 bytes/sector, Ultra Density Optical 2, ECMA-380, ISO 11976 + UDO2_WORM = 102, + #endregion Plasmon UDO, types 100 to 109 + + #region Sony game media, types 110 to 129 + PlayStationMemoryCard = 110, PlayStationMemoryCard2 = 111, + /// Sony PlayStation game CD + PS1CD = 112, + /// Sony PlayStation 2 game CD + PS2CD = 113, + /// Sony PlayStation 2 game DVD + PS2DVD = 114, + /// Sony PlayStation 3 game DVD + PS3DVD = 115, + /// Sony PlayStation 3 game Blu-ray + PS3BD = 116, + /// Sony PlayStation 4 game Blu-ray + PS4BD = 117, + /// Sony PlayStation Portable Universal Media Disc (ECMA-365) + UMD = 118, PlayStationVitaGameCard = 119, + /// Sony PlayStation 5 game Ultra HD Blu-ray + PS5BD = 120, + #endregion Sony game media, types 110 to 129 + + #region Microsoft game media, types 130 to 149 + /// Microsoft X-box Game Disc + XGD = 130, + /// Microsoft X-box 360 Game Disc + XGD2 = 131, + /// Microsoft X-box 360 Game Disc + XGD3 = 132, + /// Microsoft X-box One Game Disc + XGD4 = 133, + #endregion Microsoft game media, types 130 to 149 + + #region Sega game media, types 150 to 169 + /// Sega MegaCD + MEGACD = 150, + /// Sega Saturn disc + SATURNCD = 151, + /// Sega/Yamaha Gigabyte Disc + GDROM = 152, + /// Sega/Yamaha recordable Gigabyte Disc + GDR = 153, SegaCard = 154, MilCD = 155, + #endregion Sega game media, types 150 to 169 + + #region Other game media, types 170 to 179 + /// PC-Engine / TurboGrafx cartridge + HuCard = 170, + /// PC-Engine / TurboGrafx CD + SuperCDROM2 = 171, + /// Atari Jaguar CD + JaguarCD = 172, + /// 3DO CD + ThreeDO = 173, + /// NEC PC-FX + PCFX = 174, + /// NEO-GEO CD + NeoGeoCD = 175, + /// Commodore CDTV + CDTV = 176, + /// Amiga CD32 + CD32 = 177, + /// Nuon (DVD based videogame console) + Nuon = 178, + /// Bandai Playdia + Playdia = 179, + #endregion Other game media, types 170 to 179 + + #region Apple standard floppy format, types 180 to 189 + /// 5.25", SS, DD, 35 tracks, 13 spt, 256 bytes/sector, GCR + Apple32SS = 180, + /// 5.25", DS, DD, 35 tracks, 13 spt, 256 bytes/sector, GCR + Apple32DS = 181, + /// 5.25", SS, DD, 35 tracks, 16 spt, 256 bytes/sector, GCR + Apple33SS = 182, + /// 5.25", DS, DD, 35 tracks, 16 spt, 256 bytes/sector, GCR + Apple33DS = 183, + /// 3.5", SS, DD, 80 tracks, 8 to 12 spt, 512 bytes/sector, GCR + AppleSonySS = 184, + /// 3.5", DS, DD, 80 tracks, 8 to 12 spt, 512 bytes/sector, GCR + AppleSonyDS = 185, + /// 5.25", DS, ?D, ?? tracks, ?? spt, 512 bytes/sector, GCR, opposite side heads, aka Twiggy + AppleFileWare = 186, + #endregion Apple standard floppy format + + #region IBM/Microsoft PC floppy formats, types 190 to 209 + /// 5.25", SS, DD, 40 tracks, 8 spt, 512 bytes/sector, MFM + DOS_525_SS_DD_8 = 190, + /// 5.25", SS, DD, 40 tracks, 9 spt, 512 bytes/sector, MFM + DOS_525_SS_DD_9 = 191, + /// 5.25", DS, DD, 40 tracks, 8 spt, 512 bytes/sector, MFM + DOS_525_DS_DD_8 = 192, + /// 5.25", DS, DD, 40 tracks, 9 spt, 512 bytes/sector, MFM + DOS_525_DS_DD_9 = 193, + /// 5.25", DS, HD, 80 tracks, 15 spt, 512 bytes/sector, MFM + DOS_525_HD = 194, + /// 3.5", SS, DD, 80 tracks, 8 spt, 512 bytes/sector, MFM + DOS_35_SS_DD_8 = 195, + /// 3.5", SS, DD, 80 tracks, 9 spt, 512 bytes/sector, MFM + DOS_35_SS_DD_9 = 196, + /// 3.5", DS, DD, 80 tracks, 8 spt, 512 bytes/sector, MFM + DOS_35_DS_DD_8 = 197, + /// 3.5", DS, DD, 80 tracks, 9 spt, 512 bytes/sector, MFM + DOS_35_DS_DD_9 = 198, + /// 3.5", DS, HD, 80 tracks, 18 spt, 512 bytes/sector, MFM + DOS_35_HD = 199, + /// 3.5", DS, ED, 80 tracks, 36 spt, 512 bytes/sector, MFM + DOS_35_ED = 200, + /// 3.5", DS, HD, 80 tracks, 21 spt, 512 bytes/sector, MFM + DMF = 201, + /// 3.5", DS, HD, 82 tracks, 21 spt, 512 bytes/sector, MFM + DMF_82 = 202, + /// + /// 5.25", DS, HD, 80 tracks, ? spt, ??? + ??? + ??? bytes/sector, MFM track 0 = ??15 sectors, 512 bytes/sector, + /// falsified to DOS as 19 spt, 512 bps + /// + XDF_525 = 203, + /// + /// 3.5", DS, HD, 80 tracks, 4 spt, 8192 + 2048 + 1024 + 512 bytes/sector, MFM track 0 = 19 sectors, 512 + /// bytes/sector, falsified to DOS as 23 spt, 512 bps + /// + XDF_35 = 204, + #endregion IBM/Microsoft PC standard floppy formats, types 190 to 209 + + #region IBM standard floppy formats, types 210 to 219 + /// 8", SS, SD, 32 tracks, 8 spt, 319 bytes/sector, FM + IBM23FD = 210, + /// 8", SS, SD, 73 tracks, 26 spt, 128 bytes/sector, FM + IBM33FD_128 = 211, + /// 8", SS, SD, 74 tracks, 15 spt, 256 bytes/sector, FM, track 0 = 26 sectors, 128 bytes/sector + IBM33FD_256 = 212, + /// 8", SS, SD, 74 tracks, 8 spt, 512 bytes/sector, FM, track 0 = 26 sectors, 128 bytes/sector + IBM33FD_512 = 213, + /// 8", DS, SD, 74 tracks, 26 spt, 128 bytes/sector, FM, track 0 = 26 sectors, 128 bytes/sector + IBM43FD_128 = 214, + /// 8", DS, SD, 74 tracks, 26 spt, 256 bytes/sector, FM, track 0 = 26 sectors, 128 bytes/sector + IBM43FD_256 = 215, + /// + /// 8", DS, DD, 74 tracks, 26 spt, 256 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 + /// side 1 = 26 sectors, 256 bytes/sector + /// + IBM53FD_256 = 216, + /// + /// 8", DS, DD, 74 tracks, 15 spt, 512 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 + /// side 1 = 26 sectors, 256 bytes/sector + /// + IBM53FD_512 = 217, + /// + /// 8", DS, DD, 74 tracks, 8 spt, 1024 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 + /// side 1 = 26 sectors, 256 bytes/sector + /// + IBM53FD_1024 = 218, + #endregion IBM standard floppy formats, types 210 to 219 + + #region DEC standard floppy formats, types 220 to 229 + /// 8", SS, DD, 77 tracks, 26 spt, 128 bytes/sector, FM + RX01 = 220, + /// 8", SS, DD, 77 tracks, 26 spt, 256 bytes/sector, FM/MFM + RX02 = 221, + /// 8", DS, DD, 77 tracks, 26 spt, 256 bytes/sector, FM/MFM + RX03 = 222, + /// 5.25", SS, DD, 80 tracks, 10 spt, 512 bytes/sector, MFM + RX50 = 223, + #endregion DEC standard floppy formats, types 220 to 229 + + #region Acorn standard floppy formats, types 230 to 239 + /// 5,25", SS, SD, 40 tracks, 10 spt, 256 bytes/sector, FM + ACORN_525_SS_SD_40 = 230, + /// 5,25", SS, SD, 80 tracks, 10 spt, 256 bytes/sector, FM + ACORN_525_SS_SD_80 = 231, + /// 5,25", SS, DD, 40 tracks, 16 spt, 256 bytes/sector, MFM + ACORN_525_SS_DD_40 = 232, + /// 5,25", SS, DD, 80 tracks, 16 spt, 256 bytes/sector, MFM + ACORN_525_SS_DD_80 = 233, + /// 5,25", DS, DD, 80 tracks, 16 spt, 256 bytes/sector, MFM + ACORN_525_DS_DD = 234, + /// 3,5", DS, DD, 80 tracks, 5 spt, 1024 bytes/sector, MFM + ACORN_35_DS_DD = 235, + /// 3,5", DS, HD, 80 tracks, 10 spt, 1024 bytes/sector, MFM + ACORN_35_DS_HD = 236, + #endregion Acorn standard floppy formats, types 230 to 239 + + #region Atari standard floppy formats, types 240 to 249 + /// 5,25", SS, SD, 40 tracks, 18 spt, 128 bytes/sector, FM + ATARI_525_SD = 240, + /// 5,25", SS, ED, 40 tracks, 26 spt, 128 bytes/sector, MFM + ATARI_525_ED = 241, + /// 5,25", SS, DD, 40 tracks, 18 spt, 256 bytes/sector, MFM + ATARI_525_DD = 242, + /// 3,5", SS, DD, 80 tracks, 10 spt, 512 bytes/sector, MFM + ATARI_35_SS_DD = 243, + /// 3,5", DS, DD, 80 tracks, 10 spt, 512 bytes/sector, MFM + ATARI_35_DS_DD = 244, + /// 3,5", SS, DD, 80 tracks, 11 spt, 512 bytes/sector, MFM + ATARI_35_SS_DD_11 = 245, + /// 3,5", DS, DD, 80 tracks, 11 spt, 512 bytes/sector, MFM + ATARI_35_DS_DD_11 = 246, + #endregion Atari standard floppy formats, types 240 to 249 + + #region Commodore standard floppy formats, types 250 to 259 + /// 3,5", DS, DD, 80 tracks, 10 spt, 512 bytes/sector, MFM (1581) + CBM_35_DD = 250, + /// 3,5", DS, DD, 80 tracks, 11 spt, 512 bytes/sector, MFM (Amiga) + CBM_AMIGA_35_DD = 251, + /// 3,5", DS, HD, 80 tracks, 22 spt, 512 bytes/sector, MFM (Amiga) + CBM_AMIGA_35_HD = 252, + /// 5,25", SS, DD, 35 tracks, GCR + CBM_1540 = 253, + /// 5,25", SS, DD, 40 tracks, GCR + CBM_1540_Ext = 254, + /// 5,25", DS, DD, 35 tracks, GCR + CBM_1571 = 255, + #endregion Commodore standard floppy formats, types 250 to 259 + + #region NEC/SHARP standard floppy formats, types 260 to 269 + /// 8", DS, SD, 77 tracks, 26 spt, 128 bytes/sector, FM + NEC_8_SD = 260, + /// 8", DS, DD, 77 tracks, 26 spt, 256 bytes/sector, MFM + NEC_8_DD = 261, + /// 5.25", SS, SD, 80 tracks, 16 spt, 256 bytes/sector, FM + NEC_525_SS = 262, + /// 5.25", DS, SD, 80 tracks, 16 spt, 256 bytes/sector, MFM + NEC_525_DS = 263, + /// 5,25", DS, HD, 77 tracks, 8 spt, 1024 bytes/sector, MFM + NEC_525_HD = 264, + /// 3,5", DS, HD, 77 tracks, 8 spt, 1024 bytes/sector, MFM, aka mode 3 + NEC_35_HD_8 = 265, + /// 3,5", DS, HD, 80 tracks, 15 spt, 512 bytes/sector, MFM + NEC_35_HD_15 = 266, + /// 3,5", DS, TD, 240 tracks, 38 spt, 512 bytes/sector, MFM + NEC_35_TD = 267, + /// 5,25", DS, HD, 77 tracks, 8 spt, 1024 bytes/sector, MFM + SHARP_525 = NEC_525_HD, + /// 3,5", DS, HD, 80 tracks, 9 spt, 1024 bytes/sector, MFM + SHARP_525_9 = 268, + /// 3,5", DS, HD, 77 tracks, 8 spt, 1024 bytes/sector, MFM + SHARP_35 = NEC_35_HD_8, + /// 3,5", DS, HD, 80 tracks, 9 spt, 1024 bytes/sector, MFM + SHARP_35_9 = 269, + #endregion NEC/SHARP standard floppy formats, types 260 to 269 + + #region ECMA floppy standards, types 270 to 289 + /// + /// 5,25", DS, DD, 80 tracks, 8 spt, 1024 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track + /// 0 side 1 = 26 sectors, 256 bytes/sector + /// + ECMA_99_8 = 270, + /// + /// 5,25", DS, DD, 77 tracks, 15 spt, 512 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track + /// 0 side 1 = 26 sectors, 256 bytes/sector + /// + ECMA_99_15 = 271, + /// + /// 5,25", DS, DD, 77 tracks, 26 spt, 256 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track + /// 0 side 1 = 26 sectors, 256 bytes/sector + /// + ECMA_99_26 = 272, + /// 3,5", DS, DD, 80 tracks, 9 spt, 512 bytes/sector, MFM + ECMA_100 = DOS_35_DS_DD_9, + /// 3,5", DS, HD, 80 tracks, 18 spt, 512 bytes/sector, MFM + ECMA_125 = DOS_35_HD, + /// 3,5", DS, ED, 80 tracks, 36 spt, 512 bytes/sector, MFM + ECMA_147 = DOS_35_ED, + /// 8", SS, SD, 77 tracks, 26 spt, 128 bytes/sector, FM + ECMA_54 = 273, + /// 8", DS, SD, 77 tracks, 26 spt, 128 bytes/sector, FM + ECMA_59 = 274, + /// 5,25", SS, DD, 35 tracks, 9 spt, 256 bytes/sector, FM, track 0 side 0 = 16 sectors, 128 bytes/sector + ECMA_66 = 275, + /// + /// 8", DS, DD, 77 tracks, 8 spt, 1024 bytes/sector, FM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 + /// side 1 = 26 sectors, 256 bytes/sector + /// + ECMA_69_8 = 276, + /// + /// 8", DS, DD, 77 tracks, 15 spt, 512 bytes/sector, FM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 + /// side 1 = 26 sectors, 256 bytes/sector + /// + ECMA_69_15 = 277, + /// + /// 8", DS, DD, 77 tracks, 26 spt, 256 bytes/sector, FM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 + /// side 1 = 26 sectors, 256 bytes/sector + /// + ECMA_69_26 = 278, + /// + /// 5,25", DS, DD, 40 tracks, 16 spt, 256 bytes/sector, FM, track 0 side 0 = 16 sectors, 128 bytes/sector, track 0 + /// side 1 = 16 sectors, 256 bytes/sector + /// + ECMA_70 = 279, + /// + /// 5,25", DS, DD, 80 tracks, 16 spt, 256 bytes/sector, FM, track 0 side 0 = 16 sectors, 128 bytes/sector, track 0 + /// side 1 = 16 sectors, 256 bytes/sector + /// + ECMA_78 = 280, + /// 5,25", DS, DD, 80 tracks, 9 spt, 512 bytes/sector, FM + ECMA_78_2 = 281, + #endregion ECMA floppy standards, types 270 to 289 + + #region Non-standard PC formats (FDFORMAT, 2M, etc), types 290 to 308 + /// 5,25", DS, DD, 82 tracks, 10 spt, 512 bytes/sector, MFM + FDFORMAT_525_DD = 290, + /// 5,25", DS, HD, 82 tracks, 17 spt, 512 bytes/sector, MFM + FDFORMAT_525_HD = 291, + /// 3,5", DS, DD, 82 tracks, 10 spt, 512 bytes/sector, MFM + FDFORMAT_35_DD = 292, + /// 3,5", DS, HD, 82 tracks, 21 spt, 512 bytes/sector, MFM + FDFORMAT_35_HD = 293, + #endregion Non-standard PC formats (FDFORMAT, 2M, etc), types 290 to 308 + + #region Apricot ACT standard floppy formats, type 309 + /// 3.5", DS, DD, 70 tracks, 9 spt, 512 bytes/sector, MFM + Apricot_35 = 309, + #endregion Apricot ACT standard floppy formats, type 309 + + #region OnStream ADR, types 310 to 319 + ADR2120 = 310, ADR260 = 311, ADR30 = 312, + ADR50 = 313, + #endregion OnStream ADR, types 310 to 319 + + #region Advanced Intelligent Tape, types 320 to 339 + AIT1 = 320, AIT1Turbo = 321, AIT2 = 322, + AIT2Turbo = 323, AIT3 = 324, AIT3Ex = 325, + AIT3Turbo = 326, AIT4 = 327, AIT5 = 328, + AITETurbo = 329, SAIT1 = 330, SAIT2 = 331, + #endregion Advanced Intelligent Tape, types 320 to 339 + + #region Iomega, types 340 to 359 + /// Obsolete type for 8"x11" Bernoulli Box disk + [Obsolete] + Bernoulli = 340, + /// Obsolete type for 5⅓" Bernoulli Box II disks + [Obsolete] + Bernoulli2 = 341, Ditto = 342, DittoMax = 343, Jaz = 344, + Jaz2 = 345, PocketZip = 346, REV120 = 347, + REV35 = 348, REV70 = 349, ZIP100 = 350, + ZIP250 = 351, ZIP750 = 352, + /// 5⅓" Bernoulli Box II disk with 35Mb capacity + Bernoulli35 = 353, + /// 5⅓" Bernoulli Box II disk with 44Mb capacity + Bernoulli44 = 354, + /// 5⅓" Bernoulli Box II disk with 65Mb capacity + Bernoulli65 = 355, + /// 5⅓" Bernoulli Box II disk with 90Mb capacity + Bernoulli90 = 356, + /// 5⅓" Bernoulli Box II disk with 105Mb capacity + Bernoulli105 = 357, + /// 5⅓" Bernoulli Box II disk with 150Mb capacity + Bernoulli150 = 358, + /// 5⅓" Bernoulli Box II disk with 230Mb capacity + Bernoulli230 = 359, + #endregion Iomega, types 340 to 359 + + #region Audio or video media, types 360 to 369 + CompactCassette = 360, Data8 = 361, MiniDV = 362, + /// D/CAS-25: Digital data on Compact Cassette form factor, special magnetic media, 9-track + Dcas25 = 363, + /// D/CAS-85: Digital data on Compact Cassette form factor, special magnetic media, 17-track + Dcas85 = 364, + /// D/CAS-103: Digital data on Compact Cassette form factor, special magnetic media, 21-track + Dcas103 = 365, + #endregion Audio media, types 360 to 369 + + #region CompactFlash Association, types 370 to 379 + CFast = 370, CompactFlash = 371, CompactFlashType2 = 372, + #endregion CompactFlash Association, types 370 to 379 + + #region Digital Audio Tape / Digital Data Storage, types 380 to 389 + DigitalAudioTape = 380, DAT160 = 381, DAT320 = 382, + DAT72 = 383, DDS1 = 384, DDS2 = 385, + DDS3 = 386, DDS4 = 387, + #endregion Digital Audio Tape / Digital Data Storage, types 380 to 389 + + #region DEC, types 390 to 399 + CompactTapeI = 390, CompactTapeII = 391, DECtapeII = 392, + DLTtapeIII = 393, DLTtapeIIIxt = 394, DLTtapeIV = 395, + DLTtapeS4 = 396, SDLT1 = 397, SDLT2 = 398, + VStapeI = 399, + #endregion DEC, types 390 to 399 + + #region Exatape, types 400 to 419 + Exatape15m = 400, Exatape22m = 401, Exatape22mAME = 402, + Exatape28m = 403, Exatape40m = 404, Exatape45m = 405, + Exatape54m = 406, Exatape75m = 407, Exatape76m = 408, + Exatape80m = 409, Exatape106m = 410, Exatape160mXL = 411, + Exatape112m = 412, Exatape125m = 413, Exatape150m = 414, + Exatape170m = 415, Exatape225m = 416, + #endregion Exatape, types 400 to 419 + + #region PCMCIA / ExpressCard, types 420 to 429 + ExpressCard34 = 420, ExpressCard54 = 421, PCCardTypeI = 422, + PCCardTypeII = 423, PCCardTypeIII = 424, PCCardTypeIV = 425, + #endregion PCMCIA / ExpressCard, types 420 to 429 + + #region SyQuest, types 430 to 449 + /// SyQuest 135Mb cartridge for use in EZ135 and EZFlyer drives + EZ135 = 430, + /// SyQuest EZFlyer 230Mb cartridge for use in EZFlyer drive + EZ230 = 431, + /// SyQuest 4.7Gb for use in Quest drive + Quest = 432, + /// SyQuest SparQ 1Gb cartridge + SparQ = 433, + /// SyQuest 5Mb cartridge for SQ306RD drive + SQ100 = 434, + /// SyQuest 10Mb cartridge for SQ312RD drive + SQ200 = 435, + /// SyQuest 15Mb cartridge for SQ319RD drive + SQ300 = 436, + /// SyQuest 105Mb cartridge for SQ3105 and SQ3270 drives + SQ310 = 437, + /// SyQuest 270Mb cartridge for SQ3270 drive + SQ327 = 438, + /// SyQuest 44Mb cartridge for SQ555, SQ5110 and SQ5200C/SQ200 drives + SQ400 = 439, + /// SyQuest 88Mb cartridge for SQ5110 and SQ5200C/SQ200 drives + SQ800 = 440, + /// SyQuest 1.5Gb cartridge for SyJet drive + [Obsolete] + SQ1500 = 441, + /// SyQuest 200Mb cartridge for use in SQ5200C drive + SQ2000 = 442, + /// SyQuest 1.5Gb cartridge for SyJet drive + SyJet = 443, + #endregion SyQuest, types 430 to 449 + + #region Nintendo, types 450 to 469 + FamicomGamePak = 450, GameBoyAdvanceGamePak = 451, GameBoyGamePak = 452, + /// Nintendo GameCube Optical Disc + GOD = 453, N64DD = 454, N64GamePak = 455, NESGamePak = 456, + Nintendo3DSGameCard = 457, NintendoDiskCard = 458, NintendoDSGameCard = 459, + NintendoDSiGameCard = 460, SNESGamePak = 461, SNESGamePakUS = 462, + /// Nintendo Wii Optical Disc + WOD = 463, + /// Nintendo Wii U Optical Disc + WUOD = 464, SwitchGameCard = 465, + #endregion Nintendo, types 450 to 469 + + #region IBM Tapes, types 470 to 479 + IBM3470 = 470, IBM3480 = 471, IBM3490 = 472, + IBM3490E = 473, IBM3592 = 474, + #endregion IBM Tapes, types 470 to 479 + + #region LTO Ultrium, types 480 to 509 + LTO = 480, LTO2 = 481, LTO3 = 482, + LTO3WORM = 483, LTO4 = 484, LTO4WORM = 485, + LTO5 = 486, LTO5WORM = 487, LTO6 = 488, + LTO6WORM = 489, LTO7 = 490, LTO7WORM = 491, + #endregion LTO Ultrium, types 480 to 509 + + #region MemoryStick, types 510 to 519 + MemoryStick = 510, MemoryStickDuo = 511, MemoryStickMicro = 512, + MemoryStickPro = 513, MemoryStickProDuo = 514, + #endregion MemoryStick, types 510 to 519 + + #region SecureDigital, types 520 to 529 + microSD = 520, miniSD = 521, SecureDigital = 522, + #endregion SecureDigital, types 520 to 529 + + #region MultiMediaCard, types 530 to 539 + MMC = 530, MMCmicro = 531, RSMMC = 532, + MMCplus = 533, MMCmobile = 534, + #endregion MultiMediaCard, types 530 to 539 + + #region SLR, types 540 to 569 + MLR1 = 540, MLR1SL = 541, MLR3 = 542, + SLR1 = 543, SLR2 = 544, SLR3 = 545, + SLR32 = 546, SLR32SL = 547, SLR4 = 548, + SLR5 = 549, SLR5SL = 550, SLR6 = 551, + SLRtape7 = 552, SLRtape7SL = 553, SLRtape24 = 554, + SLRtape24SL = 555, SLRtape40 = 556, SLRtape50 = 557, + SLRtape60 = 558, SLRtape75 = 559, SLRtape100 = 560, + SLRtape140 = 561, + #endregion SLR, types 540 to 569 + + #region QIC, types 570 to 589 + QIC11 = 570, QIC120 = 571, QIC1350 = 572, + QIC150 = 573, QIC24 = 574, QIC3010 = 575, + QIC3020 = 576, QIC3080 = 577, QIC3095 = 578, + QIC320 = 579, QIC40 = 580, QIC525 = 581, + QIC80 = 582, + #endregion QIC, types 570 to 589 + + #region StorageTek tapes, types 590 to 609 + STK4480 = 590, STK4490 = 591, STK9490 = 592, + T9840A = 593, T9840B = 594, T9840C = 595, + T9840D = 596, T9940A = 597, T9940B = 598, + T10000A = 599, T10000B = 600, T10000C = 601, + T10000D = 602, + #endregion StorageTek tapes, types 590 to 609 + + #region Travan, types 610 to 619 + Travan = 610, Travan1Ex = 611, Travan3 = 612, + Travan3Ex = 613, Travan4 = 614, Travan5 = 615, + Travan7 = 616, + #endregion Travan, types 610 to 619 + + #region VXA, types 620 to 629 + VXA1 = 620, VXA2 = 621, VXA3 = 622, + #endregion VXA, types 620 to 629 + + #region Magneto-optical, types 630 to 659 + /// 5,25", M.O., WORM, 650Mb, 318750 sectors, 1024 bytes/sector, ECMA-153, ISO 11560 + ECMA_153 = 630, + /// 5,25", M.O., WORM, 600Mb, 581250 sectors, 512 bytes/sector, ECMA-153, ISO 11560 + ECMA_153_512 = 631, + /// 3,5", M.O., RW, 128Mb, 248826 sectors, 512 bytes/sector, ECMA-154, ISO 10090 + ECMA_154 = 632, + /// 5,25", M.O., RW/WORM, 1Gb, 904995 sectors, 512 bytes/sector, ECMA-183, ISO 13481 + ECMA_183_512 = 633, + /// 5,25", M.O., RW/WORM, 1Gb, 498526 sectors, 1024 bytes/sector, ECMA-183, ISO 13481 + ECMA_183 = 634, + /// 5,25", M.O., RW/WORM, 1.2Gb, 1165600 sectors, 512 bytes/sector, ECMA-184, ISO 13549 + ECMA_184_512 = 635, + /// 5,25", M.O., RW/WORM, 1.3Gb, 639200 sectors, 1024 bytes/sector, ECMA-184, ISO 13549 + ECMA_184 = 636, + /// 300mm, M.O., WORM, ??? sectors, 1024 bytes/sector, ECMA-189, ISO 13614 + ECMA_189 = 637, + /// 300mm, M.O., WORM, ??? sectors, 1024 bytes/sector, ECMA-190, ISO 13403 + ECMA_190 = 638, + /// 5,25", M.O., RW/WORM, 936921 or 948770 sectors, 1024 bytes/sector, ECMA-195, ISO 13842 + ECMA_195 = 639, + /// 5,25", M.O., RW/WORM, 1644581 or 1647371 sectors, 512 bytes/sector, ECMA-195, ISO 13842 + ECMA_195_512 = 640, + /// 3,5", M.O., 446325 sectors, 512 bytes/sector, ECMA-201, ISO 13963 + ECMA_201 = 641, + /// 3,5", M.O., 429975 sectors, 512 bytes/sector, embossed, ISO 13963 + ECMA_201_ROM = 642, + /// 3,5", M.O., 371371 sectors, 1024 bytes/sector, ECMA-223 + ECMA_223 = 643, + /// 3,5", M.O., 694929 sectors, 512 bytes/sector, ECMA-223 + ECMA_223_512 = 644, + /// 5,25", M.O., 1244621 sectors, 1024 bytes/sector, ECMA-238, ISO 15486 + ECMA_238 = 645, + /// 3,5", M.O., 310352, 320332 or 321100 sectors, 2048 bytes/sector, ECMA-239, ISO 15498 + ECMA_239 = 646, + /// 356mm, M.O., 14476734 sectors, 1024 bytes/sector, ECMA-260, ISO 15898 + ECMA_260 = 647, + /// 356mm, M.O., 24445990 sectors, 1024 bytes/sector, ECMA-260, ISO 15898 + ECMA_260_Double = 648, + /// 5,25", M.O., 1128134 sectors, 2048 bytes/sector, ECMA-280, ISO 18093 + ECMA_280 = 649, + /// 300mm, M.O., 7355716 sectors, 2048 bytes/sector, ECMA-317, ISO 20162 + ECMA_317 = 650, + /// 5,25", M.O., 1095840 sectors, 4096 bytes/sector, ECMA-322, ISO 22092, 9.1Gb/cart + ECMA_322 = 651, + /// 5,25", M.O., 2043664 sectors, 2048 bytes/sector, ECMA-322, ISO 22092, 8.6Gb/cart + ECMA_322_2k = 652, + /// 3,5", M.O., 605846 sectors, 2048 bytes/sector, Cherry Book, GigaMo, ECMA-351, ISO 17346 + GigaMo = 653, + /// 3,5", M.O., 1063146 sectors, 2048 bytes/sector, Cherry Book 2, GigaMo 2, ECMA-353, ISO 22533 + GigaMo2 = 654, + /// 5,25", M.O., 1263472 sectors, 2048 bytes/sector, ISO 15286, 5.2Gb/cart + ISO_15286 = 655, + /// 5,25", M.O., 2319786 sectors, 1024 bytes/sector, ISO 15286, 4.8Gb/cart + ISO_15286_1024 = 656, + /// 5,25", M.O., ??????? sectors, 512 bytes/sector, ISO 15286, 4.1Gb/cart + ISO_15286_512 = 657, + /// 5,25", M.O., 314569 sectors, 1024 bytes/sector, ISO 10089, 650Mb/cart + ISO_10089 = 658, + /// 5,25", M.O., ?????? sectors, 512 bytes/sector, ISO 10089, 594Mb/cart + ISO_10089_512 = 659, + #endregion Magneto-optical, types 630 to 659 + + #region Other floppy standards, types 660 to 689 + CompactFloppy = 660, DemiDiskette = 661, + /// 3.5", 652 tracks, 2 sides, 512 bytes/sector, Floptical, ECMA-207, ISO 14169 + Floptical = 662, HiFD = 663, QuickDisk = 664, UHD144 = 665, + VideoFloppy = 666, Wafer = 667, ZXMicrodrive = 668, + /// 5.25", SS, DD, 77 tracks, 16 spt, 256 bytes/sector, MFM, 100 tpi, 300rpm + MetaFloppy_Mod_II = 669, + #endregion Other floppy standards, types 660 to 669 + + #region Miscellaneous, types 670 to 689 + BeeCard = 670, Borsu = 671, DataStore = 672, + DIR = 673, DST = 674, DTF = 675, + DTF2 = 676, Flextra3020 = 677, Flextra3225 = 678, + HiTC1 = 679, HiTC2 = 680, LT1 = 681, + MiniCard = 872, Orb = 683, Orb5 = 684, + SmartMedia = 685, xD = 686, XQD = 687, + DataPlay = 688, + #endregion Miscellaneous, types 670 to 689 + + #region Apple specific media, types 690 to 699 + AppleProfile = 690, AppleWidget = 691, AppleHD20 = 692, + PriamDataTower = 693, Pippin = 694, + #endregion Apple specific media, types 690 to 699 + + #region DEC hard disks, types 700 to 729 + /// + /// 2382 cylinders, 4 tracks/cylinder, 42 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, + /// 204890112 bytes + /// + RA60 = 700, + /// + /// 546 cylinders, 14 tracks/cylinder, 31 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, + /// 121325568 bytes + /// + RA80 = 701, + /// + /// 1248 cylinders, 14 tracks/cylinder, 51 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, + /// 456228864 bytes + /// + RA81 = 702, + /// + /// 302 cylinders, 4 tracks/cylinder, 42 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 25976832 + /// bytes + /// + RC25 = 703, + /// + /// 615 cylinders, 4 tracks/cylinder, 17 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 21411840 + /// bytes + /// + RD31 = 704, + /// + /// 820 cylinders, 6 tracks/cylinder, 17 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 42823680 + /// bytes + /// + RD32 = 705, + /// + /// 306 cylinders, 4 tracks/cylinder, 17 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 10653696 + /// bytes + /// + RD51 = 706, + /// + /// 480 cylinders, 7 tracks/cylinder, 18 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 30965760 + /// bytes + /// + RD52 = 707, + /// + /// 1024 cylinders, 7 tracks/cylinder, 18 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, + /// 75497472 bytes + /// + RD53 = 708, + /// + /// 1225 cylinders, 8 tracks/cylinder, 18 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, + /// 159936000 bytes + /// + RD54 = 709, + /// + /// 411 cylinders, 3 tracks/cylinder, 22 sectors/track, 256 words/sector, 16 bits/word, 512 bytes/sector, 13888512 + /// bytes + /// + RK06 = 710, + /// + /// 411 cylinders, 3 tracks/cylinder, 20 sectors/track, 256 words/sector, 18 bits/word, 576 bytes/sector, 14204160 + /// bytes + /// + RK06_18 = 711, + /// + /// 815 cylinders, 3 tracks/cylinder, 22 sectors/track, 256 words/sector, 16 bits/word, 512 bytes/sector, 27540480 + /// bytes + /// + RK07 = 712, + /// + /// 815 cylinders, 3 tracks/cylinder, 20 sectors/track, 256 words/sector, 18 bits/word, 576 bytes/sector, 28166400 + /// bytes + /// + RK07_18 = 713, + /// + /// 823 cylinders, 5 tracks/cylinder, 32 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 67420160 + /// bytes + /// + RM02 = 714, + /// + /// 823 cylinders, 5 tracks/cylinder, 32 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 67420160 + /// bytes + /// + RM03 = 715, + /// + /// 823 cylinders, 19 tracks/cylinder, 32 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, + /// 256196608 bytes + /// + RM05 = 716, + /// + /// 203 cylinders, 10 tracks/cylinder, 22 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, + /// 22865920 bytes + /// + RP02 = 717, + /// + /// 203 cylinders, 10 tracks/cylinder, 20 sectors/track, 128 words/sector, 36 bits/word, 576 bytes/sector, + /// 23385600 bytes + /// + RP02_18 = 718, + /// + /// 400 cylinders, 10 tracks/cylinder, 22 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, + /// 45056000 bytes + /// + RP03 = 719, + /// + /// 400 cylinders, 10 tracks/cylinder, 20 sectors/track, 128 words/sector, 36 bits/word, 576 bytes/sector, + /// 46080000 bytes + /// + RP03_18 = 720, + /// + /// 411 cylinders, 19 tracks/cylinder, 22 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, + /// 87960576 bytes + /// + RP04 = 721, + /// + /// 411 cylinders, 19 tracks/cylinder, 20 sectors/track, 128 words/sector, 36 bits/word, 576 bytes/sector, + /// 89959680 bytes + /// + RP04_18 = 722, + /// + /// 411 cylinders, 19 tracks/cylinder, 22 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, + /// 87960576 bytes + /// + RP05 = 723, + /// + /// 411 cylinders, 19 tracks/cylinder, 20 sectors/track, 128 words/sector, 36 bits/word, 576 bytes/sector, + /// 89959680 bytes + /// + RP05_18 = 724, + /// + /// 815 cylinders, 19 tracks/cylinder, 22 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, + /// 174423040 bytes + /// + RP06 = 725, + /// + /// 815 cylinders, 19 tracks/cylinder, 20 sectors/track, 128 words/sector, 36 bits/word, 576 bytes/sector, + /// 178387200 bytes + /// + RP06_18 = 726, + #endregion DEC hard disks, types 700 to 729 + + #region Imation, types 730 to 739 + LS120 = 730, LS240 = 731, FD32MB = 732, + RDX = 733, + /// Imation 320Gb RDX + RDX320 = 734, + #endregion Imation, types 730 to 739 + + #region VideoNow, types 740 to 749 + VideoNow = 740, VideoNowColor = 741, VideoNowXp = 742, + #endregion + + #region Iomega, types 750 to 759 + /// 8"x11" Bernoulli Box disk with 10Mb capacity + Bernoulli10 = 750, + /// 8"x11" Bernoulli Box disk with 20Mb capacity + Bernoulli20 = 751, + /// 5⅓" Bernoulli Box II disk with 20Mb capacity + BernoulliBox2_20 = 752, + #endregion Iomega, types 750 to 759 + + #region Kodak, types 760 to 769 + KodakVerbatim3 = 760, KodakVerbatim6 = 761, KodakVerbatim12 = 762, + #endregion Kodak, types 760 to 769 + + #region Sony and Panasonic Blu-ray derived, types 770 to 799 + /// Professional Disc for video, single layer, rewritable, 23Gb + ProfessionalDisc = 770, + /// Professional Disc for video, dual layer, rewritable, 50Gb + ProfessionalDiscDual = 771, + /// Professional Disc for video, triple layer, rewritable, 100Gb + ProfessionalDiscTriple = 772, + /// Professional Disc for video, quad layer, write once, 128Gb + ProfessionalDiscQuad = 773, + /// Professional Disc for DATA, single layer, rewritable, 23Gb + PDD = 774, + /// Professional Disc for DATA, single layer, write once, 23Gb + PDD_WORM = 775, + /// Archival Disc, 1st gen., 300Gb + ArchivalDisc = 776, + /// Archival Disc, 2nd gen., 500Gb + ArchivalDisc2 = 777, + /// Archival Disc, 3rd gen., 1Tb + ArchivalDisc3 = 778, + /// Optical Disc archive, 1st gen., write once, 300Gb + ODC300R = 779, + /// Optical Disc archive, 1st gen., rewritable, 300Gb + ODC300RE = 780, + /// Optical Disc archive, 2nd gen., write once, 600Gb + ODC600R = 781, + /// Optical Disc archive, 2nd gen., rewritable, 600Gb + ODC600RE = 782, + /// Optical Disc archive, 3rd gen., rewritable, 1200Gb + ODC1200RE = 783, + /// Optical Disc archive, 3rd gen., write once, 1500Gb + ODC1500R = 784, + /// Optical Disc archive, 4th gen., write once, 3300Gb + ODC3300R = 785, + /// Optical Disc archive, 5th gen., write once, 5500Gb + ODC5500R = 786, + #endregion Sony and Panasonic Blu-ray derived, types 770 to 799 + + #region Magneto-optical, types 800 to 819 + /// 5,25", M.O., 4383356 sectors, 1024 bytes/sector, ECMA-322, ISO 22092, 9.1Gb/cart + ECMA_322_1k = 800, + /// 5,25", M.O., ??????? sectors, 512 bytes/sector, ECMA-322, ISO 22092, 9.1Gb/cart + ECMA_322_512 = 801, + /// 5,25", M.O., 1273011 sectors, 1024 bytes/sector, ISO 14517, 2.6Gb/cart + ISO_14517 = 802, + /// 5,25", M.O., 2244958 sectors, 512 bytes/sector, ISO 14517, 2.3Gb/cart + ISO_14517_512 = 803, + /// 3,5", M.O., 1041500 sectors, 512 bytes/sector, ISO 15041, 540Mb/cart + ISO_15041_512 = 804, + #endregion Magneto-optical, types 800 to 819 + + #region More floppy formats, types 820 to deprecated + /// 5.25", SS, DD, 35 tracks, 16 spt, 256 bytes/sector, MFM, 48 tpi, ???rpm + MetaFloppy_Mod_I = 820, + #endregion + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/MediaType.csv b/Aaru.CommonTypes/MediaType.csv new file mode 100644 index 000000000..cb1b3378a --- /dev/null +++ b/Aaru.CommonTypes/MediaType.csv @@ -0,0 +1,532 @@ +Enum,Value,Summary +"Unknown",0,"Unknown disk type" +"UnknownMO",1,"Unknown magneto-optical" +"GENERIC_HDD",2,"Generic hard disk" +"Microdrive",3,"Microdrive type hard disk" +"Zone_HDD",4,"Zoned hard disk" +"FlashDrive",5,"USB flash drives" +"UnknownTape",6,"Unknown data tape" +"CD",10,"Any unknown or standard violating CD" +"CDDA",11,"CD Digital Audio (Red Book)" +"CDG",12,"CD+G (Red Book)" +"CDEG",13,"CD+EG (Red Book)" +"CDI",14,"CD-i (Green Book)" +"CDROM",15,"CD-ROM (Yellow Book)" +"CDROMXA",16,"CD-ROM XA (Yellow Book)" +"CDPLUS",17,"CD+ (Blue Book)" +"CDMO",18,"CD-MO (Orange Book)" +"CDR",19,"CD-Recordable (Orange Book)" +"CDRW",20,"CD-ReWritable (Orange Book)" +"CDMRW",21,"Mount-Rainier CD-RW" +"VCD",22,"Video CD (White Book)" +"SVCD",23,"Super Video CD (White Book)" +"PCD",24,"Photo CD (Beige Book)" +"SACD",25,"Super Audio CD (Scarlet Book)" +"DDCD",26,"Double-Density CD-ROM (Purple Book)" +"DDCDR",27,"DD CD-R (Purple Book)" +"DDCDRW",28,"DD CD-RW (Purple Book)" +"DTSCD",29,"DTS audio CD (non-standard)" +"CDMIDI",30,"CD-MIDI (Red Book)" +"CDV",31,"CD-Video (ISO/IEC 61104)" +"PD650",32,"120mm, Phase-Change, 1298496 sectors, 512 bytes/sector, PD650, ECMA-240, ISO 15485" +"PD650_WORM",33,"120mm, Write-Once, 1281856 sectors, 512 bytes/sector, PD650, ECMA-240, ISO 15485" +"CDIREADY",34,"CD-i Ready, contains a track before the first TOC track, in mode 2, and all TOC tracks are Audio. Subchannel marks track as audio pause." +"FMTOWNS",35, +"DVDROM",40,"DVD-ROM (applies to DVD Video and DVD Audio)" +"DVDR",41,"DVD-R" +"DVDRW",42,"DVD-RW" +"DVDPR",43,"DVD+R" +"DVDPRW",44,"DVD+RW" +"DVDPRWDL",45,"DVD+RW DL" +"DVDRDL",46,"DVD-R DL" +"DVDPRDL",47,"DVD+R DL" +"DVDRAM",48,"DVD-RAM" +"DVDRWDL",49,"DVD-RW DL" +"DVDDownload",50,"DVD-Download" +"HDDVDROM",51,"HD DVD-ROM (applies to HD DVD Video)" +"HDDVDRAM",52,"HD DVD-RAM" +"HDDVDR",53,"HD DVD-R" +"HDDVDRW",54,"HD DVD-RW" +"HDDVDRDL",55,"HD DVD-R DL" +"HDDVDRWDL",56,"HD DVD-RW DL" +"BDROM",60,"BD-ROM (and BD Video)" +"BDR",61,"BD-R" +"BDRE",62,"BD-RE" +"BDRXL",63,"BD-R XL" +"BDREXL",64,"BD-RE XL" +"UHDBD",65,"Ultra HD Blu-ray" +"EVD",70,"Enhanced Versatile Disc" +"FVD",71,"Forward Versatile Disc" +"HVD",72,"Holographic Versatile Disc" +"CBHD",73,"China Blue High Definition" +"HDVMD",74,"High Definition Versatile Multilayer Disc" +"VCDHD",75,"Versatile Compact Disc High Density" +"SVOD",76,"Stacked Volumetric Optical Disc" +"FDDVD",77,"Five Dimensional disc" +"CVD",78,"China Video Disc" +"LD",80,"Pioneer LaserDisc" +"LDROM",81,"Pioneer LaserDisc data" +"LDROM2",82, +"LVROM",83, +"MegaLD",84, +"CRVdisc",85,"Writable LaserDisc with support for component video" +"HiMD",90,"Sony Hi-MD" +"MD",91,"Sony MiniDisc" +"MDData",92,"Sony MD-Data" +"MDData2",93,"Sony MD-Data2" +"MD60",94,"Sony MiniDisc, 60 minutes, formatted with Hi-MD format" +"MD74",95,"Sony MiniDisc, 74 minutes, formatted with Hi-MD format" +"MD80",96,"Sony MiniDisc, 80 minutes, formatted with Hi-MD format" +"UDO",100,"5.25"", Phase-Change, 1834348 sectors, 8192 bytes/sector, Ultra Density Optical, ECMA-350, ISO 17345" +"UDO2",101,"5.25"", Phase-Change, 3669724 sectors, 8192 bytes/sector, Ultra Density Optical 2, ECMA-380, ISO 11976" +"UDO2_WORM",102,"5.25"", Write-Once, 3668759 sectors, 8192 bytes/sector, Ultra Density Optical 2, ECMA-380, ISO 11976" +"PlayStationMemoryCard",110, +"PlayStationMemoryCard2",111, +"PS1CD",112,"Sony PlayStation game CD" +"PS2CD",113,"Sony PlayStation 2 game CD" +"PS2DVD",114,"Sony PlayStation 2 game DVD" +"PS3DVD",115,"Sony PlayStation 3 game DVD" +"PS3BD",116,"Sony PlayStation 3 game Blu-ray" +"PS4BD",117,"Sony PlayStation 4 game Blu-ray" +"UMD",118,"Sony PlayStation Portable Universal Media Disc (ECMA-365)" +"PlayStationVitaGameCard",119, +"PS5BD",120,"Sony PlayStation 5 game Ultra HD Blu-ray" +"XGD",130,"Microsoft X-box Game Disc" +"XGD2",131,"Microsoft X-box 360 Game Disc" +"XGD3",132,"Microsoft X-box 360 Game Disc" +"XGD4",133,"Microsoft X-box One Game Disc" +"MEGACD",150,"Sega MegaCD" +"SATURNCD",151,"Sega Saturn disc" +"GDROM",152,"Sega/Yamaha Gigabyte Disc" +"GDR",153,"Sega/Yamaha recordable Gigabyte Disc" +"SegaCard",154, +"MilCD",155, +"HuCard",170,"PC-Engine / TurboGrafx cartridge" +"SuperCDROM2",171,"PC-Engine / TurboGrafx CD" +"JaguarCD",172,"Atari Jaguar CD" +"ThreeDO",173,"3DO CD" +"PCFX",174,"NEC PC-FX" +"NeoGeoCD",175,"NEO-GEO CD" +"CDTV",176,"Commodore CDTV" +"CD32",177,"Amiga CD32" +"Nuon",178,"Nuon (DVD based videogame console)" +"Playdia",179,"Bandai Playdia" +"Apple32SS",180,"5.25"", SS, DD, 35 tracks, 13 spt, 256 bytes/sector, GCR" +"Apple32DS",181,"5.25"", DS, DD, 35 tracks, 13 spt, 256 bytes/sector, GCR" +"Apple33SS",182,"5.25"", SS, DD, 35 tracks, 16 spt, 256 bytes/sector, GCR" +"Apple33DS",183,"5.25"", DS, DD, 35 tracks, 16 spt, 256 bytes/sector, GCR" +"AppleSonySS",184,"3.5"", SS, DD, 80 tracks, 8 to 12 spt, 512 bytes/sector, GCR" +"AppleSonyDS",185,"3.5"", DS, DD, 80 tracks, 8 to 12 spt, 512 bytes/sector, GCR" +"AppleFileWare",186,"5.25"", DS, ?D, ?? tracks, ?? spt, 512 bytes/sector, GCR, opposite side heads, aka Twiggy" +"DOS_525_SS_DD_8",190,"5.25"", SS, DD, 40 tracks, 8 spt, 512 bytes/sector, MFM" +"DOS_525_SS_DD_9",191,"5.25"", SS, DD, 40 tracks, 9 spt, 512 bytes/sector, MFM" +"DOS_525_DS_DD_8",192,"5.25"", DS, DD, 40 tracks, 8 spt, 512 bytes/sector, MFM" +"DOS_525_DS_DD_9",193,"5.25"", DS, DD, 40 tracks, 9 spt, 512 bytes/sector, MFM" +"DOS_525_HD",194,"5.25"", DS, HD, 80 tracks, 15 spt, 512 bytes/sector, MFM" +"DOS_35_SS_DD_8",195,"3.5"", SS, DD, 80 tracks, 8 spt, 512 bytes/sector, MFM" +"DOS_35_SS_DD_9",196,"3.5"", SS, DD, 80 tracks, 9 spt, 512 bytes/sector, MFM" +"DOS_35_DS_DD_8",197,"3.5"", DS, DD, 80 tracks, 8 spt, 512 bytes/sector, MFM" +"DOS_35_DS_DD_9",198,"3.5"", DS, DD, 80 tracks, 9 spt, 512 bytes/sector, MFM" +"DOS_35_HD",199,"3.5"", DS, HD, 80 tracks, 18 spt, 512 bytes/sector, MFM" +"DOS_35_ED",200,"3.5"", DS, ED, 80 tracks, 36 spt, 512 bytes/sector, MFM" +"DMF",201,"3.5"", DS, HD, 80 tracks, 21 spt, 512 bytes/sector, MFM" +"DMF_82",202,"3.5"", DS, HD, 82 tracks, 21 spt, 512 bytes/sector, MFM" +"XDF_525",203,"5.25"", DS, HD, 80 tracks, ? spt, ??? + ??? + ??? bytes/sector, MFM track 0 = ??15 sectors, 512 bytes/sector, falsified to DOS as 19 spt, 512 bps" +"XDF_35",204,"3.5"", DS, HD, 80 tracks, 4 spt, 8192 + 2048 + 1024 + 512 bytes/sector, MFM track 0 = 19 sectors, 512 bytes/sector, falsified to DOS as 23 spt, 512 bps" +"IBM23FD",210,"8"", SS, SD, 32 tracks, 8 spt, 319 bytes/sector, FM" +"IBM33FD_128",211,"8"", SS, SD, 73 tracks, 26 spt, 128 bytes/sector, FM" +"IBM33FD_256",212,"8"", SS, SD, 74 tracks, 15 spt, 256 bytes/sector, FM, track 0 = 26 sectors, 128 bytes/sector" +"IBM33FD_512",213,"8"", SS, SD, 74 tracks, 8 spt, 512 bytes/sector, FM, track 0 = 26 sectors, 128 bytes/sector" +"IBM43FD_128",214,"8"", DS, SD, 74 tracks, 26 spt, 128 bytes/sector, FM, track 0 = 26 sectors, 128 bytes/sector" +"IBM43FD_256",215,"8"", DS, SD, 74 tracks, 26 spt, 256 bytes/sector, FM, track 0 = 26 sectors, 128 bytes/sector" +"IBM53FD_256",216,"8"", DS, DD, 74 tracks, 26 spt, 256 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector" +"IBM53FD_512",217,"8"", DS, DD, 74 tracks, 15 spt, 512 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector" +"IBM53FD_1024",218,"8"", DS, DD, 74 tracks, 8 spt, 1024 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector" +"RX01",220,"8"", SS, DD, 77 tracks, 26 spt, 128 bytes/sector, FM" +"RX02",221,"8"", SS, DD, 77 tracks, 26 spt, 256 bytes/sector, FM/MFM" +"RX03",222,"8"", DS, DD, 77 tracks, 26 spt, 256 bytes/sector, FM/MFM" +"RX50",223,"5.25"", SS, DD, 80 tracks, 10 spt, 512 bytes/sector, MFM" +"ACORN_525_SS_SD_40",230,"5,25"", SS, SD, 40 tracks, 10 spt, 256 bytes/sector, FM" +"ACORN_525_SS_SD_80",231,"5,25"", SS, SD, 80 tracks, 10 spt, 256 bytes/sector, FM" +"ACORN_525_SS_DD_40",232,"5,25"", SS, DD, 40 tracks, 16 spt, 256 bytes/sector, MFM" +"ACORN_525_SS_DD_80",233,"5,25"", SS, DD, 80 tracks, 16 spt, 256 bytes/sector, MFM" +"ACORN_525_DS_DD",234,"5,25"", DS, DD, 80 tracks, 16 spt, 256 bytes/sector, MFM" +"ACORN_35_DS_DD",235,"3,5"", DS, DD, 80 tracks, 5 spt, 1024 bytes/sector, MFM" +"ACORN_35_DS_HD",236,"3,5"", DS, HD, 80 tracks, 10 spt, 1024 bytes/sector, MFM" +"ATARI_525_SD",240,"5,25"", SS, SD, 40 tracks, 18 spt, 128 bytes/sector, FM" +"ATARI_525_ED",241,"5,25"", SS, ED, 40 tracks, 26 spt, 128 bytes/sector, MFM" +"ATARI_525_DD",242,"5,25"", SS, DD, 40 tracks, 18 spt, 256 bytes/sector, MFM" +"ATARI_35_SS_DD",243,"3,5"", SS, DD, 80 tracks, 10 spt, 512 bytes/sector, MFM" +"ATARI_35_DS_DD",244,"3,5"", DS, DD, 80 tracks, 10 spt, 512 bytes/sector, MFM" +"ATARI_35_SS_DD_11",245,"3,5"", SS, DD, 80 tracks, 11 spt, 512 bytes/sector, MFM" +"ATARI_35_DS_DD_11",246,"3,5"", DS, DD, 80 tracks, 11 spt, 512 bytes/sector, MFM" +"CBM_35_DD",250,"3,5"", DS, DD, 80 tracks, 10 spt, 512 bytes/sector, MFM (1581)" +"CBM_AMIGA_35_DD",251,"3,5"", DS, DD, 80 tracks, 11 spt, 512 bytes/sector, MFM (Amiga)" +"CBM_AMIGA_35_HD",252,"3,5"", DS, HD, 80 tracks, 22 spt, 512 bytes/sector, MFM (Amiga)" +"CBM_1540",253,"5,25"", SS, DD, 35 tracks, GCR" +"CBM_1540_Ext",254,"5,25"", SS, DD, 40 tracks, GCR" +"CBM_1571",255,"5,25"", DS, DD, 35 tracks, GCR" +"NEC_8_SD",260,"8"", DS, SD, 77 tracks, 26 spt, 128 bytes/sector, FM" +"NEC_8_DD",261,"8"", DS, DD, 77 tracks, 26 spt, 256 bytes/sector, MFM" +"NEC_525_SS",262,"5.25"", SS, SD, 80 tracks, 16 spt, 256 bytes/sector, FM" +"NEC_525_DS",263,"5.25"", DS, SD, 80 tracks, 16 spt, 256 bytes/sector, MFM" +"NEC_525_HD",264,"5,25"", DS, HD, 77 tracks, 8 spt, 1024 bytes/sector, MFM" +"NEC_35_HD_8",265,"3,5"", DS, HD, 77 tracks, 8 spt, 1024 bytes/sector, MFM, aka mode 3" +"NEC_35_HD_15",266,"3,5"", DS, HD, 80 tracks, 15 spt, 512 bytes/sector, MFM" +"NEC_35_TD",267,"3,5"", DS, TD, 240 tracks, 38 spt, 512 bytes/sector, MFM" +"SHARP_525",NEC_525_HD,"5,25"", DS, HD, 77 tracks, 8 spt, 1024 bytes/sector, MFM" +"SHARP_525_9",268,"3,5"", DS, HD, 80 tracks, 9 spt, 1024 bytes/sector, MFM" +"SHARP_35",NEC_35_HD_8,"3,5"", DS, HD, 77 tracks, 8 spt, 1024 bytes/sector, MFM" +"SHARP_35_9",269,"3,5"", DS, HD, 80 tracks, 9 spt, 1024 bytes/sector, MFM" +"ECMA_99_8",270,"5,25"", DS, DD, 80 tracks, 8 spt, 1024 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector" +"ECMA_99_15",271,"5,25"", DS, DD, 77 tracks, 15 spt, 512 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector" +"ECMA_99_26",272,"5,25"", DS, DD, 77 tracks, 26 spt, 256 bytes/sector, MFM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector" +"ECMA_100",DOS_35_DS_DD_9,"3,5"", DS, DD, 80 tracks, 9 spt, 512 bytes/sector, MFM" +"ECMA_125",DOS_35_HD,"3,5"", DS, HD, 80 tracks, 18 spt, 512 bytes/sector, MFM" +"ECMA_147",DOS_35_ED,"3,5"", DS, ED, 80 tracks, 36 spt, 512 bytes/sector, MFM" +"ECMA_54",273,"8"", SS, SD, 77 tracks, 26 spt, 128 bytes/sector, FM" +"ECMA_59",274,"8"", DS, SD, 77 tracks, 26 spt, 128 bytes/sector, FM" +"ECMA_66",275,"5,25"", SS, DD, 35 tracks, 9 spt, 256 bytes/sector, FM, track 0 side 0 = 16 sectors, 128 bytes/sector" +"ECMA_69_8",276,"8"", DS, DD, 77 tracks, 8 spt, 1024 bytes/sector, FM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector" +"ECMA_69_15",277,"8"", DS, DD, 77 tracks, 15 spt, 512 bytes/sector, FM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector" +"ECMA_69_26",278,"8"", DS, DD, 77 tracks, 26 spt, 256 bytes/sector, FM, track 0 side 0 = 26 sectors, 128 bytes/sector, track 0 side 1 = 26 sectors, 256 bytes/sector" +"ECMA_70",279,"5,25"", DS, DD, 40 tracks, 16 spt, 256 bytes/sector, FM, track 0 side 0 = 16 sectors, 128 bytes/sector, track 0 side 1 = 16 sectors, 256 bytes/sector" +"ECMA_78",280,"5,25"", DS, DD, 80 tracks, 16 spt, 256 bytes/sector, FM, track 0 side 0 = 16 sectors, 128 bytes/sector, track 0 side 1 = 16 sectors, 256 bytes/sector" +"ECMA_78_2",281,"5,25"", DS, DD, 80 tracks, 9 spt, 512 bytes/sector, FM" +"FDFORMAT_525_DD",290,"5,25"", DS, DD, 82 tracks, 10 spt, 512 bytes/sector, MFM" +"FDFORMAT_525_HD",291,"5,25"", DS, HD, 82 tracks, 17 spt, 512 bytes/sector, MFM" +"FDFORMAT_35_DD",292,"3,5"", DS, DD, 82 tracks, 10 spt, 512 bytes/sector, MFM" +"FDFORMAT_35_HD",293,"3,5"", DS, HD, 82 tracks, 21 spt, 512 bytes/sector, MFM" +"Apricot_35",309,"3.5"", DS, DD, 70 tracks, 9 spt, 512 bytes/sector, MFM" +"ADR2120",310, +"ADR260",311, +"ADR30",312, +"ADR50",313, +"AIT1",320, +"AIT1Turbo",321, +"AIT2",322, +"AIT2Turbo",323, +"AIT3",324, +"AIT3Ex",325, +"AIT3Turbo",326, +"AIT4",327, +"AIT5",328, +"AITETurbo",329, +"SAIT1",330, +"SAIT2",331, +"Bernoulli",340,"Obsolete type for 8""x11"" Bernoulli Box disk" +"Bernoulli2",341,"Obsolete type for 5⅓"" Bernoulli Box II disks" +"Ditto",342, +"DittoMax",343, +"Jaz",344, +"Jaz2",345, +"PocketZip",346, +"REV120",347, +"REV35",348, +"REV70",349, +"ZIP100",350, +"ZIP250",351, +"ZIP750",352, +"Bernoulli35",353,"5⅓"" Bernoulli Box II disk with 35Mb capacity" +"Bernoulli44",354,"5⅓"" Bernoulli Box II disk with 44Mb capacity" +"Bernoulli65",355,"5⅓"" Bernoulli Box II disk with 65Mb capacity" +"Bernoulli90",356,"5⅓"" Bernoulli Box II disk with 90Mb capacity" +"Bernoulli105",357,"5⅓"" Bernoulli Box II disk with 105Mb capacity" +"Bernoulli150",358,"5⅓"" Bernoulli Box II disk with 150Mb capacity" +"Bernoulli230",359,"5⅓"" Bernoulli Box II disk with 230Mb capacity" +"CompactCassette",360, +"Data8",361, +"MiniDV",362, +"Dcas25",363,"D/CAS-25: Digital data on Compact Cassette form factor, special magnetic media, 9-track" +"Dcas85",364,"D/CAS-85: Digital data on Compact Cassette form factor, special magnetic media, 17-track" +"Dcas103",365,"D/CAS-103: Digital data on Compact Cassette form factor, special magnetic media, 21-track" +"CFast",370, +"CompactFlash",371, +"CompactFlashType2",372, +"DigitalAudioTape",380, +"DAT160",381, +"DAT320",382, +"DAT72",383, +"DDS1",384, +"DDS2",385, +"DDS3",386, +"DDS4",387, +"CompactTapeI",390, +"CompactTapeII",391, +"DECtapeII",392, +"DLTtapeIII",393, +"DLTtapeIIIxt",394, +"DLTtapeIV",395, +"DLTtapeS4",396, +"SDLT1",397, +"SDLT2",398, +"VStapeI",399, +"Exatape15m",400, +"Exatape22m",401, +"Exatape22mAME",402, +"Exatape28m",403, +"Exatape40m",404, +"Exatape45m",405, +"Exatape54m",406, +"Exatape75m",407, +"Exatape76m",408, +"Exatape80m",409, +"Exatape106m",410, +"Exatape160mXL",411, +"Exatape112m",412, +"Exatape125m",413, +"Exatape150m",414, +"Exatape170m",415, +"Exatape225m",416, +"ExpressCard34",420, +"ExpressCard54",421, +"PCCardTypeI",422, +"PCCardTypeII",423, +"PCCardTypeIII",424, +"PCCardTypeIV",425, +"EZ135",430,"SyQuest 135Mb cartridge for use in EZ135 and EZFlyer drives" +"EZ230",431,"SyQuest EZFlyer 230Mb cartridge for use in EZFlyer drive" +"Quest",432,"SyQuest 4.7Gb for use in Quest drive" +"SparQ",433,"SyQuest SparQ 1Gb cartridge" +"SQ100",434,"SyQuest 5Mb cartridge for SQ306RD drive" +"SQ200",435,"SyQuest 10Mb cartridge for SQ312RD drive" +"SQ300",436,"SyQuest 15Mb cartridge for SQ319RD drive" +"SQ310",437,"SyQuest 105Mb cartridge for SQ3105 and SQ3270 drives" +"SQ327",438,"SyQuest 270Mb cartridge for SQ3270 drive" +"SQ400",439,"SyQuest 44Mb cartridge for SQ555, SQ5110 and SQ5200C/SQ200 drives" +"SQ800",440,"SyQuest 88Mb cartridge for SQ5110 and SQ5200C/SQ200 drives" +"SQ1500",441,"SyQuest 1.5Gb cartridge for SyJet drive" +"SQ2000",442,"SyQuest 200Mb cartridge for use in SQ5200C drive" +"SyJet",443,"SyQuest 1.5Gb cartridge for SyJet drive" +"FamicomGamePak",450, +"GameBoyAdvanceGamePak",451, +"GameBoyGamePak",452, +"GOD",453,"Nintendo GameCube Optical Disc" +"N64DD",454, +"N64GamePak",455, +"NESGamePak",456, +"Nintendo3DSGameCard",457, +"NintendoDiskCard",458, +"NintendoDSGameCard",459, +"NintendoDSiGameCard",460, +"SNESGamePak",461, +"SNESGamePakUS",462, +"WOD",463,"Nintendo Wii Optical Disc" +"WUOD",464,"Nintendo Wii U Optical Disc" +"SwitchGameCard",465, +"IBM3470",470, +"IBM3480",471, +"IBM3490",472, +"IBM3490E",473, +"IBM3592",474, +"LTO",480, +"LTO2",481, +"LTO3",482, +"LTO3WORM",483, +"LTO4",484, +"LTO4WORM",485, +"LTO5",486, +"LTO5WORM",487, +"LTO6",488, +"LTO6WORM",489, +"LTO7",490, +"LTO7WORM",491, +"MemoryStick",510, +"MemoryStickDuo",511, +"MemoryStickMicro",512, +"MemoryStickPro",513, +"MemoryStickProDuo",514, +"microSD",520, +"miniSD",521, +"SecureDigital",522, +"MMC",530, +"MMCmicro",531, +"RSMMC",532, +"MMCplus",533, +"MMCmobile",534, +"MLR1",540, +"MLR1SL",541, +"MLR3",542, +"SLR1",543, +"SLR2",544, +"SLR3",545, +"SLR32",546, +"SLR32SL",547, +"SLR4",548, +"SLR5",549, +"SLR5SL",550, +"SLR6",551, +"SLRtape7",552, +"SLRtape7SL",553, +"SLRtape24",554, +"SLRtape24SL",555, +"SLRtape40",556, +"SLRtape50",557, +"SLRtape60",558, +"SLRtape75",559, +"SLRtape100",560, +"SLRtape140",561, +"QIC11",570, +"QIC120",571, +"QIC1350",572, +"QIC150",573, +"QIC24",574, +"QIC3010",575, +"QIC3020",576, +"QIC3080",577, +"QIC3095",578, +"QIC320",579, +"QIC40",580, +"QIC525",581, +"QIC80",582, +"STK4480",590, +"STK4490",591, +"STK9490",592, +"T9840A",593, +"T9840B",594, +"T9840C",595, +"T9840D",596, +"T9940A",597, +"T9940B",598, +"T10000A",599, +"T10000B",600, +"T10000C",601, +"T10000D",602, +"Travan",610, +"Travan1Ex",611, +"Travan3",612, +"Travan3Ex",613, +"Travan4",614, +"Travan5",615, +"Travan7",616, +"VXA1",620, +"VXA2",621, +"VXA3",622, +"ECMA_153",630,"5,25"", M.O., WORM, 650Mb, 318750 sectors, 1024 bytes/sector, ECMA-153, ISO 11560" +"ECMA_153_512",631,"5,25"", M.O., WORM, 600Mb, 581250 sectors, 512 bytes/sector, ECMA-153, ISO 11560" +"ECMA_154",632,"3,5"", M.O., RW, 128Mb, 248826 sectors, 512 bytes/sector, ECMA-154, ISO 10090" +"ECMA_183_512",633,"5,25"", M.O., RW/WORM, 1Gb, 904995 sectors, 512 bytes/sector, ECMA-183, ISO 13481" +"ECMA_183",634,"5,25"", M.O., RW/WORM, 1Gb, 498526 sectors, 1024 bytes/sector, ECMA-183, ISO 13481" +"ECMA_184_512",635,"5,25"", M.O., RW/WORM, 1.2Gb, 1165600 sectors, 512 bytes/sector, ECMA-184, ISO 13549" +"ECMA_184",636,"5,25"", M.O., RW/WORM, 1.3Gb, 639200 sectors, 1024 bytes/sector, ECMA-184, ISO 13549" +"ECMA_189",637,"300mm, M.O., WORM, ??? sectors, 1024 bytes/sector, ECMA-189, ISO 13614" +"ECMA_190",638,"300mm, M.O., WORM, ??? sectors, 1024 bytes/sector, ECMA-190, ISO 13403" +"ECMA_195",639,"5,25"", M.O., RW/WORM, 936921 or 948770 sectors, 1024 bytes/sector, ECMA-195, ISO 13842" +"ECMA_195_512",640,"5,25"", M.O., RW/WORM, 1644581 or 1647371 sectors, 512 bytes/sector, ECMA-195, ISO 13842" +"ECMA_201",641,"3,5"", M.O., 446325 sectors, 512 bytes/sector, ECMA-201, ISO 13963" +"ECMA_201_ROM",642,"3,5"", M.O., 429975 sectors, 512 bytes/sector, embossed, ISO 13963" +"ECMA_223",643,"3,5"", M.O., 371371 sectors, 1024 bytes/sector, ECMA-223" +"ECMA_223_512",644,"3,5"", M.O., 694929 sectors, 512 bytes/sector, ECMA-223" +"ECMA_238",645,"5,25"", M.O., 1244621 sectors, 1024 bytes/sector, ECMA-238, ISO 15486" +"ECMA_239",646,"3,5"", M.O., 310352, 320332 or 321100 sectors, 2048 bytes/sector, ECMA-239, ISO 15498" +"ECMA_260",647,"356mm, M.O., 14476734 sectors, 1024 bytes/sector, ECMA-260, ISO 15898" +"ECMA_260_Double",648,"356mm, M.O., 24445990 sectors, 1024 bytes/sector, ECMA-260, ISO 15898" +"ECMA_280",649,"5,25"", M.O., 1128134 sectors, 2048 bytes/sector, ECMA-280, ISO 18093" +"ECMA_317",650,"300mm, M.O., 7355716 sectors, 2048 bytes/sector, ECMA-317, ISO 20162" +"ECMA_322",651,"5,25"", M.O., 1095840 sectors, 4096 bytes/sector, ECMA-322, ISO 22092, 9.1Gb/cart" +"ECMA_322_2k",652,"5,25"", M.O., 2043664 sectors, 2048 bytes/sector, ECMA-322, ISO 22092, 8.6Gb/cart" +"GigaMo",653,"3,5"", M.O., 605846 sectors, 2048 bytes/sector, Cherry Book, GigaMo, ECMA-351, ISO 17346" +"GigaMo2",654,"3,5"", M.O., 1063146 sectors, 2048 bytes/sector, Cherry Book 2, GigaMo 2, ECMA-353, ISO 22533" +"ISO_15286",655,"5,25"", M.O., 1263472 sectors, 2048 bytes/sector, ISO 15286, 5.2Gb/cart" +"ISO_15286_1024",656,"5,25"", M.O., 2319786 sectors, 1024 bytes/sector, ISO 15286, 4.8Gb/cart" +"ISO_15286_512",657,"5,25"", M.O., ??????? sectors, 512 bytes/sector, ISO 15286, 4.1Gb/cart" +"ISO_10089",658,"5,25"", M.O., 314569 sectors, 1024 bytes/sector, ISO 10089, 650Mb/cart" +"ISO_10089_512",659,"5,25"", M.O., ?????? sectors, 512 bytes/sector, ISO 10089, 594Mb/cart" +"CompactFloppy",660, +"DemiDiskette",661, +"Floptical",662,"3.5"", 652 tracks, 2 sides, 512 bytes/sector, Floptical, ECMA-207, ISO 14169" +"HiFD",663, +"QuickDisk",664, +"UHD144",665, +"VideoFloppy",666, +"Wafer",667, +"ZXMicrodrive",668, +"MetaFloppy_Mod_II",669,"5.25"", SS, DD, 77 tracks, 16 spt, 256 bytes/sector, MFM, 100 tpi, 300rpm" +"BeeCard",670, +"Borsu",671, +"DataStore",672, +"DIR",673, +"DST",674, +"DTF",675, +"DTF2",676, +"Flextra3020",677, +"Flextra3225",678, +"HiTC1",679, +"HiTC2",680, +"LT1",681, +"MiniCard",872, +"Orb",683, +"Orb5",684, +"SmartMedia",685, +"xD",686, +"XQD",687, +"DataPlay",688, +"AppleProfile",690, +"AppleWidget",691, +"AppleHD20",692, +"PriamDataTower",693, +"Pippin",694, +"RA60",700,"2382 cylinders, 4 tracks/cylinder, 42 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 204890112 bytes" +"RA80",701,"546 cylinders, 14 tracks/cylinder, 31 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 121325568 bytes" +"RA81",702,"1248 cylinders, 14 tracks/cylinder, 51 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 456228864 bytes" +"RC25",703,"302 cylinders, 4 tracks/cylinder, 42 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 25976832 bytes" +"RD31",704,"615 cylinders, 4 tracks/cylinder, 17 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 21411840 bytes" +"RD32",705,"820 cylinders, 6 tracks/cylinder, 17 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 42823680 bytes" +"RD51",706,"306 cylinders, 4 tracks/cylinder, 17 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 10653696 bytes" +"RD52",707,"480 cylinders, 7 tracks/cylinder, 18 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 30965760 bytes" +"RD53",708,"1024 cylinders, 7 tracks/cylinder, 18 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 75497472 bytes" +"RD54",709,"1225 cylinders, 8 tracks/cylinder, 18 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 159936000 bytes" +"RK06",710,"411 cylinders, 3 tracks/cylinder, 22 sectors/track, 256 words/sector, 16 bits/word, 512 bytes/sector, 13888512 bytes" +"RK06_18",711,"411 cylinders, 3 tracks/cylinder, 20 sectors/track, 256 words/sector, 18 bits/word, 576 bytes/sector, 14204160 bytes" +"RK07",712,"815 cylinders, 3 tracks/cylinder, 22 sectors/track, 256 words/sector, 16 bits/word, 512 bytes/sector, 27540480 bytes" +"RK07_18",713,"815 cylinders, 3 tracks/cylinder, 20 sectors/track, 256 words/sector, 18 bits/word, 576 bytes/sector, 28166400 bytes" +"RM02",714,"823 cylinders, 5 tracks/cylinder, 32 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 67420160 bytes" +"RM03",715,"823 cylinders, 5 tracks/cylinder, 32 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 67420160 bytes" +"RM05",716,"823 cylinders, 19 tracks/cylinder, 32 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 256196608 bytes" +"RP02",717,"203 cylinders, 10 tracks/cylinder, 22 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 22865920 bytes" +"RP02_18",718,"203 cylinders, 10 tracks/cylinder, 20 sectors/track, 128 words/sector, 36 bits/word, 576 bytes/sector, 23385600 bytes" +"RP03",719,"400 cylinders, 10 tracks/cylinder, 22 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 45056000 bytes" +"RP03_18",720,"400 cylinders, 10 tracks/cylinder, 20 sectors/track, 128 words/sector, 36 bits/word, 576 bytes/sector, 46080000 bytes" +"RP04",721,"411 cylinders, 19 tracks/cylinder, 22 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 87960576 bytes" +"RP04_18",722,"411 cylinders, 19 tracks/cylinder, 20 sectors/track, 128 words/sector, 36 bits/word, 576 bytes/sector, 89959680 bytes" +"RP05",723,"411 cylinders, 19 tracks/cylinder, 22 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 87960576 bytes" +"RP05_18",724,"411 cylinders, 19 tracks/cylinder, 20 sectors/track, 128 words/sector, 36 bits/word, 576 bytes/sector, 89959680 bytes" +"RP06",725,"815 cylinders, 19 tracks/cylinder, 22 sectors/track, 128 words/sector, 32 bits/word, 512 bytes/sector, 174423040 bytes" +"RP06_18",726,"815 cylinders, 19 tracks/cylinder, 20 sectors/track, 128 words/sector, 36 bits/word, 576 bytes/sector, 178387200 bytes" +"LS120",730, +"LS240",731, +"FD32MB",732, +"RDX",733, +"RDX320",734,"Imation 320Gb RDX" +"VideoNow",740, +"VideoNowColor",741, +"VideoNowXp",742, +"Bernoulli10",750,"8""x11"" Bernoulli Box disk with 10Mb capacity" +"Bernoulli20",751,"8""x11"" Bernoulli Box disk with 20Mb capacity" +"BernoulliBox2_20",752,"5⅓"" Bernoulli Box II disk with 20Mb capacity" +"KodakVerbatim3",760, +"KodakVerbatim6",761, +"KodakVerbatim12",762, +"ProfessionalDisc",770,"Professional Disc for video, single layer, rewritable, 23Gb" +"ProfessionalDiscDual",771,"Professional Disc for video, dual layer, rewritable, 50Gb" +"ProfessionalDiscTriple",772,"Professional Disc for video, triple layer, rewritable, 100Gb" +"ProfessionalDiscQuad",773,"Professional Disc for video, quad layer, write once, 128Gb" +"PDD",774,"Professional Disc for DATA, single layer, rewritable, 23Gb" +"PDD_WORM",775,"Professional Disc for DATA, single layer, write once, 23Gb" +"ArchivalDisc",776,"Archival Disc, 1st gen., 300Gb" +"ArchivalDisc2",777,"Archival Disc, 2nd gen., 500Gb" +"ArchivalDisc3",778,"Archival Disc, 3rd gen., 1Tb" +"ODC300R",779,"Optical Disc archive, 1st gen., write once, 300Gb" +"ODC300RE",780,"Optical Disc archive, 1st gen., rewritable, 300Gb" +"ODC600R",781,"Optical Disc archive, 2nd gen., write once, 600Gb" +"ODC600RE",782,"Optical Disc archive, 2nd gen., rewritable, 600Gb" +"ODC1200RE",783,"Optical Disc archive, 3rd gen., rewritable, 1200Gb" +"ODC1500R",784,"Optical Disc archive, 3rd gen., write once, 1500Gb" +"ODC3300R",785,"Optical Disc archive, 4th gen., write once, 3300Gb" +"ODC5500R",786,"Optical Disc archive, 5th gen., write once, 5500Gb" +"ECMA_322_1k",800,"5,25"", M.O., 4383356 sectors, 1024 bytes/sector, ECMA-322, ISO 22092, 9.1Gb/cart" +"ECMA_322_512",801,"5,25"", M.O., ??????? sectors, 512 bytes/sector, ECMA-322, ISO 22092, 9.1Gb/cart" +"ISO_14517",802,"5,25"", M.O., 1273011 sectors, 1024 bytes/sector, ISO 14517, 2.6Gb/cart" +"ISO_14517_512",803,"5,25"", M.O., 2244958 sectors, 512 bytes/sector, ISO 14517, 2.3Gb/cart" +"ISO_15041_512",804,"3,5"", M.O., 1041500 sectors, 512 bytes/sector, ISO 15041, 540Mb/cart" +"MetaFloppy_Mod_I",820,"5.25"", SS, DD, 35 tracks, 16 spt, 256 bytes/sector, MFM, 48 tpi, ???rpm" \ No newline at end of file diff --git a/Aaru.CommonTypes/MediaTypeFromDevice/FromAta.cs b/Aaru.CommonTypes/MediaTypeFromDevice/FromAta.cs new file mode 100644 index 000000000..616744b1e --- /dev/null +++ b/Aaru.CommonTypes/MediaTypeFromDevice/FromAta.cs @@ -0,0 +1,73 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : FromAta.cs +// Author(s) : Natalia Portillo +// +// Component : Aaru common types. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using Aaru.Console; + +namespace Aaru.CommonTypes +{ + public static partial class MediaTypeFromDevice + { + /// Gets the media type from an ATA (not ATAPI) device + /// Manufacturer string + /// Model string + /// Is the device removable? + /// Does the device self-identify as CompactFlash? + /// Is the device attached thru PCMCIA or CardBus? + /// Number of blocks in device + /// The media type + public static MediaType GetFromAta(string manufacturer, string model, bool removable, bool compactFlash, + bool pcmcia, ulong blocks) + { + if(!removable) + { + if(compactFlash) + return MediaType.CompactFlash; + + return pcmcia ? MediaType.PCCardTypeI : MediaType.GENERIC_HDD; + } + + if(manufacturer.ToLowerInvariant() == "syquest" && + model.ToLowerInvariant() == "sparq" && + blocks == 1961069) + { + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is SyQuest, media has 1961069 blocks of 512 bytes, setting media type to SparQ."); + + return MediaType.SparQ; + } + + return MediaType.Unknown; + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/MediaTypeFromDevice/FromMmc.cs b/Aaru.CommonTypes/MediaTypeFromDevice/FromMmc.cs new file mode 100644 index 000000000..6f728cf46 --- /dev/null +++ b/Aaru.CommonTypes/MediaTypeFromDevice/FromMmc.cs @@ -0,0 +1,179 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : FromMmc.cs +// Author(s) : Natalia Portillo +// +// Component : Aaru common types. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using Aaru.Console; + +namespace Aaru.CommonTypes +{ + /// Gets the media type from a real device + public static partial class MediaTypeFromDevice + { + /// Gets the media type from an SCSI MultiMedia Commands compliant device + /// Model string + /// Medium type from MODE SENSE + /// Density code from MODE SENSE + /// Number of blocks in media + /// Size of a block in bytes + /// Is the device USB attached + /// Is the media an optical disc + /// Media type + static MediaType GetFromMmc(string model, byte mediumType, byte densityCode, ulong blocks, uint blockSize, + bool isUsb, bool opticalDisc) + { + switch(mediumType) + { + case 0x00: + if(blockSize == 512) + if(blocks == 1281856) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to WORM PD-650.", + mediumType, blocks, blockSize); + + return MediaType.PD650_WORM; + } + else + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to PD-650.", + mediumType, blocks, blockSize); + + return MediaType.PD650; + } + else + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, setting media type to Compact Disc.", + mediumType); + + return MediaType.CD; + } + case 0x01: + case 0x05: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, setting media type to CD-ROM.", + mediumType); + + return MediaType.CDROM; + case 0x02: + case 0x06: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, setting media type to Compact Disc Digital Audio.", + mediumType); + + return MediaType.CDDA; + case 0x03: + case 0x07: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, setting media type to CD+.", mediumType); + + return MediaType.CDPLUS; + case 0x04: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, setting media type to Photo CD.", + mediumType); + + return MediaType.PCD; + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, setting media type to CD-R.", mediumType); + + return MediaType.CDR; + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, setting media type to CD-RW.", mediumType); + + return MediaType.CDRW; + case 0x40 when isUsb && !opticalDisc: + case 0x41 when isUsb && !opticalDisc: + case 0x42 when isUsb && !opticalDisc: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h and device is USB, setting media type to Flash Drive.", + mediumType); + + return MediaType.FlashDrive; + case 0x80: + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + switch(densityCode) + { + case 0x42: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive starts with \"ult\", setting media type to LTO-2.", + mediumType, densityCode); + + return MediaType.LTO2; + case 0x44: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive starts with \"ult\", setting media type to LTO-2.", + mediumType, densityCode); + + return MediaType.LTO3; + case 0x46: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive starts with \"ult\", setting media type to LTO-2.", + mediumType, densityCode); + + return MediaType.LTO4; + case 0x58: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive starts with \"ult\", setting media type to LTO-2.", + mediumType, densityCode); + + return MediaType.LTO5; + } + + break; + } + + return MediaType.Unknown; + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/MediaTypeFromDevice/FromOdc.cs b/Aaru.CommonTypes/MediaTypeFromDevice/FromOdc.cs new file mode 100644 index 000000000..c12cd449c --- /dev/null +++ b/Aaru.CommonTypes/MediaTypeFromDevice/FromOdc.cs @@ -0,0 +1,342 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : FromOdc.cs +// Author(s) : Natalia Portillo +// +// Component : Aaru common types. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using Aaru.Console; + +namespace Aaru.CommonTypes +{ + public static partial class MediaTypeFromDevice + { + /// Gets the device type from a SCSI Optical Device + /// Medium type from MODE SENSE + /// Number of blocks in device + /// Size in bytes of a block + /// Media type + static MediaType GetFromOdc(byte mediumType, ulong blocks, uint blockSize) + { + if(mediumType != 0x01 && + mediumType != 0x02 && + mediumType != 0x03 && + mediumType != 0x05 && + mediumType != 0x07) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, setting media type to unknown magneto-optical.", + mediumType); + + return MediaType.UnknownMO; + } + + switch(blockSize) + { + case 512: + { + switch(blocks) + { + case 248826: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-154 / ISO 10090 conforming 3½\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_154; + case 429975: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-201 / ISO 13963 conforming 3½\" embossed magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_201_ROM; + case 446325: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-201 / ISO 13963 conforming 3½\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_201; + case 694929: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-223 conforming 3½\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_223_512; + case 904995: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-183 / ISO 13481 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_183_512; + case 1041500: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 15041 conforming 3½\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ISO_15041_512; + case 1128772: + case 1163337: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-184 / ISO 13549 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_184_512; + case 1281856: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to WORM PD-650.", + mediumType, blocks, blockSize); + + return MediaType.PD650_WORM; + case 1298496: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to PD-650.", + mediumType, blocks, blockSize); + + return MediaType.PD650; + case 1644581: + case 1647371: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-195 / ISO 13842 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_195_512; + case 2244958: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 14517 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ISO_14517_512; + default: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.UnknownMO; + } + } + + case 1024: + { + switch(blocks) + { + case 314569: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 10089 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ISO_10089; + case 371371: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-223 conforming 3½\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_223; + case 498526: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-184 / ISO 13549 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_183; + case 603466: + case 637041: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-184 / ISO 13549 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_184; + case 936921: + case 948770: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-195 / ISO 13842 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_195; + case 1244621: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-238 / ISO 15486 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_238; + case 1273011: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 14517 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ISO_14517; + case 2319786: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 15286 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ISO_15286_1024; + case 4383356: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-322 / ISO 22092 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_322_1k; + case 14476734: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-260 / ISO 15898 conforming 356mm magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_260; + case 24445990: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-260 / ISO 15898 conforming 356mm magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_260_Double; + default: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.UnknownMO; + } + } + + case 2048: + { + switch(blocks) + { + case 310352: // Found in real media + case 318988: + case 320332: + case 321100: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-239 / ISO 15498 conforming 3½\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_239; + case 605846: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to GigaMO 3½\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.GigaMo; + case 1063146: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to GigaMO 2 3½\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.GigaMo2; + case 1128134: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-280 / ISO 18093 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_280; + case 1263472: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 15286 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ISO_15286; + case 2043664: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-322 / ISO 22092 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_322_2k; + case 7355716: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-317 / ISO 20162 conforming 300mm magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_317; + default: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.UnknownMO; + } + } + + case 4096: + { + switch(blocks) + { + case 1095840: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-322 / ISO 22092 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_322; + default: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.UnknownMO; + } + } + + case 8192: + { + switch(blocks) + { + case 1834348: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to UDO.", + mediumType, blocks, blockSize); + + return MediaType.UDO; + case 3668759: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to WORM UDO2.", + mediumType, blocks, blockSize); + + return MediaType.UDO2_WORM; + case 3669724: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to UDO2.", + mediumType, blocks, blockSize); + + return MediaType.UDO2; + default: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.UnknownMO; + } + } + + default: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.UnknownMO; + } + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/MediaTypeFromDevice/FromSbc.cs b/Aaru.CommonTypes/MediaTypeFromDevice/FromSbc.cs new file mode 100644 index 000000000..5b17faab9 --- /dev/null +++ b/Aaru.CommonTypes/MediaTypeFromDevice/FromSbc.cs @@ -0,0 +1,951 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : FromSbc.cs +// Author(s) : Natalia Portillo +// +// Component : Aaru common types. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using Aaru.Console; + +namespace Aaru.CommonTypes +{ + public static partial class MediaTypeFromDevice + { + /// Gets the media type from a SCSI Block Commands compliant device + /// Vendor string + /// Model string + /// Medium type from MODE SENSE + /// Number of blocks in device + /// Size of a block in bytes + /// Media type + static MediaType GetFromSbc(string vendor, string model, byte mediumType, ulong blocks, uint blockSize) + { + switch(mediumType) + { + case 0x09: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-54 formatted 8\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_54; + case 0x0A: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-59 formatted 8\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_59; + case 0x0B: + switch(blockSize) + { + case 256: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-69 formatted 8\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_69_26; + case 512: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-69 formatted 8\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_69_15; + case 1024: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-69 formatted 8\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_69_8; + } + + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown.", + mediumType, blocks, blockSize); + + return MediaType.Unknown; + case 0x0E: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-66 formatted 5¼\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_66; + case 0x12: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-70 formatted 5¼\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_70; + case 0x16: + switch(blockSize) + { + case 256: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-78 formatted 5¼\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_78; + case 512: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-78 formatted 5¼\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_78_2; + } + + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown.", + mediumType, blocks, blockSize); + + return MediaType.Unknown; + case 0x1A: + switch(blockSize) + { + case 256: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-99 formatted 5¼\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_99_26; + case 512: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-99 formatted 5¼\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_99_15; + case 1024: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-99 formatted 5¼\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_99_8; + } + + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to unknown.", + mediumType, blocks, blockSize); + + return MediaType.Unknown; + case 0x1E: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 3½\" double density floppy.", + mediumType, blocks, blockSize); + + return MediaType.DOS_35_DS_DD_9; + case 0x41: + switch(blocks) + { + case 58620544: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to 120Gb REV.", + mediumType, blocks, blockSize); + + return MediaType.REV120; + case 34185728: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to 70Gb REV.", + mediumType, blocks, blockSize); + + return MediaType.REV70; + case 17090880: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to 35Gb REV.", + mediumType, blocks, blockSize); + + return MediaType.REV35; + } + + break; + case 0x93: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to PC-98 formatted 3½\" high density floppy (15 sectors).", + mediumType, blocks, blockSize); + + return MediaType.NEC_35_HD_15; + case 0x94: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 3½\" high density floppy.", + mediumType, blocks, blockSize); + + return MediaType.DOS_35_HD; + } + + switch(blockSize) + { + case 128: + switch(blocks) + { + case 720: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Atari formatted 5¼\" single density floppy.", + mediumType, blocks, blockSize); + + return MediaType.ATARI_525_SD; + case 1040: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Atari formatted 5¼\" double density floppy.", + mediumType, blocks, blockSize); + + return MediaType.ATARI_525_DD; + case 1898: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 8\" (33FD) floppy.", + mediumType, blocks, blockSize); + + return MediaType.IBM33FD_128; + case 2002: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-54 formatted 8\" single density floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_54; + case 3848: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 8\" (43FD) floppy.", + mediumType, blocks, blockSize); + + return MediaType.IBM43FD_128; + case 4004: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-59 formatted 8\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_59; + } + + break; + case 256: + switch(blocks) + { + case 322: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-56 formatted 5¼\" double density floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_66; + case 400: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Acorn formatted 5¼\" single density floppy.", + mediumType, blocks, blockSize); + + return MediaType.ACORN_525_SS_SD_40; + case 455: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Apple DOS 3.2 formatted 5¼\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.Apple32SS; + case 560: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Apple DOS 3.3 formatted 5¼\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.Apple33SS; + case 640: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Acorn formatted 5¼\" double density floppy.", + mediumType, blocks, blockSize); + + return MediaType.ACORN_525_SS_DD_40; + case 720: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Atari formatted 5¼\" double density floppy.", + mediumType, blocks, blockSize); + + return MediaType.ATARI_525_DD; + case 800: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Acorn formatted 5¼\" double density floppy (80 tracks).", + mediumType, blocks, blockSize); + + return MediaType.ACORN_525_SS_SD_80; + case 910: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Apple DOS 3.2 formatted 5¼\" double sided floppy.", + mediumType, blocks, blockSize); + + return MediaType.Apple32DS; + case 1120: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Apple DOS 3.3 formatted 5¼\" double sided floppy.", + mediumType, blocks, blockSize); + + return MediaType.Apple33DS; + case 1121: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 8\" (33FD) floppy.", + mediumType, blocks, blockSize); + + return MediaType.IBM33FD_256; + case 1232: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to MetaFloppy formatted 5¼\" double density single sided floppy.", + mediumType, blocks, blockSize); + + return MediaType.MetaFloppy_Mod_II; + case 1280 when mediumType == 0x01: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Acorn formatted 5¼\" double density floppy with 80 tracks.", + mediumType, blocks, blockSize); + + return MediaType.ACORN_525_SS_DD_80; + case 1280: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-70 formatted 5¼\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_70; + case 2002: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to DEC RX02 floppy.", + mediumType, blocks, blockSize); + + return MediaType.RX02; + case 2560: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-78 formatted 5¼\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_78; + case 3848: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 8\" (53FD) floppy.", + mediumType, blocks, blockSize); + + return MediaType.IBM53FD_256; + case 4004: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-99 formatted 5¼\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_99_26; + case 39168 when vendor.StartsWith("iomega", StringComparison.OrdinalIgnoreCase): + case 41004 when vendor.StartsWith("iomega", StringComparison.OrdinalIgnoreCase): + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is IOMEGA, media has {0} blocks of 256 bytes, setting media type to 10Mb Bernoulli Box.", + blocks); + + return MediaType.Bernoulli10; + } + + break; + case 319: + switch(blocks) + { + case 256: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 8\" (23FD) floppy.", + mediumType, blocks, blockSize); + + return MediaType.IBM23FD; + } + + break; + case 512: + switch(blocks) + { + case 320: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 5¼\" double density single sided floppy (8 sectors).", + mediumType, blocks, blockSize); + + return MediaType.DOS_525_SS_DD_8; + case 360: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 5¼\" double density single sided floppy.", + mediumType, blocks, blockSize); + + return MediaType.DOS_525_SS_DD_9; + case 610: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 8\" (33FD) floppy.", + mediumType, blocks, blockSize); + + return MediaType.IBM33FD_512; + case 630 when mediumType == 0x01: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Apricot formatted 3½\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.Apricot_35; + case 640 when mediumType == 0x01: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 3½\" double density single sided floppy (8 sectors).", + mediumType, blocks, blockSize); + + return MediaType.DOS_35_SS_DD_8; + case 640: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 5¼\" double density floppy (8 sectors).", + mediumType, blocks, blockSize); + + return MediaType.DOS_525_DS_DD_8; + case 720 when mediumType == 0x01: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 3½\" double density single sided floppy.", + mediumType, blocks, blockSize); + + return MediaType.DOS_35_SS_DD_9; + case 720: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 5¼\" double density floppy.", + mediumType, blocks, blockSize); + + return MediaType.DOS_525_DS_DD_9; + case 800: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Apple formatted 3½\" double density single sided floppy.", + mediumType, blocks, blockSize); + + return MediaType.AppleSonySS; + case 1280: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 3½\" double density floppy (8 sectors).", + mediumType, blocks, blockSize); + + return MediaType.DOS_35_DS_DD_8; + case 1440: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 3½\" double density floppy.", + mediumType, blocks, blockSize); + + return MediaType.DOS_35_DS_DD_9; + case 1640: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to FDFORMAT formatted 3½\" double density floppy.", + mediumType, blocks, blockSize); + + return MediaType.FDFORMAT_35_DD; + case 1760: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Amiga formatted 3½\" double density floppy.", + mediumType, blocks, blockSize); + + return MediaType.CBM_AMIGA_35_DD; + case 2242: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 8\" (53FD) floppy.", + mediumType, blocks, blockSize); + + return MediaType.IBM53FD_512; + case 2332: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-99 formatted 5¼\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_99_15; + case 2400: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 5¼\" high density floppy.", + mediumType, blocks, blockSize); + + return MediaType.DOS_525_HD; + case 2788: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to FDFORMAT formatted 5¼\" high density floppy.", + mediumType, blocks, blockSize); + + return MediaType.FDFORMAT_525_HD; + case 2880: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 3½\" high density floppy.", + mediumType, blocks, blockSize); + + return MediaType.DOS_35_HD; + case 3360: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Microsoft DMF formatted 3½\" high density floppy.", + mediumType, blocks, blockSize); + + return MediaType.DMF; + case 3444: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to FDFORMAT formatted 3½\" high density floppy.", + mediumType, blocks, blockSize); + + return MediaType.FDFORMAT_35_HD; + case 3520: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Amiga formatted 3½\" high density floppy.", + mediumType, blocks, blockSize); + + return MediaType.CBM_AMIGA_35_HD; + case 5760: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 3½\" extra density floppy.", + mediumType, blocks, blockSize); + + return MediaType.DOS_35_ED; + case 40662 when mediumType == 0x20: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Floptical.", + mediumType, blocks, blockSize); + + return MediaType.Floptical; + case 65536 when model.ToLowerInvariant().StartsWith("ls-", StringComparison.Ordinal): + AaruConsole.DebugWriteLine("Media detection", + "Drive model is LS (SuperDisk), media has 65536 blocks of 512 bytes, setting media type to FD32MB."); + + return MediaType.FD32MB; + case 78882 when vendor.StartsWith("iomega", StringComparison.OrdinalIgnoreCase): + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is IOMEGA, media has 78882 blocks of 512 bytes, setting media type to PocketZIP."); + + return MediaType.PocketZip; + case 86700 when vendor.ToLowerInvariant() == "syquest": + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is SyQuest, media has 86700 blocks of 512 bytes, setting media type to SQ400."); + + return MediaType.SQ400; + case 87040 when vendor.StartsWith("iomega", StringComparison.OrdinalIgnoreCase): + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is IOMEGA, media has 87040 blocks of 512 bytes, setting media type to 44Mb Bernoulli Box II."); + + return MediaType.Bernoulli44; + case 173456 when vendor.ToLowerInvariant() == "syquest": + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is SyQuest, media has 173456 blocks of 512 bytes, setting media type to SQ800."); + + return MediaType.SQ800; + case 175856 when vendor.StartsWith("iomega", StringComparison.OrdinalIgnoreCase): + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is IOMEGA, media has 175856 blocks of 512 bytes, setting media type to 90Mb Bernoulli Box II."); + + return MediaType.Bernoulli90; + case 196608 when model.ToLowerInvariant().StartsWith("zip", StringComparison.OrdinalIgnoreCase): + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is IOMEGA, drive model is ZIP, media has 196608 blocks of 512 bytes, setting media type to 100Mb ZIP."); + + return MediaType.ZIP100; + + case 215440 when vendor.ToLowerInvariant() == "syquest": + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is SyQuest, media has 215440 blocks of 512 bytes, setting media type to SQ310."); + + return MediaType.SQ310; + case 246528 when model.ToLowerInvariant().StartsWith("ls-", StringComparison.Ordinal): + AaruConsole.DebugWriteLine("Media detection", + "Drive model is LS (SuperDisk), media has 246528 blocks of 512 bytes, setting media type to LS-120."); + + return MediaType.LS120; + case 248826 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-154 / ISO 10090 conforming 3½\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_154; + case 262144 when vendor.ToLowerInvariant() == "syquest": + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is SyQuest, media has 262144 blocks of 512 bytes, setting media type to EZ135."); + + return MediaType.EZ135; + case 294918 when vendor.StartsWith("iomega", StringComparison.OrdinalIgnoreCase): + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is IOMEGA, media has 294918 blocks of 512 bytes, setting media type to 150Mb Bernoulli Box II."); + + return MediaType.Bernoulli150; + case 390696 when vendor.ToLowerInvariant() == "syquest": + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is SyQuest, media has 390696 blocks of 512 bytes, setting media type to SQ2000."); + + return MediaType.SQ2000; + case 393380 when model.ToLowerInvariant().StartsWith("hifd", StringComparison.Ordinal): + AaruConsole.DebugWriteLine("Media detection", + "Drive model is HiFD, media has 393380 blocks of 512 bytes, setting media type to HiFD.", + blocks, blockSize); + + return MediaType.HiFD; + case 429975 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-201 / ISO 13963 conforming 3½\" embossed magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_201_ROM; + case 446325 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-201 / ISO 13963 conforming 3½\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_201; + case 450560 when vendor.ToLowerInvariant() == "syquest": + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is SyQuest, media has 450560 blocks of 512 bytes, setting media type to EZ230."); + + return MediaType.EZ230; + case 469504 when model.ToLowerInvariant().StartsWith("ls-", StringComparison.Ordinal): + AaruConsole.DebugWriteLine("Media detection", + "Drive model is LS (SuperDisk), media has 469504 blocks of 512 bytes, setting media type to LS-240."); + + return MediaType.LS240; + case 489532 when model.ToLowerInvariant().StartsWith("zip", StringComparison.OrdinalIgnoreCase): + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is IOMEGA, drive model is ZIP, media has 489532 blocks of 512 bytes, setting media type to 250Mb ZIP."); + + return MediaType.ZIP250; + case 524288 when vendor.ToLowerInvariant() == "syquest": + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is SyQuest, media has 524288 blocks of 512 bytes, setting media type to SQ327."); + + return MediaType.SQ327; + case 694929 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-223 conforming 3½\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_223_512; + case 904995 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-183 / ISO 13481 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_183_512; + case 1041500 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 15041 conforming 3½\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ISO_15041_512; + case 1128772 when mediumType == 0x01 || mediumType == 0x02: + case 1163337 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-184 / ISO 13549 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_184_512; + case 1281856 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to WORM PD-650.", + mediumType, blocks, blockSize); + + return MediaType.PD650_WORM; + case 1298496 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to PD-650.", + mediumType, blocks, blockSize); + + return MediaType.PD650; + case 1470500 + when model.ToLowerInvariant().StartsWith("zip", StringComparison.OrdinalIgnoreCase): + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is IOMEGA, drive model is ZIP, media has 489532 blocks of 512 bytes, setting media type to 250Mb ZIP."); + + return MediaType.ZIP750; + case 1644581 when mediumType == 0x01 || mediumType == 0x02: + case 1647371 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-195 / ISO 13842 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_195_512; + case 1961069 when vendor.ToLowerInvariant() == "syquest": + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is SyQuest, media has 1961069 blocks of 512 bytes, setting media type to SparQ."); + + return MediaType.SparQ; + case 2091050 when model.ToLowerInvariant().StartsWith("jaz", StringComparison.Ordinal): + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is IOMEGA, drive model is JAZ, media has 2091050 blocks of 512 bytes, setting media type to 1Gb JAZ."); + + return MediaType.Jaz; + case 2244958 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 14517 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ISO_14517_512; + case 2929800 when vendor.ToLowerInvariant() == "syquest": + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is SyQuest, media has 2929800 blocks of 512 bytes, setting media type to SyJet."); + + return MediaType.SyJet; + case 3915600 when model.ToLowerInvariant().StartsWith("jaz", StringComparison.Ordinal): + AaruConsole.DebugWriteLine("Media detection", + "Drive manufacturer is IOMEGA, drive model is JAZ, media has 3915600 blocks of 512 bytes, setting media type to 2Gb JAZ."); + + return MediaType.Jaz2; + case 4307184 when vendor.ToLowerInvariant().StartsWith("cws orb", StringComparison.Ordinal): + AaruConsole.DebugWriteLine("Media detection", + "Drive model is Castlewood Orb, media has 4307184 blocks of 512 bytes, setting media type to Orb."); + + return MediaType.Orb; + case 625134256 when model.ToLowerInvariant().StartsWith("rdx", StringComparison.Ordinal): + AaruConsole.DebugWriteLine("Media detection", + "Drive model is LS (SuperDisk), media has {0} blocks of {1} bytes, setting media type to unknown.", + blocks, blockSize); + + return MediaType.RDX320; + } + + break; + case 1024: + { + switch(blocks) + { + case 800 when mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Acorn formatted 3½\" double density floppy.", + mediumType, blocks, blockSize); + + return MediaType.ACORN_35_DS_DD; + case 1220: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to IBM formatted 8\" (53FD) floppy.", + mediumType, blocks, blockSize); + + return MediaType.IBM53FD_1024; + case 1232 when model.ToLowerInvariant().StartsWith("ls-", StringComparison.Ordinal): + AaruConsole.DebugWriteLine("Media detection", + "Drive model is LS (SuperDisk), media has 2880 blocks of 512 bytes, setting media type to PC-98 formatted 3½\" high density floppy."); + + return MediaType.NEC_35_HD_8; + case 1232: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Sharp formatted 3½\" high density floppy.", + mediumType, blocks, blockSize); + + return MediaType.SHARP_35; + case 1268: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-69 formatted 8\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_69_8; + case 1280: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to PC-98 formatted 5¼\" high density floppy.", + mediumType, blocks, blockSize); + + return MediaType.NEC_525_HD; + case 1316: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-99 formatted 5¼\" floppy.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_99_8; + case 1600 when mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Acorn formatted 3½\" high density floppy.", + mediumType, blocks, blockSize); + + return MediaType.ACORN_35_DS_HD; + case 314569 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 10089 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ISO_10089; + case 371371 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-223 conforming 3½\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_223; + case 498526 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-183 / ISO 13481 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_183; + case 603466 when mediumType == 0x01 || mediumType == 0x02: + case 637041 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-184 / ISO 13549 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_184; + case 936921 when mediumType == 0x01 || mediumType == 0x02: + case 948770 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-195 / ISO 13842 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_195; + case 1244621 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-238 / ISO 15486 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_238; + case 1273011 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 14517 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ISO_14517; + case 2319786 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 15286 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ISO_15286_1024; + case 4383356 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-322 / ISO 22092 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_322_1k; + case 14476734 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-260 / ISO 15898 conforming 356mm magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_260; + case 24445990 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-260 / ISO 15898 conforming 356mm magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_260_Double; + } + } + + break; + case 2048: + { + switch(blocks) + { + case 112311: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to 60 minute MiniDisc.", + mediumType, blocks, blockSize); + + return MediaType.MD60; + case 138363: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to 74 minute MiniDisc.", + mediumType, blocks, blockSize); + + return MediaType.MD74; + case 149373: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to 80 minute MiniDisc.", + mediumType, blocks, blockSize); + + return MediaType.MD80; + case 310352 when mediumType == 0x01 || mediumType == 0x02: // Found in real media + case 318988 when mediumType == 0x01 || mediumType == 0x02: + case 320332 when mediumType == 0x01 || mediumType == 0x02: + case 321100 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-239 / ISO 15498 conforming 3½\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_239; + case 494023: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to Sony HiMD.", + mediumType, blocks, blockSize); + + return MediaType.HiMD; + case 605846 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to GigaMO 3½\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.GigaMo; + case 1063146 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to GigaMO 2 3½\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.GigaMo2; + case 1128134 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-280 / ISO 18093 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_280; + case 1263472 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ISO 15286 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ISO_15286; + case 2043664 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-322 / ISO 22092 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_322_2k; + case 7355716 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-317 / ISO 20162 conforming 300mm magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_317; + } + } + + break; + case 4096: + { + switch(blocks) + { + case 1095840 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to ECMA-322 / ISO 22092 conforming 5¼\" magneto-optical.", + mediumType, blocks, blockSize); + + return MediaType.ECMA_322; + } + } + + break; + case 8192: + { + switch(blocks) + { + case 1834348 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to UDO.", + mediumType, blocks, blockSize); + + return MediaType.UDO; + case 3668759 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to WORM UDO2.", + mediumType, blocks, blockSize); + + return MediaType.UDO2_WORM; + case 3669724 when mediumType == 0x01 || mediumType == 0x02: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to UDO2.", + mediumType, blocks, blockSize); + + return MediaType.UDO2; + } + } + + break; + } + + return MediaType.Unknown; + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/MediaTypeFromDevice/FromScsi.cs b/Aaru.CommonTypes/MediaTypeFromDevice/FromScsi.cs new file mode 100644 index 000000000..c51895222 --- /dev/null +++ b/Aaru.CommonTypes/MediaTypeFromDevice/FromScsi.cs @@ -0,0 +1,134 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : FromScsi.cs +// Author(s) : Natalia Portillo +// +// Component : Aaru common types. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using Aaru.Console; + +namespace Aaru.CommonTypes +{ + public static partial class MediaTypeFromDevice + { + /// Tries to guess, from SCSI information, the media type of a device and/or its inserted media + /// The SCSI Peripheral Type as indicated in the INQUIRY response + /// The vendor string of the device + /// The model string of the device + /// The medium type byte from MODE SENSE + /// The density type byte from MODE SENSE + /// How many blocks are on the media + /// Size in bytes of each block + /// Device is USB + /// Is media an optical disc? + /// The media type + public static MediaType GetFromScsi(byte scsiPeripheralType, string vendor, string model, byte mediumType, + byte densityCode, ulong blocks, uint blockSize, bool isUsb, + bool opticalDisc) + { + switch(scsiPeripheralType) + { + // Direct access device + case 0x00: + // Simplified access device + case 0x0E: + if(mediumType == 0x03 || + mediumType == 0x05 || + mediumType == 0x07) + goto case 0x07; + + return GetFromSbc(vendor, model, mediumType, blocks, blockSize); + + // Sequential access device + case 0x01: + return GetFromSsc(scsiPeripheralType, vendor, model, mediumType, densityCode, blocks, blockSize); + + // Write-once device + case 0x04: + // Optical device + case 0x07: return GetFromOdc(mediumType, blocks, blockSize); + + // MultiMedia Device + case 0x05: return GetFromMmc(model, mediumType, densityCode, blocks, blockSize, isUsb, opticalDisc); + + // MD DATA drives + case 0x10 when model.StartsWith("MDM", StringComparison.Ordinal) || + model.StartsWith("MDH", StringComparison.Ordinal): + if(blockSize == 2048) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI peripheral type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to MiniDisc for Data.", + scsiPeripheralType, blocks, blockSize); + + return MediaType.MDData; + } + + switch(blocks) + { + case 57312: + AaruConsole.DebugWriteLine("Media detection", + "SCSI peripheral type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to 60 minute MiniDisc.", + scsiPeripheralType, blocks, blockSize); + + return MediaType.MD60; + case 70464: + AaruConsole.DebugWriteLine("Media detection", + "SCSI peripheral type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to 74 minute MiniDisc.", + scsiPeripheralType, blocks, blockSize); + + return MediaType.MD74; + case 76096: + AaruConsole.DebugWriteLine("Media detection", + "SCSI peripheral type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to 80 minute MiniDisc.", + scsiPeripheralType, blocks, blockSize); + + return MediaType.MD80; + } + + AaruConsole.DebugWriteLine("Media detection", + "SCSI peripheral type is {0:X2}h, media has {1} blocks of {2} bytes, setting media type to 60 minute MiniDisc.", + scsiPeripheralType, blocks, blockSize); + + return MediaType.MD; + + // Host managed zoned block device + case 0x14: + AaruConsole.DebugWriteLine("Media detection", + "SCSI peripheral type is {0:X2}h, setting media type to host managed zoned block device.", + scsiPeripheralType, blocks, blockSize); + + return MediaType.Zone_HDD; + } + + return MediaType.Unknown; + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/MediaTypeFromDevice/FromSsc.cs b/Aaru.CommonTypes/MediaTypeFromDevice/FromSsc.cs new file mode 100644 index 000000000..e5978709e --- /dev/null +++ b/Aaru.CommonTypes/MediaTypeFromDevice/FromSsc.cs @@ -0,0 +1,1611 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : FromSsc.cs +// Author(s) : Natalia Portillo +// +// Component : Aaru common types. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using Aaru.Console; + +namespace Aaru.CommonTypes +{ + public static partial class MediaTypeFromDevice + { + /// Gets the media type from an SCSI Streaming Commands compliant device + /// Peripheral type + /// Vendor string + /// Model string + /// Medium type from MODE SENSE + /// Density code from MODE SENSE + /// Number of blocks in media + /// Size of a block in bytes + /// Media type + public static MediaType GetFromSsc(byte scsiPeripheralType, string vendor, string model, byte mediumType, + byte densityCode, ulong blocks, uint blockSize) + { + switch(mediumType) + { + case 0x00: + switch(densityCode) + { + case 0x04: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, setting media type to QIC-11.", + mediumType, densityCode); + + return MediaType.QIC11; + case 0x05: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, setting media type to QIC-24.", + mediumType, densityCode); + + return MediaType.QIC24; + case 0x09: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, setting media type to IBM 3490.", + mediumType, densityCode); + + return MediaType.IBM3490; + case 0x0F: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, setting media type to QIC-120.", + mediumType, densityCode); + + return MediaType.QIC120; + case 0x10: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, setting media type to QIC-150.", + mediumType, densityCode); + + return MediaType.QIC150; + case 0x13: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, setting media type to DDS.", + mediumType, densityCode); + + return MediaType.DDS1; + case 0x24: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, setting media type to DDS-2.", + mediumType, densityCode); + + return MediaType.DDS2; + case 0x25: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, setting media type to DDS-3.", + mediumType, densityCode); + + return MediaType.DDS3; + case 0x26: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, setting media type to DDS-4.", + mediumType, densityCode); + + return MediaType.DDS4; + case 0x28: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, setting media type to IBM 3490E.", + mediumType, densityCode); + + return MediaType.IBM3490E; + case 0x40: + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to LTO.", + mediumType, densityCode); + + return MediaType.LTO; + } + + if(model.ToLowerInvariant().StartsWith("sdz", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"sdz\" setting media type to Super AIT.", + mediumType, densityCode); + + return MediaType.SAIT1; + } + + break; + + case 0x41: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to LTO-2.", + mediumType, densityCode); + + return MediaType.LTO2; + } + + break; + } + + case 0x42: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to LTO-2.", + mediumType, densityCode); + + return MediaType.LTO2; + } + + if(vendor.ToLowerInvariant() == "stk") + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive manufacturer is StorageTek, setting media type to T9840A.", + mediumType, densityCode); + + return MediaType.T9840A; + } + + break; + } + + case 0x43: + { + if(vendor.ToLowerInvariant() == "stk") + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive manufacturer is StorageTek, setting media type to T9940A.", + mediumType, densityCode); + + return MediaType.T9940A; + } + + break; + } + + case 0x44: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to LTO-3.", + mediumType, densityCode); + + return MediaType.LTO3; + } + + if(vendor.ToLowerInvariant() == "stk") + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive manufacturer is StorageTek, setting media type to T9940B.", + mediumType, densityCode); + + return MediaType.T9940B; + } + + break; + } + + case 0x45: + { + if(vendor.ToLowerInvariant() == "stk") + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive manufacturer is StorageTek, setting media type to T9840C.", + mediumType, densityCode); + + return MediaType.T9840C; + } + + break; + } + + case 0x46: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to LTO-4.", + mediumType, densityCode); + + return MediaType.LTO4; + } + + if(vendor.ToLowerInvariant() == "stk") + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive manufacturer is StorageTek, setting media type to T9840D.", + mediumType, densityCode); + + return MediaType.T9840D; + } + + break; + } + + case 0x4A: + { + if(vendor.ToLowerInvariant() == "stk") + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive manufacturer is StorageTek, setting media type to T10000A.", + mediumType, densityCode); + + return MediaType.T10000A; + } + + break; + } + + case 0x4B: + { + if(vendor.ToLowerInvariant() == "stk") + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive manufacturer is StorageTek, setting media type to T10000B.", + mediumType, densityCode); + + return MediaType.T10000B; + } + + break; + } + + case 0x4C: + { + if(vendor.ToLowerInvariant() == "stk") + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive manufacturer is StorageTek, setting media type to T10000C.", + mediumType, densityCode); + + return MediaType.T10000C; + } + + break; + } + + case 0x4D: + { + if(vendor.ToLowerInvariant() == "stk") + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive manufacturer is StorageTek, setting media type to T10000D.", + mediumType, densityCode); + + return MediaType.T10000D; + } + + break; + } + + case 0x58: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to LTO-5.", + mediumType, densityCode); + + return MediaType.LTO5; + } + + break; + } + + // Used by some HP drives for all generations + case 0x8C: + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, setting media type to DDS.", + mediumType, densityCode); + + return MediaType.DDS1; + } + } + + break; + case 0x01: + { + switch(densityCode) + { + case 0x44: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to WORM LTO-3.", + mediumType, densityCode); + + return MediaType.LTO3WORM; + } + + break; + } + + case 0x46: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to WORM LTO-4.", + mediumType, densityCode); + + return MediaType.LTO4WORM; + } + + break; + } + + case 0x58: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to WORM LTO-5.", + mediumType, densityCode); + + return MediaType.LTO5WORM; + } + + break; + } + } + } + + break; + case 0x18: + { + switch(densityCode) + { + case 0x00: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to LTO.", + mediumType, densityCode); + + return MediaType.LTO; + } + + break; + } + + case 0x40: + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, setting media type to LTO.", + mediumType, densityCode); + + return MediaType.LTO; + } + } + } + + break; + case 0x28: + { + switch(densityCode) + { + case 0x00: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to LTO-2.", + mediumType, densityCode); + + return MediaType.LTO2; + } + + break; + } + + case 0x42: + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, setting media type to LTO-2.", + mediumType, densityCode); + + return MediaType.LTO2; + } + } + } + + break; + case 0x33: + { + switch(densityCode) + { + case 0x00: + case 0x25: + { + if(model.ToLowerInvariant().StartsWith("dat", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to DDS-3.", + mediumType, densityCode); + + return MediaType.DDS3; + } + + break; + } + } + } + + break; + case 0x34: + { + switch(densityCode) + { + case 0x00: + case 0x26: + { + if(model.ToLowerInvariant().StartsWith("dat", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to DDS-4.", + mediumType, densityCode); + + return MediaType.DDS4; + } + + break; + } + } + } + + break; + case 0x35: + { + switch(densityCode) + { + case 0x00: + case 0x47: + { + if(model.ToLowerInvariant().StartsWith("dat", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to DAT72.", + mediumType, densityCode); + + return MediaType.DAT72; + } + + break; + } + } + } + + break; + case 0x38: + { + switch(densityCode) + { + case 0x00: + case 0x44: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to LTO-3.", + mediumType, densityCode); + + return MediaType.LTO3; + } + + break; + } + } + } + + break; + case 0x3C: + { + switch(densityCode) + { + case 0x00: + case 0x44: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to WORM LTO-3.", + mediumType, densityCode); + + return MediaType.LTO3WORM; + } + + break; + } + } + } + + break; + case 0x48: + { + switch(densityCode) + { + case 0x00: + case 0x46: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to LTO-4.", + mediumType, densityCode); + + return MediaType.LTO4; + } + + break; + } + } + } + + break; + case 0x4C: + { + switch(densityCode) + { + case 0x00: + case 0x46: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to WORM LTO-4.", + mediumType, densityCode); + + return MediaType.LTO4WORM; + } + + break; + } + } + } + + break; + case 0x50: + { + switch(densityCode) + { + case 0x00: + case 0x24: + { + if(model.ToLowerInvariant().StartsWith("dat", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to DDS-2.", + mediumType, densityCode); + + return MediaType.DDS2; + } + + break; + } + } + } + + break; + case 0x58: + { + switch(densityCode) + { + case 0x00: + case 0x58: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to LTO-5.", + mediumType, densityCode); + + return MediaType.LTO5; + } + + break; + } + } + } + + break; + case 0x5C: + { + switch(densityCode) + { + case 0x00: + case 0x58: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to WORM LTO-5.", + mediumType, densityCode); + + return MediaType.LTO5WORM; + } + + break; + } + } + } + + break; + case 0x68: + { + switch(densityCode) + { + case 0x00: + case 0x5A: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to LTO-6.", + mediumType, densityCode); + + return MediaType.LTO6; + } + + break; + } + } + } + + break; + case 0x6C: + { + switch(densityCode) + { + case 0x00: + case 0x5A: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to WORM LTO-6.", + mediumType, densityCode); + + return MediaType.LTO6WORM; + } + + break; + } + } + } + + break; + case 0x78: + { + switch(densityCode) + { + case 0x00: + case 0x5C: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to LTO-7.", + mediumType, densityCode); + + return MediaType.LTO7; + } + + break; + } + } + } + + break; + case 0x7C: + { + switch(densityCode) + { + case 0x00: + case 0x5C: + { + if(model.ToLowerInvariant().StartsWith("ult", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"ult\" setting media type to WORM LTO-7.", + mediumType, densityCode); + + return MediaType.LTO7WORM; + } + + break; + } + } + } + + break; + case 0x81: + { + switch(densityCode) + { + case 0x00: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 15m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape15m; + } + + if(vendor.ToLowerInvariant() == "ibm") + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive manufacturer is IBM, setting media type to IBM 3592.", + mediumType, densityCode); + + return MediaType.IBM3592; + } + + if(model.ToLowerInvariant().StartsWith("vxa", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"vxa\" setting media type to VXA.", + mediumType, densityCode); + + return MediaType.VXA1; + } + + break; + } + + case 0x14: + case 0x15: + case 0x27: + case 0x8C: + case 0x90: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 15m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape15m; + } + + break; + } + + case 0x29: + case 0x2A: + { + if(vendor.ToLowerInvariant() == "ibm") + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive manufacturer is IBM, setting media type to IBM 3592.", + mediumType, densityCode); + + return MediaType.IBM3592; + } + + break; + } + + case 0x80: + { + if(model.ToLowerInvariant().StartsWith("vxa", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"vxa\" setting media type to VXA.", + mediumType, densityCode); + + return MediaType.VXA1; + } + + break; + } + } + } + + break; + case 0x82: + { + switch(densityCode) + { + case 0x00: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 28m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape28m; + } + + if(vendor.ToLowerInvariant() == "ibm") + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive manufacturer is IBM, setting media type to IBM 3592.", + mediumType, densityCode); + + return MediaType.IBM3592; + } + + break; + } + + case 0x0A: + { + if(model.ToLowerInvariant().StartsWith("dlt", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"dlt\" setting media type to CompactTape.", + mediumType, densityCode); + + return MediaType.CompactTapeI; + } + + break; + } + + case 0x14: + case 0x15: + case 0x27: + case 0x8C: + case 0x90: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 28m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape28m; + } + + break; + } + + case 0x16: + { + if(model.ToLowerInvariant().StartsWith("dlt", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"dlt\" setting media type to CompactTape II.", + mediumType, densityCode); + + return MediaType.CompactTapeII; + } + + break; + } + + case 0x29: + case 0x2A: + { + if(vendor.ToLowerInvariant() == "ibm") + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive manufacturer is IBM, setting media type to IBM 3592.", + mediumType, densityCode); + + return MediaType.IBM3592; + } + + break; + } + + case 0x81: + { + if(model.ToLowerInvariant().StartsWith("vxa", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"vxa\" setting media type to VXA 2.", + mediumType, densityCode); + + return MediaType.VXA2; + } + + break; + } + + case 0x82: + { + if(model.ToLowerInvariant().StartsWith("vxa", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"vxa\" setting media type to VXA 3.", + mediumType, densityCode); + + return MediaType.VXA3; + } + + break; + } + } + } + + break; + case 0x83: + { + switch(densityCode) + { + case 0x00: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 54m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape54m; + } + + if(model.ToLowerInvariant().StartsWith("dlt", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"dlt\" setting media type to DLTtape III.", + mediumType, densityCode); + + return MediaType.DLTtapeIII; + } + + break; + } + + case 0x14: + case 0x15: + case 0x27: + case 0x8C: + case 0x90: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 54m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape54m; + } + + break; + } + + case 0x17: + case 0x18: + case 0x19: + case 0x80: + case 0x81: + { + if(model.ToLowerInvariant().StartsWith("dlt", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"dlt\" setting media type to DLTtape III.", + mediumType, densityCode); + + return MediaType.DLTtapeIII; + } + + break; + } + } + } + + break; + case 0x84: + { + switch(densityCode) + { + case 0x00: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 80m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape80m; + } + + if(model.ToLowerInvariant().StartsWith("dlt", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"dlt\" setting media type to DLTtape IIIxt.", + mediumType, densityCode); + + return MediaType.DLTtapeIIIxt; + } + + break; + } + + case 0x14: + case 0x15: + case 0x27: + case 0x8C: + case 0x90: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 80m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape80m; + } + + break; + } + + case 0x19: + case 0x80: + case 0x81: + { + if(model.ToLowerInvariant().StartsWith("dlt", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"dlt\" setting media type to DLTtape IIIxt.", + mediumType, densityCode); + + return MediaType.DLTtapeIIIxt; + } + + break; + } + } + } + + break; + case 0x85: + { + switch(densityCode) + { + case 0x00: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 106m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape106m; + } + + if(model.ToLowerInvariant().StartsWith("dlt", StringComparison.Ordinal) || + model.ToLowerInvariant().StartsWith("sdlt", StringComparison.Ordinal) || + model.ToLowerInvariant().StartsWith("superdlt", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"dlt\" setting media type to DLTtape IV.", + mediumType, densityCode); + + return MediaType.DLTtapeIV; + } + + if(model.ToLowerInvariant().StartsWith("stt", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"stt\" setting media type to Travan 5.", + mediumType, densityCode); + + return MediaType.Travan5; + } + + break; + } + + case 0x14: + case 0x15: + case 0x27: + case 0x8C: + case 0x90: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 106m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape106m; + } + + break; + } + + case 0x1A: + case 0x1B: + case 0x40: + case 0x41: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + { + if(model.ToLowerInvariant().StartsWith("dlt", StringComparison.Ordinal) || + model.ToLowerInvariant().StartsWith("sdlt", StringComparison.Ordinal) || + model.ToLowerInvariant().StartsWith("superdlt", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"dlt\" setting media type to DLTtape IV.", + mediumType, densityCode); + + return MediaType.DLTtapeIV; + } + + break; + } + + case 0x46: + { + if(model.ToLowerInvariant().StartsWith("stt", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"stt\" setting media type to Travan 5.", + mediumType, densityCode); + + return MediaType.Travan5; + } + + break; + } + } + } + + break; + case 0x86: + { + switch(densityCode) + { + case 0x00: + case 0x90: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 160m Exatape XL.", + mediumType, densityCode); + + return MediaType.Exatape160mXL; + } + + if(model.ToLowerInvariant().StartsWith("dlt", StringComparison.Ordinal) || + model.ToLowerInvariant().StartsWith("sdlt", StringComparison.Ordinal) || + model.ToLowerInvariant().StartsWith("superdlt", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"dlt\" setting media type to SuperDLT.", + mediumType, densityCode); + + return MediaType.SDLT1; + } + + break; + } + + case 0x8C: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 160m Exatape XL.", + mediumType, densityCode); + + return MediaType.Exatape160mXL; + } + + break; + } + + case 0x91: + case 0x92: + case 0x93: + { + if(model.ToLowerInvariant().StartsWith("dlt", StringComparison.Ordinal) || + model.ToLowerInvariant().StartsWith("sdlt", StringComparison.Ordinal) || + model.ToLowerInvariant().StartsWith("superdlt", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"dlt\" setting media type to SuperDLT.", + mediumType, densityCode); + + return MediaType.SDLT1; + } + + break; + } + } + } + + break; + case 0x87: + { + switch(densityCode) + { + case 0x00: + case 0x4A: + { + if(model.ToLowerInvariant().StartsWith("dlt", StringComparison.Ordinal) || + model.ToLowerInvariant().StartsWith("sdlt", StringComparison.Ordinal) || + model.ToLowerInvariant().StartsWith("superdlt", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"dlt\" setting media type to SuperDLT 2.", + mediumType, densityCode); + + return MediaType.SDLT2; + } + + break; + } + } + } + + break; + case 0x90: + { + switch(densityCode) + { + case 0x00: + case 0x50: + case 0x98: + case 0x99: + { + if(model.ToLowerInvariant().StartsWith("dlt", StringComparison.Ordinal) || + model.ToLowerInvariant().StartsWith("sdlt", StringComparison.Ordinal) || + model.ToLowerInvariant().StartsWith("superdlt", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"dlt\" setting media type to VStape I.", + mediumType, densityCode); + + return MediaType.VStapeI; + } + + break; + } + } + } + + break; + case 0x95: + { + if(model.ToLowerInvariant().StartsWith("stt", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"stt\" setting media type to Travan 7.", + mediumType, densityCode); + + return MediaType.Travan7; + } + } + + break; + case 0xB6: + { + switch(densityCode) + { + case 0x45: + // HP Colorado tapes have a different capacity but return same density code at least in Seagate drives + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, setting media type to Travan 4.", + mediumType, densityCode); + + return MediaType.Travan4; + } + } + + break; + case 0xB7: + { + switch(densityCode) + { + case 0x47: + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, setting media type to Travan 5.", + mediumType, densityCode); + + return MediaType.Travan5; + } + } + + break; + case 0xC1: + { + switch(densityCode) + { + case 0x00: + case 0x14: + case 0x15: + case 0x8C: + case 0x90: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 22m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape22m; + } + + break; + } + } + } + + break; + case 0xC2: + { + switch(densityCode) + { + case 0x00: + case 0x14: + case 0x15: + case 0x27: + case 0x8C: + case 0x90: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 40m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape40m; + } + + break; + } + } + } + + break; + case 0xC3: + { + switch(densityCode) + { + case 0x00: + case 0x14: + case 0x15: + case 0x27: + case 0x8C: + case 0x90: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 76m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape76m; + } + + break; + } + } + } + + break; + case 0xC4: + { + switch(densityCode) + { + case 0x00: + case 0x14: + case 0x15: + case 0x27: + case 0x8C: + case 0x90: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 112m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape112m; + } + + break; + } + } + } + + break; + case 0xD1: + { + switch(densityCode) + { + case 0x00: + case 0x27: + case 0x28: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 22m Exatape AME.", + mediumType, densityCode); + + return MediaType.Exatape22mAME; + } + + break; + } + } + } + + break; + case 0xD2: + { + switch(densityCode) + { + case 0x00: + case 0x27: + case 0x28: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 170m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape170m; + } + + break; + } + } + } + + break; + case 0xD3: + { + switch(densityCode) + { + case 0x00: + case 0x27: + case 0x28: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 125m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape125m; + } + + break; + } + } + } + + break; + case 0xD4: + { + switch(densityCode) + { + case 0x00: + case 0x27: + case 0x28: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 45m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape45m; + } + + break; + } + } + } + + break; + case 0xD5: + { + switch(densityCode) + { + case 0x00: + case 0x27: + case 0x28: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 225m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape225m; + } + + break; + } + } + } + + break; + case 0xD6: + { + switch(densityCode) + { + case 0x00: + case 0x27: + case 0x28: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 150m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape150m; + } + + break; + } + } + } + + break; + case 0xD7: + { + switch(densityCode) + { + case 0x00: + case 0x27: + case 0x28: + { + if(model.ToLowerInvariant().StartsWith("exb", StringComparison.Ordinal)) + { + AaruConsole.DebugWriteLine("Media detection", + "SCSI medium type is {0:X2}h, density code is {1:X2}h, drive model starts with \"exb\" setting media type to 75m Exatape.", + mediumType, densityCode); + + return MediaType.Exatape75m; + } + + break; + } + } + } + + break; + } + + return MediaType.Unknown; + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Metadata/CdOffset.cs b/Aaru.CommonTypes/Metadata/CdOffset.cs new file mode 100644 index 000000000..885e32e56 --- /dev/null +++ b/Aaru.CommonTypes/Metadata/CdOffset.cs @@ -0,0 +1,58 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CdOffset.cs +// Author(s) : Natalia Portillo +// +// Component : Device database. +// +// --[ Description ] ---------------------------------------------------------- +// +// Models Compact Disc read offset entries from AccurateRip database. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.ComponentModel.DataAnnotations; + +namespace Aaru.CommonTypes.Metadata +{ + /// Describes CD reading offset + public class CdOffset + { + /// Drive manufacturer + public string Manufacturer { get; set; } + /// Drive model + public string Model { get; set; } + /// Reading offset + public short Offset { get; set; } + /// Number of times this offset has been submitted + public int Submissions { get; set; } + /// Percentage of submissions in agreement with this offset + [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:P0}")] + public float Agreement { get; set; } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Metadata/DeviceReport.cs b/Aaru.CommonTypes/Metadata/DeviceReport.cs new file mode 100644 index 000000000..8b9434278 --- /dev/null +++ b/Aaru.CommonTypes/Metadata/DeviceReport.cs @@ -0,0 +1,1070 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : DeviceReport.cs +// Author(s) : Natalia Portillo +// +// Component : XML metadata. +// +// --[ Description ] ---------------------------------------------------------- +// +// Contains classes for an XML device report. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.ComponentModel; +using System.Xml.Serialization; +using Aaru.CommonTypes.Structs.Devices.ATA; +using Aaru.CommonTypes.Structs.Devices.SCSI; +using Aaru.CommonTypes.Structs.Devices.SCSI.Modes; +using Newtonsoft.Json; + +// This is obsolete +#pragma warning disable 1591 + +// ReSharper disable InconsistentNaming +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Aaru.CommonTypes.Metadata +{ + [Serializable, XmlRoot("DicDeviceReport", Namespace = "", IsNullable = false)] + public class DeviceReport + { + public usbType USB { get; set; } + public firewireType FireWire { get; set; } + public pcmciaType PCMCIA { get; set; } + public bool CompactFlash { get; set; } + public ataType ATA { get; set; } + public ataType ATAPI { get; set; } + public scsiType SCSI { get; set; } + public mmcsdType MultiMediaCard { get; set; } + public mmcsdType SecureDigital { get; set; } + + [XmlIgnore] + public bool CompactFlashSpecified { get; set; } + } + + public class usbType + { + public ushort VendorID { get; set; } + public ushort ProductID { get; set; } + public string Manufacturer { get; set; } + public string Product { get; set; } + public bool RemovableMedia { get; set; } + public byte[] Descriptors { get; set; } + } + + public class firewireType + { + public uint VendorID { get; set; } + public uint ProductID { get; set; } + public string Manufacturer { get; set; } + public string Product { get; set; } + public bool RemovableMedia { get; set; } + } + + public class ataType + { + public string AdditionalPID { get; set; } + public Identify.TransferMode APIOSupported { get; set; } + public ushort ATAPIByteCount { get; set; } + public ushort BufferType { get; set; } + public ushort BufferSize { get; set; } + public Identify.CapabilitiesBit Capabilities { get; set; } + public Identify.CapabilitiesBit2 Capabilities2 { get; set; } + public Identify.CapabilitiesBit3 Capabilities3 { get; set; } + public ushort CFAPowerMode { get; set; } + public Identify.CommandSetBit CommandSet { get; set; } + public Identify.CommandSetBit2 CommandSet2 { get; set; } + public Identify.CommandSetBit3 CommandSet3 { get; set; } + public Identify.CommandSetBit4 CommandSet4 { get; set; } + public Identify.CommandSetBit5 CommandSet5 { get; set; } + public byte CurrentAAM { get; set; } + public ushort CurrentAPM { get; set; } + public Identify.DataSetMgmtBit DataSetMgmt { get; set; } + public ushort DataSetMgmtSize { get; set; } + public Identify.DeviceFormFactorEnum DeviceFormFactor { get; set; } + public Identify.TransferMode DMAActive { get; set; } + public Identify.TransferMode DMASupported { get; set; } + public byte DMATransferTimingMode { get; set; } + public ushort EnhancedSecurityEraseTime { get; set; } + public Identify.CommandSetBit EnabledCommandSet { get; set; } + public Identify.CommandSetBit2 EnabledCommandSet2 { get; set; } + public Identify.CommandSetBit3 EnabledCommandSet3 { get; set; } + public Identify.CommandSetBit4 EnabledCommandSet4 { get; set; } + public Identify.SATAFeaturesBit EnabledSATAFeatures { get; set; } + public ulong ExtendedUserSectors { get; set; } + public byte FreeFallSensitivity { get; set; } + public string FirmwareRevision { get; set; } + public Identify.GeneralConfigurationBit GeneralConfiguration { get; set; } + public ushort HardwareResetResult { get; set; } + public ushort InterseekDelay { get; set; } + public Identify.MajorVersionBit MajorVersion { get; set; } + public ushort MasterPasswordRevisionCode { get; set; } + public ushort MaxDownloadMicroMode3 { get; set; } + public ushort MaxQueueDepth { get; set; } + public Identify.TransferMode MDMAActive { get; set; } + public Identify.TransferMode MDMASupported { get; set; } + public ushort MinDownloadMicroMode3 { get; set; } + public ushort MinMDMACycleTime { get; set; } + public ushort MinorVersion { get; set; } + public ushort MinPIOCycleTimeNoFlow { get; set; } + public ushort MinPIOCycleTimeFlow { get; set; } + public string Model { get; set; } + public byte MultipleMaxSectors { get; set; } + public byte MultipleSectorNumber { get; set; } + public ushort NVCacheCaps { get; set; } + public uint NVCacheSize { get; set; } + public ushort NVCacheWriteSpeed { get; set; } + public byte NVEstimatedSpinUp { get; set; } + public ushort PacketBusRelease { get; set; } + public byte PIOTransferTimingMode { get; set; } + public byte RecommendedAAM { get; set; } + public ushort RecommendedMDMACycleTime { get; set; } + public ushort RemovableStatusSet { get; set; } + public Identify.SATACapabilitiesBit SATACapabilities { get; set; } + public Identify.SATACapabilitiesBit2 SATACapabilities2 { get; set; } + public Identify.SATAFeaturesBit SATAFeatures { get; set; } + public Identify.SCTCommandTransportBit SCTCommandTransport { get; set; } + public uint SectorsPerCard { get; set; } + public ushort SecurityEraseTime { get; set; } + public Identify.SecurityStatusBit SecurityStatus { get; set; } + public ushort ServiceBusyClear { get; set; } + public Identify.SpecificConfigurationEnum SpecificConfiguration { get; set; } + public ushort StreamAccessLatency { get; set; } + public ushort StreamMinReqSize { get; set; } + public uint StreamPerformanceGranularity { get; set; } + public ushort StreamTransferTimeDMA { get; set; } + public ushort StreamTransferTimePIO { get; set; } + public ushort TransportMajorVersion { get; set; } + public ushort TransportMinorVersion { get; set; } + public Identify.TrustedComputingBit TrustedComputing { get; set; } + public Identify.TransferMode UDMAActive { get; set; } + public Identify.TransferMode UDMASupported { get; set; } + public byte WRVMode { get; set; } + public uint WRVSectorCountMode3 { get; set; } + public uint WRVSectorCountMode2 { get; set; } + + public byte[] Identify { get; set; } + + public testedMediaType ReadCapabilities { get; set; } + public testedMediaType[] RemovableMedias { get; set; } + + [XmlIgnore] + public bool AdditionalPIDSpecified { get; set; } + [XmlIgnore] + public bool APIOSupportedSpecified { get; set; } + [XmlIgnore] + public bool ATAPIByteCountSpecified { get; set; } + [XmlIgnore] + public bool BufferTypeSpecified { get; set; } + [XmlIgnore] + public bool BufferSizeSpecified { get; set; } + [XmlIgnore] + public bool CapabilitiesSpecified { get; set; } + [XmlIgnore] + public bool Capabilities2Specified { get; set; } + [XmlIgnore] + public bool Capabilities3Specified { get; set; } + [XmlIgnore] + public bool CFAPowerModeSpecified { get; set; } + [XmlIgnore] + public bool CommandSetSpecified { get; set; } + [XmlIgnore] + public bool CommandSet2Specified { get; set; } + [XmlIgnore] + public bool CommandSet3Specified { get; set; } + [XmlIgnore] + public bool CommandSet4Specified { get; set; } + [XmlIgnore] + public bool CommandSet5Specified { get; set; } + [XmlIgnore] + public bool CurrentAAMSpecified { get; set; } + [XmlIgnore] + public bool CurrentAPMSpecified { get; set; } + [XmlIgnore] + public bool DataSetMgmtSpecified { get; set; } + [XmlIgnore] + public bool DataSetMgmtSizeSpecified { get; set; } + [XmlIgnore] + public bool DeviceFormFactorSpecified { get; set; } + [XmlIgnore] + public bool DMAActiveSpecified { get; set; } + [XmlIgnore] + public bool DMASupportedSpecified { get; set; } + [XmlIgnore] + public bool DMATransferTimingModeSpecified { get; set; } + [XmlIgnore] + public bool EnhancedSecurityEraseTimeSpecified { get; set; } + [XmlIgnore] + public bool EnabledCommandSetSpecified { get; set; } + [XmlIgnore] + public bool EnabledCommandSet2Specified { get; set; } + [XmlIgnore] + public bool EnabledCommandSet3Specified { get; set; } + [XmlIgnore] + public bool EnabledCommandSet4Specified { get; set; } + [XmlIgnore] + public bool EnabledSATAFeaturesSpecified { get; set; } + [XmlIgnore] + public bool ExtendedIdentifySpecified { get; set; } + [XmlIgnore] + public bool ExtendedUserSectorsSpecified { get; set; } + [XmlIgnore] + public bool FreeFallSensitivitySpecified { get; set; } + [XmlIgnore] + public bool FirmwareRevisionSpecified { get; set; } + [XmlIgnore] + public bool GeneralConfigurationSpecified { get; set; } + [XmlIgnore] + public bool HardwareResetResultSpecified { get; set; } + [XmlIgnore] + public bool InterseekDelaySpecified { get; set; } + [XmlIgnore] + public bool MajorVersionSpecified { get; set; } + [XmlIgnore] + public bool MasterPasswordRevisionCodeSpecified { get; set; } + [XmlIgnore] + public bool MaxDownloadMicroMode3Specified { get; set; } + [XmlIgnore] + public bool MaxQueueDepthSpecified { get; set; } + [XmlIgnore] + public bool MDMAActiveSpecified { get; set; } + [XmlIgnore] + public bool MDMASupportedSpecified { get; set; } + [XmlIgnore] + public bool MinDownloadMicroMode3Specified { get; set; } + [XmlIgnore] + public bool MinMDMACycleTimeSpecified { get; set; } + [XmlIgnore] + public bool MinorVersionSpecified { get; set; } + [XmlIgnore] + public bool MinPIOCycleTimeNoFlowSpecified { get; set; } + [XmlIgnore] + public bool MinPIOCycleTimeFlowSpecified { get; set; } + [XmlIgnore] + public bool ModelSpecified { get; set; } + [XmlIgnore] + public bool MultipleMaxSectorsSpecified { get; set; } + [XmlIgnore] + public bool MultipleSectorNumberSpecified { get; set; } + [XmlIgnore] + public bool NVCacheCapsSpecified { get; set; } + [XmlIgnore] + public bool NVCacheSizeSpecified { get; set; } + [XmlIgnore] + public bool NVCacheWriteSpeedSpecified { get; set; } + [XmlIgnore] + public bool NVEstimatedSpinUpSpecified { get; set; } + [XmlIgnore] + public bool PacketBusReleaseSpecified { get; set; } + [XmlIgnore] + public bool PIOTransferTimingModeSpecified { get; set; } + [XmlIgnore] + public bool RecommendedAAMSpecified { get; set; } + [XmlIgnore] + public bool RecommendedMDMACycleTimeSpecified { get; set; } + [XmlIgnore] + public bool RemovableStatusSetSpecified { get; set; } + [XmlIgnore] + public bool SATACapabilitiesSpecified { get; set; } + [XmlIgnore] + public bool SATACapabilities2Specified { get; set; } + [XmlIgnore] + public bool SATAFeaturesSpecified { get; set; } + [XmlIgnore] + public bool SCTCommandTransportSpecified { get; set; } + [XmlIgnore] + public bool SectorsPerCardSpecified { get; set; } + [XmlIgnore] + public bool SecurityEraseTimeSpecified { get; set; } + [XmlIgnore] + public bool SecurityStatusSpecified { get; set; } + [XmlIgnore] + public bool ServiceBusyClearSpecified { get; set; } + [XmlIgnore] + public bool SpecificConfigurationSpecified { get; set; } + [XmlIgnore] + public bool StreamAccessLatencySpecified { get; set; } + [XmlIgnore] + public bool StreamMinReqSizeSpecified { get; set; } + [XmlIgnore] + public bool StreamPerformanceGranularitySpecified { get; set; } + [XmlIgnore] + public bool StreamTransferTimeDMASpecified { get; set; } + [XmlIgnore] + public bool StreamTransferTimePIOSpecified { get; set; } + [XmlIgnore] + public bool TransportMajorVersionSpecified { get; set; } + [XmlIgnore] + public bool TransportMinorVersionSpecified { get; set; } + [XmlIgnore] + public bool TrustedComputingSpecified { get; set; } + [XmlIgnore] + public bool UDMAActiveSpecified { get; set; } + [XmlIgnore] + public bool UDMASupportedSpecified { get; set; } + [XmlIgnore] + public bool WRVModeSpecified { get; set; } + [XmlIgnore] + public bool WRVSectorCountMode3Specified { get; set; } + [XmlIgnore] + public bool WRVSectorCountMode2Specified { get; set; } + } + + public class chsType + { + public ushort Cylinders { get; set; } + public ushort Heads { get; set; } + public ushort Sectors { get; set; } + } + + public class scsiType + { + public scsiInquiryType Inquiry { get; set; } + public pageType[] EVPDPages { get; set; } + public bool SupportsModeSense6 { get; set; } + public bool SupportsModeSense10 { get; set; } + public bool SupportsModeSubpages { get; set; } + public modeType ModeSense { get; set; } + public mmcType MultiMediaDevice { get; set; } + public testedMediaType ReadCapabilities { get; set; } + public testedMediaType[] RemovableMedias { get; set; } + public sscType SequentialDevice { get; set; } + public byte[] ModeSense6Data { get; set; } + public byte[] ModeSense10Data { get; set; } + + [XmlIgnore] + public bool ReadCapabilitiesSpecified { get; set; } + } + + public class scsiInquiryType + { + public bool AccessControlCoordinator { get; set; } + public bool ACKRequests { get; set; } + public bool AERCSupported { get; set; } + public bool Address16 { get; set; } + public bool Address32 { get; set; } + public byte ANSIVersion { get; set; } + public TGPSValues AsymmetricalLUNAccess { get; set; } + public bool BasicQueueing { get; set; } + public byte DeviceTypeModifier { get; set; } + public byte ECMAVersion { get; set; } + public bool EnclosureServices { get; set; } + public bool HierarchicalLUN { get; set; } + public bool IUS { get; set; } + public byte ISOVersion { get; set; } + public bool LinkedCommands { get; set; } + public bool MediumChanger { get; set; } + public bool MultiPortDevice { get; set; } + public bool NormalACA { get; set; } + public PeripheralDeviceTypes PeripheralDeviceType { get; set; } + public PeripheralQualifiers PeripheralQualifier { get; set; } + public string ProductIdentification { get; set; } + public string ProductRevisionLevel { get; set; } + public bool Protection { get; set; } + public bool QAS { get; set; } + public bool RelativeAddressing { get; set; } + public bool Removable { get; set; } + public byte ResponseDataFormat { get; set; } + public bool TaggedCommandQueue { get; set; } + public bool TerminateTaskSupported { get; set; } + public bool ThirdPartyCopy { get; set; } + public bool TranferDisable { get; set; } + public bool SoftReset { get; set; } + public SPIClocking SPIClocking { get; set; } + public bool StorageArrayController { get; set; } + public bool SyncTransfer { get; set; } + public string VendorIdentification { get; set; } + public ushort[] VersionDescriptors { get; set; } + public bool WideBus16 { get; set; } + public bool WideBus32 { get; set; } + public byte[] Data { get; set; } + + [XmlIgnore] + public bool ANSIVersionSpecified { get; set; } + [XmlIgnore] + public bool ECMAVersionSpecified { get; set; } + [XmlIgnore] + public bool DeviceTypeModifierSpecified { get; set; } + [XmlIgnore] + public bool ISOVersionSpecified { get; set; } + [XmlIgnore] + public bool ProductIdentificationSpecified { get; set; } + [XmlIgnore] + public bool ProductRevisionLevelSpecified { get; set; } + [XmlIgnore] + public bool ResponseDataFormatSpecified { get; set; } + [XmlIgnore] + public bool VendorIdentificationSpecified { get; set; } + } + + [Serializable] + public class pageType + { + [XmlAttribute] + public byte page { get; set; } + + [XmlText] + public byte[] value { get; set; } + } + + public class modeType + { + public byte MediumType { get; set; } + public bool WriteProtected { get; set; } + public blockDescriptorType[] BlockDescriptors { get; set; } + public byte Speed { get; set; } + public byte BufferedMode { get; set; } + public bool BlankCheckEnabled { get; set; } + public bool DPOandFUA { get; set; } + public modePageType[] ModePages { get; set; } + + [XmlIgnore] + public bool MediumTypeSpecified { get; set; } + [XmlIgnore] + public bool SpeedSpecified { get; set; } + [XmlIgnore] + public bool BufferedModeSpecified { get; set; } + } + + public class blockDescriptorType + { + public byte Density { get; set; } + public ulong Blocks { get; set; } + public uint BlockLength { get; set; } + + [XmlIgnore] + public bool BlocksSpecified { get; set; } + [XmlIgnore] + public bool BlockLengthSpecified { get; set; } + } + + [Serializable] + public class modePageType + { + [XmlAttribute] + public byte page { get; set; } + + [XmlAttribute] + public byte subpage { get; set; } + + [XmlText] + public byte[] value { get; set; } + } + + public class mmcType + { + public mmcModeType ModeSense2A { get; set; } + public mmcFeaturesType Features { get; set; } + public testedMediaType[] TestedMedia { get; set; } + } + + public class mmcModeType + { + public bool AccurateCDDA { get; set; } + public bool BCK { get; set; } + public ushort BufferSize { get; set; } + public bool BufferUnderRunProtection { get; set; } + public bool CanEject { get; set; } + public bool CanLockMedia { get; set; } + public bool CDDACommand { get; set; } + public bool CompositeAudioVideo { get; set; } + public bool CSSandCPPMSupported { get; set; } + public ushort CurrentSpeed { get; set; } + public ushort CurrentWriteSpeed { get; set; } + public ushort CurrentWriteSpeedSelected { get; set; } + public bool DeterministicSlotChanger { get; set; } + public bool DigitalPort1 { get; set; } + public bool DigitalPort2 { get; set; } + public bool LeadInPW { get; set; } + public byte LoadingMechanismType { get; set; } + public bool LockStatus { get; set; } + public bool LSBF { get; set; } + public ushort MaximumSpeed { get; set; } + public ushort MaximumWriteSpeed { get; set; } + public bool PlaysAudio { get; set; } + public bool PreventJumperStatus { get; set; } + public bool RCK { get; set; } + public bool ReadsBarcode { get; set; } + public bool ReadsBothSides { get; set; } + public bool ReadsCDR { get; set; } + public bool ReadsCDRW { get; set; } + public bool ReadsDeinterlavedSubchannel { get; set; } + public bool ReadsDVDR { get; set; } + public bool ReadsDVDRAM { get; set; } + public bool ReadsDVDROM { get; set; } + public bool ReadsISRC { get; set; } + public bool ReadsMode2Form2 { get; set; } + public bool ReadsMode2Form1 { get; set; } + public bool ReadsPacketCDR { get; set; } + public bool ReadsSubchannel { get; set; } + public bool ReadsUPC { get; set; } + public bool ReturnsC2Pointers { get; set; } + public byte RotationControlSelected { get; set; } + public bool SeparateChannelMute { get; set; } + public bool SeparateChannelVolume { get; set; } + public bool SSS { get; set; } + public bool SupportsMultiSession { get; set; } + public ushort SupportedVolumeLevels { get; set; } + public bool TestWrite { get; set; } + public bool WritesCDR { get; set; } + public bool WritesCDRW { get; set; } + public bool WritesDVDR { get; set; } + public bool WritesDVDRAM { get; set; } + public ModePage_2A_WriteDescriptor[] WriteSpeedPerformanceDescriptors { get; set; } + + [XmlIgnore] + public bool MaximumSpeedSpecified { get; set; } + [XmlIgnore] + public bool SupportedVolumeLevelsSpecified { get; set; } + [XmlIgnore] + public bool BufferSizeSpecified { get; set; } + [XmlIgnore] + public bool CurrentSpeedSpecified { get; set; } + [XmlIgnore] + public bool MaximumWriteSpeedSpecified { get; set; } + [XmlIgnore] + public bool CurrentWriteSpeedSpecified { get; set; } + [XmlIgnore] + public bool RotationControlSelectedSpecified { get; set; } + [XmlIgnore] + public bool CurrentWriteSpeedSelectedSpecified { get; set; } + } + + public class mmcFeaturesType + { + public byte AACSVersion { get; set; } + public byte AGIDs { get; set; } + public byte BindingNonceBlocks { get; set; } + public ushort BlocksPerReadableUnit { get; set; } + public bool BufferUnderrunFreeInDVD { get; set; } + public bool BufferUnderrunFreeInSAO { get; set; } + public bool BufferUnderrunFreeInTAO { get; set; } + public bool CanAudioScan { get; set; } + public bool CanEject { get; set; } + public bool CanEraseSector { get; set; } + public bool CanExpandBDRESpareArea { get; set; } + public bool CanFormat { get; set; } + public bool CanFormatBDREWithoutSpare { get; set; } + public bool CanFormatCert { get; set; } + public bool CanFormatFRF { get; set; } + public bool CanFormatQCert { get; set; } + public bool CanFormatRRM { get; set; } + public bool CanGenerateBindingNonce { get; set; } + public bool CanLoad { get; set; } + public bool CanMuteSeparateChannels { get; set; } + public bool CanOverwriteSAOTrack { get; set; } + public bool CanOverwriteTAOTrack { get; set; } + public bool CanPlayCDAudio { get; set; } + public bool CanPseudoOverwriteBDR { get; set; } + public bool CanReadAllDualR { get; set; } + public bool CanReadAllDualRW { get; set; } + public bool CanReadBD { get; set; } + public bool CanReadBDR { get; set; } + public bool CanReadBDRE1 { get; set; } + public bool CanReadBDRE2 { get; set; } + public bool CanReadBDROM { get; set; } + public bool CanReadBluBCA { get; set; } + public bool CanReadCD { get; set; } + public bool CanReadCDMRW { get; set; } + public bool CanReadCPRM_MKB { get; set; } + public bool CanReadDDCD { get; set; } + public bool CanReadDVD { get; set; } + public bool CanReadDVDPlusMRW { get; set; } + public bool CanReadDVDPlusR { get; set; } + public bool CanReadDVDPlusRDL { get; set; } + public bool CanReadDVDPlusRW { get; set; } + public bool CanReadDVDPlusRWDL { get; set; } + public bool CanReadDriveAACSCertificate { get; set; } + public bool CanReadHDDVD { get; set; } + public bool CanReadHDDVDR { get; set; } + public bool CanReadHDDVDRAM { get; set; } + public bool CanReadLeadInCDText { get; set; } + public bool CanReadOldBDR { get; set; } + public bool CanReadOldBDRE { get; set; } + public bool CanReadOldBDROM { get; set; } + public bool CanReadSpareAreaInformation { get; set; } + public bool CanReportDriveSerial { get; set; } + public bool CanReportMediaSerial { get; set; } + public bool CanTestWriteDDCDR { get; set; } + public bool CanTestWriteDVD { get; set; } + public bool CanTestWriteInSAO { get; set; } + public bool CanTestWriteInTAO { get; set; } + public bool CanUpgradeFirmware { get; set; } + public bool CanWriteBD { get; set; } + public bool CanWriteBDR { get; set; } + public bool CanWriteBDRE1 { get; set; } + public bool CanWriteBDRE2 { get; set; } + public bool CanWriteBusEncryptedBlocks { get; set; } + public bool CanWriteCDMRW { get; set; } + public bool CanWriteCDRW { get; set; } + public bool CanWriteCDRWCAV { get; set; } + public bool CanWriteCDSAO { get; set; } + public bool CanWriteCDTAO { get; set; } + public bool CanWriteCSSManagedDVD { get; set; } + public bool CanWriteDDCDR { get; set; } + public bool CanWriteDDCDRW { get; set; } + public bool CanWriteDVDPlusMRW { get; set; } + public bool CanWriteDVDPlusR { get; set; } + public bool CanWriteDVDPlusRDL { get; set; } + public bool CanWriteDVDPlusRW { get; set; } + public bool CanWriteDVDPlusRWDL { get; set; } + public bool CanWriteDVDR { get; set; } + public bool CanWriteDVDRDL { get; set; } + public bool CanWriteDVDRW { get; set; } + public bool CanWriteHDDVDR { get; set; } + public bool CanWriteHDDVDRAM { get; set; } + public bool CanWriteOldBDR { get; set; } + public bool CanWriteOldBDRE { get; set; } + public bool CanWritePackedSubchannelInTAO { get; set; } + public bool CanWriteRWSubchannelInSAO { get; set; } + public bool CanWriteRWSubchannelInTAO { get; set; } + public bool CanWriteRaw { get; set; } + public bool CanWriteRawMultiSession { get; set; } + public bool CanWriteRawSubchannelInTAO { get; set; } + public bool ChangerIsSideChangeCapable { get; set; } + public byte ChangerSlots { get; set; } + public bool ChangerSupportsDiscPresent { get; set; } + public byte CPRMVersion { get; set; } + public byte CSSVersion { get; set; } + public bool DBML { get; set; } + public bool DVDMultiRead { get; set; } + public bool EmbeddedChanger { get; set; } + public bool ErrorRecoveryPage { get; set; } + [XmlElement(DataType = "date")] + public DateTime FirmwareDate { get; set; } + public byte LoadingMechanismType { get; set; } + public bool Locked { get; set; } + public uint LogicalBlockSize { get; set; } + public bool MultiRead { get; set; } + public PhysicalInterfaces PhysicalInterfaceStandard { get; set; } + public uint PhysicalInterfaceStandardNumber { get; set; } + public bool PreventJumper { get; set; } + public bool SupportsAACS { get; set; } + public bool SupportsBusEncryption { get; set; } + public bool SupportsC2 { get; set; } + public bool SupportsCPRM { get; set; } + public bool SupportsCSS { get; set; } + public bool SupportsDAP { get; set; } + public bool SupportsDeviceBusyEvent { get; set; } + public bool SupportsHybridDiscs { get; set; } + public bool SupportsModePage1Ch { get; set; } + public bool SupportsOSSC { get; set; } + public bool SupportsPWP { get; set; } + public bool SupportsSWPP { get; set; } + public bool SupportsSecurDisc { get; set; } + public bool SupportsSeparateVolume { get; set; } + public bool SupportsVCPS { get; set; } + public bool SupportsWriteInhibitDCB { get; set; } + public bool SupportsWriteProtectPAC { get; set; } + public ushort VolumeLevels { get; set; } + + [XmlIgnore] + public bool PhysicalInterfaceStandardSpecified { get; set; } + [XmlIgnore] + public bool PhysicalInterfaceStandardNumberSpecified { get; set; } + [XmlIgnore] + public bool AACSVersionSpecified { get; set; } + [XmlIgnore] + public bool AGIDsSpecified { get; set; } + [XmlIgnore] + public bool BindingNonceBlocksSpecified { get; set; } + [XmlIgnore] + public bool CPRMVersionSpecified { get; set; } + [XmlIgnore] + public bool CSSVersionSpecified { get; set; } + [XmlIgnore] + public bool ChangerHighestSlotNumberSpecified { get; set; } + [XmlIgnore] + public bool LoadingMechanismTypeSpecified { get; set; } + [XmlIgnore] + public bool LogicalBlockSizeSpecified { get; set; } + [XmlIgnore] + public bool BlocksPerReadableUnitSpecified { get; set; } + [XmlIgnore] + public bool FirmwareDateSpecified { get; set; } + [XmlIgnore] + public bool VolumeLevelsSpecified { get; set; } + } + + public class testedMediaType + { + public ulong Blocks { get; set; } + public uint BlockSize { get; set; } + public bool CanReadAACS { get; set; } + public bool CanReadADIP { get; set; } + public bool CanReadATIP { get; set; } + public bool CanReadBCA { get; set; } + public bool CanReadC2Pointers { get; set; } + public bool CanReadCMI { get; set; } + public bool CanReadCorrectedSubchannel { get; set; } + public bool CanReadCorrectedSubchannelWithC2 { get; set; } + public bool CanReadDCB { get; set; } + public bool CanReadDDS { get; set; } + public bool CanReadDMI { get; set; } + public bool CanReadDiscInformation { get; set; } + public bool CanReadFullTOC { get; set; } + public bool CanReadHDCMI { get; set; } + public bool CanReadLayerCapacity { get; set; } + public bool CanReadLeadIn { get; set; } + public bool CanReadLeadOut { get; set; } + public bool CanReadMediaID { get; set; } + public bool CanReadMediaSerial { get; set; } + public bool CanReadPAC { get; set; } + public bool CanReadPFI { get; set; } + public bool CanReadPMA { get; set; } + public bool CanReadPQSubchannel { get; set; } + public bool CanReadPQSubchannelWithC2 { get; set; } + public bool CanReadPRI { get; set; } + public bool CanReadRWSubchannel { get; set; } + public bool CanReadRWSubchannelWithC2 { get; set; } + public bool CanReadRecordablePFI { get; set; } + public bool CanReadSpareAreaInformation { get; set; } + public bool CanReadTOC { get; set; } + public byte Density { get; set; } + public uint LongBlockSize { get; set; } + public string Manufacturer { get; set; } + public bool MediaIsRecognized { get; set; } + public byte MediumType { get; set; } + public string MediumTypeName { get; set; } + public string Model { get; set; } + public bool SupportsHLDTSTReadRawDVD { get; set; } + public bool SupportsNECReadCDDA { get; set; } + public bool SupportsPioneerReadCDDA { get; set; } + public bool SupportsPioneerReadCDDAMSF { get; set; } + public bool SupportsPlextorReadCDDA { get; set; } + public bool SupportsPlextorReadRawDVD { get; set; } + public bool SupportsRead10 { get; set; } + public bool SupportsRead12 { get; set; } + public bool SupportsRead16 { get; set; } + public bool SupportsRead { get; set; } + public bool SupportsReadCapacity16 { get; set; } + public bool SupportsReadCapacity { get; set; } + public bool SupportsReadCd { get; set; } + public bool SupportsReadCdMsf { get; set; } + public bool SupportsReadCdRaw { get; set; } + public bool SupportsReadCdMsfRaw { get; set; } + public bool SupportsReadLong16 { get; set; } + public bool SupportsReadLong { get; set; } + + public byte[] ModeSense6Data { get; set; } + public byte[] ModeSense10Data { get; set; } + + [XmlIgnore] + public bool BlocksSpecified { get; set; } + [XmlIgnore] + public bool BlockSizeSpecified { get; set; } + [XmlIgnore] + public bool CanReadAACSSpecified { get; set; } + [XmlIgnore] + public bool CanReadADIPSpecified { get; set; } + [XmlIgnore] + public bool CanReadATIPSpecified { get; set; } + [XmlIgnore] + public bool CanReadBCASpecified { get; set; } + [XmlIgnore] + public bool CanReadC2PointersSpecified { get; set; } + [XmlIgnore] + public bool CanReadCMISpecified { get; set; } + [XmlIgnore] + public bool CanReadCorrectedSubchannelSpecified { get; set; } + [XmlIgnore] + public bool CanReadCorrectedSubchannelWithC2Specified { get; set; } + [XmlIgnore] + public bool CanReadDCBSpecified { get; set; } + [XmlIgnore] + public bool CanReadDDSSpecified { get; set; } + [XmlIgnore] + public bool CanReadDMISpecified { get; set; } + [XmlIgnore] + public bool CanReadDiscInformationSpecified { get; set; } + [XmlIgnore] + public bool CanReadFullTOCSpecified { get; set; } + [XmlIgnore] + public bool CanReadHDCMISpecified { get; set; } + [XmlIgnore] + public bool CanReadLayerCapacitySpecified { get; set; } + [XmlIgnore] + public bool CanReadLeadInSpecified { get; set; } + [XmlIgnore] + public bool CanReadLeadOutSpecified { get; set; } + [XmlIgnore] + public bool CanReadMediaIDSpecified { get; set; } + [XmlIgnore] + public bool CanReadMediaSerialSpecified { get; set; } + [XmlIgnore] + public bool CanReadPACSpecified { get; set; } + [XmlIgnore] + public bool CanReadPFISpecified { get; set; } + [XmlIgnore] + public bool CanReadPMASpecified { get; set; } + [XmlIgnore] + public bool CanReadPQSubchannelSpecified { get; set; } + [XmlIgnore] + public bool CanReadPQSubchannelWithC2Specified { get; set; } + [XmlIgnore] + public bool CanReadPRISpecified { get; set; } + [XmlIgnore] + public bool CanReadRWSubchannelSpecified { get; set; } + [XmlIgnore] + public bool CanReadRWSubchannelWithC2Specified { get; set; } + [XmlIgnore] + public bool CanReadRecordablePFISpecified { get; set; } + [XmlIgnore] + public bool CanReadSpareAreaInformationSpecified { get; set; } + [XmlIgnore] + public bool CanReadTOCSpecified { get; set; } + [XmlIgnore] + public bool DensitySpecified { get; set; } + [XmlIgnore] + public bool LongBlockSizeSpecified { get; set; } + [XmlIgnore] + public bool ManufacturerSpecified { get; set; } + [XmlIgnore] + public bool MediumTypeSpecified { get; set; } + [XmlIgnore] + public bool ModelSpecified { get; set; } + [XmlIgnore] + public bool SupportsHLDTSTReadRawDVDSpecified { get; set; } + [XmlIgnore] + public bool SupportsNECReadCDDASpecified { get; set; } + [XmlIgnore] + public bool SupportsPioneerReadCDDASpecified { get; set; } + [XmlIgnore] + public bool SupportsPioneerReadCDDAMSFSpecified { get; set; } + [XmlIgnore] + public bool SupportsPlextorReadCDDASpecified { get; set; } + [XmlIgnore] + public bool SupportsPlextorReadRawDVDSpecified { get; set; } + [XmlIgnore] + public bool SupportsRead10Specified { get; set; } + [XmlIgnore] + public bool SupportsRead12Specified { get; set; } + [XmlIgnore] + public bool SupportsRead16Specified { get; set; } + [XmlIgnore] + public bool SupportsReadSpecified { get; set; } + [XmlIgnore] + public bool SupportsReadCapacity16Specified { get; set; } + [XmlIgnore] + public bool SupportsReadCapacitySpecified { get; set; } + [XmlIgnore] + public bool SupportsReadCdSpecified { get; set; } + [XmlIgnore] + public bool SupportsReadCdMsfSpecified { get; set; } + [XmlIgnore] + public bool SupportsReadCdRawSpecified { get; set; } + [XmlIgnore] + public bool SupportsReadCdMsfRawSpecified { get; set; } + [XmlIgnore] + public bool SupportsReadLong16Specified { get; set; } + [XmlIgnore] + public bool SupportsReadLongSpecified { get; set; } + + public chsType CHS { get; set; } + public chsType CurrentCHS { get; set; } + public uint LBASectors { get; set; } + public ulong LBA48Sectors { get; set; } + public ushort LogicalAlignment { get; set; } + public ushort NominalRotationRate { get; set; } + public uint PhysicalBlockSize { get; set; } + public bool SolidStateDevice { get; set; } + public ushort UnformattedBPT { get; set; } + public ushort UnformattedBPS { get; set; } + + [XmlIgnore] + public bool LBASectorsSpecified { get; set; } + [XmlIgnore] + public bool LBA48SectorsSpecified { get; set; } + [XmlIgnore] + public bool LogicalAlignmentSpecified { get; set; } + [XmlIgnore] + public bool NominalRotationRateSpecified { get; set; } + [XmlIgnore] + public bool PhysicalBlockSizeSpecified { get; set; } + [XmlIgnore] + public bool SolidStateDeviceSpecified { get; set; } + [XmlIgnore] + public bool UnformattedBPTSpecified { get; set; } + [XmlIgnore] + public bool UnformattedBPSSpecified { get; set; } + + public bool SupportsReadDmaLba { get; set; } + public bool SupportsReadDmaRetryLba { get; set; } + public bool SupportsReadLba { get; set; } + public bool SupportsReadRetryLba { get; set; } + public bool SupportsReadLongLba { get; set; } + public bool SupportsReadLongRetryLba { get; set; } + public bool SupportsSeekLba { get; set; } + + public bool SupportsReadDmaLba48 { get; set; } + public bool SupportsReadLba48 { get; set; } + + public bool SupportsReadDma { get; set; } + public bool SupportsReadDmaRetry { get; set; } + public bool SupportsReadRetry { get; set; } + public bool SupportsReadLongRetry { get; set; } + public bool SupportsSeek { get; set; } + + [XmlIgnore] + public bool SupportsReadDmaLbaSpecified { get; set; } + [XmlIgnore] + public bool SupportsReadDmaRetryLbaSpecified { get; set; } + [XmlIgnore] + public bool SupportsReadLbaSpecified { get; set; } + [XmlIgnore] + public bool SupportsReadRetryLbaSpecified { get; set; } + [XmlIgnore] + public bool SupportsReadLongLbaSpecified { get; set; } + [XmlIgnore] + public bool SupportsReadLongRetryLbaSpecified { get; set; } + [XmlIgnore] + public bool SupportsSeekLbaSpecified { get; set; } + + [XmlIgnore] + public bool SupportsReadDmaLba48Specified { get; set; } + [XmlIgnore] + public bool SupportsReadLba48Specified { get; set; } + + [XmlIgnore] + public bool SupportsReadDmaSpecified { get; set; } + [XmlIgnore] + public bool SupportsReadDmaRetrySpecified { get; set; } + [XmlIgnore] + public bool SupportsReadRetrySpecified { get; set; } + [XmlIgnore] + public bool SupportsReadLongRetrySpecified { get; set; } + [XmlIgnore] + public bool SupportsSeekSpecified { get; set; } + } + + public class sscType + { + public byte BlockSizeGranularity { get; set; } + public uint MaxBlockLength { get; set; } + public uint MinBlockLength { get; set; } + + public SupportedDensity[] SupportedDensities { get; set; } + public SupportedMedia[] SupportedMediaTypes { get; set; } + public SequentialMedia[] TestedMedia { get; set; } + + [XmlIgnore] + public bool BlockSizeGranularitySpecified { get; set; } + [XmlIgnore] + public bool MaxBlockLengthSpecified { get; set; } + [XmlIgnore] + public bool MinBlockLengthSpecified { get; set; } + } + + public class SupportedDensity + { + [XmlIgnore, JsonIgnore] + public int Id { get; set; } + [DisplayName("Primary density code")] + public byte PrimaryCode { get; set; } + [DisplayName("Secondary density code")] + public byte SecondaryCode { get; set; } + public bool Writable { get; set; } + public bool Duplicate { get; set; } + [DisplayName("Default density code")] + public bool DefaultDensity { get; set; } + [DisplayName("Bits per mm")] + public uint BitsPerMm { get; set; } + public ushort Width { get; set; } + public ushort Tracks { get; set; } + [DisplayName("Nominal capacity (MiB)")] + public uint Capacity { get; set; } + public string Organization { get; set; } + public string Name { get; set; } + public string Description { get; set; } + } + + public class SupportedMedia + { + [XmlIgnore, JsonIgnore] + public int Id { get; set; } + public byte MediumType { get; set; } + public int[] DensityCodes { get; set; } + public ushort Width { get; set; } + public ushort Length { get; set; } + public string Organization { get; set; } + public string Name { get; set; } + public string Description { get; set; } + } + + public struct SequentialMedia + { + public bool CanReadMediaSerial { get; set; } + public byte Density { get; set; } + public string Manufacturer { get; set; } + public bool MediaIsRecognized { get; set; } + public byte MediumType { get; set; } + public string MediumTypeName { get; set; } + public string Model { get; set; } + public SupportedDensity[] SupportedDensities { get; set; } + public SupportedMedia[] SupportedMediaTypes { get; set; } + + public byte[] ModeSense6Data { get; set; } + public byte[] ModeSense10Data { get; set; } + + [XmlIgnore] + public bool CanReadMediaSerialSpecified { get; set; } + [XmlIgnore] + public bool DensitySpecified { get; set; } + [XmlIgnore] + public bool MediumTypeSpecified { get; set; } + } + + [Serializable] + public class pcmciaType + { + public byte[] CIS { get; set; } + public string Compliance { get; set; } + public ushort ManufacturerCode { get; set; } + public ushort CardCode { get; set; } + public string Manufacturer { get; set; } + public string ProductName { get; set; } + public string[] AdditionalInformation { get; set; } + + [XmlIgnore] + public bool ManufacturerCodeSpecified { get; set; } + [XmlIgnore] + public bool CardCodeSpecified { get; set; } + } + + [Serializable] + public class mmcsdType + { + public byte[] CID { get; set; } + public byte[] CSD { get; set; } + public byte[] OCR { get; set; } + public byte[] SCR { get; set; } + public byte[] ExtendedCSD { get; set; } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Metadata/DeviceReportV2.cs b/Aaru.CommonTypes/Metadata/DeviceReportV2.cs new file mode 100644 index 000000000..aefd28a4f --- /dev/null +++ b/Aaru.CommonTypes/Metadata/DeviceReportV2.cs @@ -0,0 +1,2307 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : DeviceReportV2.cs +// Author(s) : Natalia Portillo +// +// Component : JSON metadata. +// +// --[ Description ] ---------------------------------------------------------- +// +// Contains classes for a JSON device report. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Structs.Devices.ATA; +using Aaru.CommonTypes.Structs.Devices.SCSI; +using Aaru.CommonTypes.Structs.Devices.SCSI.Modes; +using Newtonsoft.Json; + +// TODO: Re-enable CS1591 in this file +#pragma warning disable 1591 + +// ReSharper disable VirtualMemberNeverOverridden.Global +// ReSharper disable VirtualMemberCallInConstructor + +// ReSharper disable InconsistentNaming +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace Aaru.CommonTypes.Metadata +{ + public class DeviceReportV2 + { + public DeviceReportV2() {} + + public DeviceReportV2(DeviceReport reportV1) + { + if(reportV1.USB != null) + USB = new Usb(reportV1.USB); + + if(reportV1.FireWire != null) + FireWire = new FireWire(reportV1.FireWire); + + if(reportV1.PCMCIA != null) + PCMCIA = new Pcmcia(reportV1.PCMCIA); + + if(reportV1.CompactFlashSpecified) + CompactFlash = reportV1.CompactFlash; + + if(reportV1.ATA != null) + { + ATA = new Ata(reportV1.ATA); + Type = DeviceType.ATA; + } + + if(reportV1.SCSI != null) + { + SCSI = new Scsi(reportV1.SCSI); + Type = DeviceType.SCSI; + + if(SCSI.ModeSense?.ModePages?.FirstOrDefault(p => p.page == 0x2A)?.value != null) + { + if(SCSI.MultiMediaDevice != null) + SCSI.MultiMediaDevice.ModeSense2AData = + SCSI.ModeSense?.ModePages?.FirstOrDefault(p => p.page == 0x2A)?.value; + else if(SCSI.Inquiry?.PeripheralDeviceType == (byte)PeripheralDeviceTypes.MultiMediaDevice) + SCSI.MultiMediaDevice = new Mmc + { + ModeSense2AData = SCSI.ModeSense?.ModePages?.FirstOrDefault(p => p.page == 0x2A)?.value + }; + } + } + + if(reportV1.ATAPI != null) + { + ATAPI = new Ata(reportV1.ATAPI); + Type = DeviceType.ATAPI; + } + + if(reportV1.MultiMediaCard != null) + { + MultiMediaCard = new MmcSd(reportV1.MultiMediaCard); + Type = DeviceType.MMC; + } + + if(reportV1.SecureDigital != null) + { + SecureDigital = new MmcSd(reportV1.SecureDigital); + Type = DeviceType.SecureDigital; + } + + if(reportV1.SCSI?.Inquiry != null) + { + Manufacturer = reportV1.SCSI.Inquiry.VendorIdentification; + Model = reportV1.SCSI.Inquiry.ProductIdentification; + Revision = reportV1.SCSI.Inquiry.ProductRevisionLevel; + } + else if(reportV1.ATA != null || + reportV1.ATAPI != null) + { + ataType ata = reportV1.ATA ?? reportV1.ATAPI; + + string[] split = ata.Model.Split(' '); + + if(split.Length > 1) + { + Manufacturer = split[0]; + Model = string.Join(" ", split, 1, split.Length - 1); + } + else + Model = ata.Model; + + Revision = ata.FirmwareRevision; + } + } + + [JsonIgnore] + public int Id { get; set; } + public virtual Usb USB { get; set; } + public virtual FireWire FireWire { get; set; } + public virtual Pcmcia PCMCIA { get; set; } + public bool CompactFlash { get; set; } + public virtual Ata ATA { get; set; } + public virtual Ata ATAPI { get; set; } + public virtual Scsi SCSI { get; set; } + public virtual MmcSd MultiMediaCard { get; set; } + public virtual MmcSd SecureDigital { get; set; } + public virtual GdRomSwapDiscCapabilities GdRomSwapDiscCapabilities { get; set; } + + public string Manufacturer { get; set; } + public string Model { get; set; } + public string Revision { get; set; } + public DeviceType Type { get; set; } + } + + public class Usb + { + public Usb() {} + + public Usb(usbType usb) + { + VendorID = usb.VendorID; + ProductID = usb.ProductID; + Manufacturer = usb.Manufacturer; + Product = usb.Product; + RemovableMedia = usb.RemovableMedia; + Descriptors = usb.Descriptors; + } + + [JsonIgnore] + public int Id { get; set; } + [DisplayName("Vendor ID"), DisplayFormat(DataFormatString = "0x{0:X4}")] + public ushort VendorID { get; set; } + [DisplayName("Product ID"), DisplayFormat(DataFormatString = "0x{0:X4}")] + public ushort ProductID { get; set; } + public string Manufacturer { get; set; } + public string Product { get; set; } + [DisplayName("Removable media")] + public bool RemovableMedia { get; set; } + public byte[] Descriptors { get; set; } + } + + public class FireWire + { + public FireWire() {} + + public FireWire(firewireType firewire) + { + VendorID = firewire.VendorID; + ProductID = firewire.ProductID; + Manufacturer = firewire.Manufacturer; + Product = firewire.Product; + RemovableMedia = firewire.RemovableMedia; + } + + [JsonIgnore] + public int Id { get; set; } + [DisplayName("Vendor ID"), DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "0x{0:X8}")] + public uint VendorID { get; set; } + [DisplayName("Product ID"), DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "0x{0:X8}")] + public uint ProductID { get; set; } + [DisplayFormat(NullDisplayText = "Unknown")] + public string Manufacturer { get; set; } + [DisplayFormat(NullDisplayText = "Unknown")] + public string Product { get; set; } + [DisplayName("Is media removable?")] + public bool RemovableMedia { get; set; } + } + + public class Ata + { + public Ata() {} + + public Ata(ataType ata) + { + Identify = ata.Identify; + + if(ata.ReadCapabilities != null) + ReadCapabilities = new TestedMedia(ata.ReadCapabilities, true); + + if(ata.RemovableMedias != null) + { + RemovableMedias = new List(); + + foreach(testedMediaType ataRemovableMedia in ata.RemovableMedias) + RemovableMedias.Add(new TestedMedia(ataRemovableMedia, true)); + } + + if(Identify != null) + return; + + var identifyDevice = new Identify.IdentifyDevice(); + + if(ata.AdditionalPIDSpecified) + identifyDevice.AdditionalPID = ata.AdditionalPID; + + if(ata.APIOSupportedSpecified) + identifyDevice.APIOSupported = ata.APIOSupported; + + if(ata.ATAPIByteCountSpecified) + identifyDevice.ATAPIByteCount = ata.ATAPIByteCount; + + if(ata.BufferTypeSpecified) + identifyDevice.BufferType = ata.BufferType; + + if(ata.BufferSizeSpecified) + identifyDevice.BufferSize = ata.BufferSize; + + if(ata.CapabilitiesSpecified) + identifyDevice.Capabilities = ata.Capabilities; + + if(ata.Capabilities2Specified) + identifyDevice.Capabilities2 = ata.Capabilities2; + + if(ata.Capabilities3Specified) + identifyDevice.Capabilities3 = ata.Capabilities3; + + if(ata.CFAPowerModeSpecified) + identifyDevice.CFAPowerMode = ata.CFAPowerMode; + + if(ata.CommandSetSpecified) + identifyDevice.CommandSet = ata.CommandSet; + + if(ata.CommandSet2Specified) + identifyDevice.CommandSet2 = ata.CommandSet2; + + if(ata.CommandSet3Specified) + identifyDevice.CommandSet3 = ata.CommandSet3; + + if(ata.CommandSet4Specified) + identifyDevice.CommandSet4 = ata.CommandSet4; + + if(ata.CommandSet5Specified) + identifyDevice.CommandSet4 = ata.CommandSet4; + + if(ata.CurrentAAMSpecified) + identifyDevice.CurrentAAM = ata.CurrentAAM; + + if(ata.CurrentAPMSpecified) + identifyDevice.CurrentAPM = ata.CurrentAPM; + + if(ata.DataSetMgmtSpecified) + identifyDevice.DataSetMgmt = ata.DataSetMgmt; + + if(ata.DataSetMgmtSizeSpecified) + identifyDevice.DataSetMgmtSize = ata.DataSetMgmtSize; + + if(ata.DeviceFormFactorSpecified) + identifyDevice.DeviceFormFactor = ata.DeviceFormFactor; + + if(ata.DMAActiveSpecified) + identifyDevice.DMAActive = ata.DMAActive; + + if(ata.DMASupportedSpecified) + identifyDevice.DMASupported = ata.DMASupported; + + if(ata.DMATransferTimingModeSpecified) + identifyDevice.DMATransferTimingMode = ata.DMATransferTimingMode; + + if(ata.EnhancedSecurityEraseTimeSpecified) + identifyDevice.EnhancedSecurityEraseTime = ata.EnhancedSecurityEraseTime; + + if(ata.EnabledCommandSetSpecified) + identifyDevice.EnabledCommandSet = ata.EnabledCommandSet; + + if(ata.EnabledCommandSet2Specified) + identifyDevice.EnabledCommandSet2 = ata.EnabledCommandSet2; + + if(ata.EnabledCommandSet3Specified) + identifyDevice.EnabledCommandSet3 = ata.EnabledCommandSet3; + + if(ata.EnabledCommandSet4Specified) + identifyDevice.EnabledCommandSet4 = ata.EnabledCommandSet4; + + if(ata.EnabledSATAFeaturesSpecified) + identifyDevice.EnabledSATAFeatures = ata.EnabledSATAFeatures; + + if(ata.ExtendedUserSectorsSpecified) + identifyDevice.ExtendedUserSectors = ata.ExtendedUserSectors; + + if(ata.FreeFallSensitivitySpecified) + identifyDevice.FreeFallSensitivity = ata.FreeFallSensitivity; + + if(ata.FirmwareRevisionSpecified) + identifyDevice.FirmwareRevision = ata.FirmwareRevision; + + if(ata.GeneralConfigurationSpecified) + identifyDevice.GeneralConfiguration = ata.GeneralConfiguration; + + if(ata.HardwareResetResultSpecified) + identifyDevice.HardwareResetResult = ata.HardwareResetResult; + + if(ata.InterseekDelaySpecified) + identifyDevice.InterseekDelay = ata.InterseekDelay; + + if(ata.MajorVersionSpecified) + identifyDevice.MajorVersion = ata.MajorVersion; + + if(ata.MasterPasswordRevisionCodeSpecified) + identifyDevice.MasterPasswordRevisionCode = ata.MasterPasswordRevisionCode; + + if(ata.MaxDownloadMicroMode3Specified) + identifyDevice.MaxDownloadMicroMode3 = ata.MaxDownloadMicroMode3; + + if(ata.MaxQueueDepthSpecified) + identifyDevice.MaxQueueDepth = ata.MaxQueueDepth; + + if(ata.MDMAActiveSpecified) + identifyDevice.MDMAActive = ata.MDMAActive; + + if(ata.MDMASupportedSpecified) + identifyDevice.MDMASupported = ata.MDMASupported; + + if(ata.MinDownloadMicroMode3Specified) + identifyDevice.MinDownloadMicroMode3 = ata.MinDownloadMicroMode3; + + if(ata.MinMDMACycleTimeSpecified) + identifyDevice.MinMDMACycleTime = ata.MinMDMACycleTime; + + if(ata.MinorVersionSpecified) + identifyDevice.MinorVersion = ata.MinorVersion; + + if(ata.MinPIOCycleTimeNoFlowSpecified) + identifyDevice.MinPIOCycleTimeNoFlow = ata.MinPIOCycleTimeNoFlow; + + if(ata.MinPIOCycleTimeFlowSpecified) + identifyDevice.MinPIOCycleTimeFlow = ata.MinPIOCycleTimeFlow; + + if(ata.ModelSpecified) + identifyDevice.Model = ata.Model; + + if(ata.MultipleMaxSectorsSpecified) + identifyDevice.MultipleMaxSectors = ata.MultipleMaxSectors; + + if(ata.MultipleSectorNumberSpecified) + identifyDevice.MultipleSectorNumber = ata.MultipleSectorNumber; + + if(ata.NVCacheCapsSpecified) + identifyDevice.NVCacheCaps = ata.NVCacheCaps; + + if(ata.NVCacheSizeSpecified) + identifyDevice.NVCacheSize = ata.NVCacheSize; + + if(ata.NVCacheWriteSpeedSpecified) + identifyDevice.NVCacheWriteSpeed = ata.NVCacheWriteSpeed; + + if(ata.NVEstimatedSpinUpSpecified) + identifyDevice.NVEstimatedSpinUp = ata.NVEstimatedSpinUp; + + if(ata.PacketBusReleaseSpecified) + identifyDevice.PacketBusRelease = ata.PacketBusRelease; + + if(ata.PIOTransferTimingModeSpecified) + identifyDevice.PIOTransferTimingMode = ata.PIOTransferTimingMode; + + if(ata.RecommendedAAMSpecified) + identifyDevice.RecommendedAAM = ata.RecommendedAAM; + + if(ata.RecommendedMDMACycleTimeSpecified) + identifyDevice.RecMDMACycleTime = ata.RecommendedMDMACycleTime; + + if(ata.RemovableStatusSetSpecified) + identifyDevice.RemovableStatusSet = ata.RemovableStatusSet; + + if(ata.SATACapabilitiesSpecified) + identifyDevice.SATACapabilities = ata.SATACapabilities; + + if(ata.SATACapabilities2Specified) + identifyDevice.SATACapabilities2 = ata.SATACapabilities2; + + if(ata.SATAFeaturesSpecified) + identifyDevice.SATAFeatures = ata.SATAFeatures; + + if(ata.SCTCommandTransportSpecified) + identifyDevice.SCTCommandTransport = ata.SCTCommandTransport; + + if(ata.SectorsPerCardSpecified) + identifyDevice.SectorsPerCard = ata.SectorsPerCard; + + if(ata.SecurityEraseTimeSpecified) + identifyDevice.SecurityEraseTime = ata.SecurityEraseTime; + + if(ata.SecurityStatusSpecified) + identifyDevice.SecurityStatus = ata.SecurityStatus; + + if(ata.ServiceBusyClearSpecified) + identifyDevice.ServiceBusyClear = ata.ServiceBusyClear; + + if(ata.SpecificConfigurationSpecified) + identifyDevice.SpecificConfiguration = ata.SpecificConfiguration; + + if(ata.StreamAccessLatencySpecified) + identifyDevice.StreamAccessLatency = ata.StreamAccessLatency; + + if(ata.StreamMinReqSizeSpecified) + identifyDevice.StreamMinReqSize = ata.StreamMinReqSize; + + if(ata.StreamPerformanceGranularitySpecified) + identifyDevice.StreamPerformanceGranularity = ata.StreamPerformanceGranularity; + + if(ata.StreamTransferTimeDMASpecified) + identifyDevice.StreamTransferTimeDMA = ata.StreamTransferTimeDMA; + + if(ata.StreamTransferTimePIOSpecified) + identifyDevice.StreamTransferTimePIO = ata.StreamTransferTimePIO; + + if(ata.TransportMajorVersionSpecified) + identifyDevice.TransportMajorVersion = ata.TransportMajorVersion; + + if(ata.TransportMinorVersionSpecified) + identifyDevice.TransportMinorVersion = ata.TransportMinorVersion; + + if(ata.TrustedComputingSpecified) + identifyDevice.TrustedComputing = ata.TrustedComputing; + + if(ata.UDMAActiveSpecified) + identifyDevice.UDMAActive = ata.UDMAActive; + + if(ata.UDMASupportedSpecified) + identifyDevice.UDMASupported = ata.UDMASupported; + + if(ata.WRVModeSpecified) + identifyDevice.WRVMode = ata.WRVMode; + + if(ata.WRVSectorCountMode3Specified) + identifyDevice.WRVSectorCountMode3 = ata.WRVSectorCountMode3; + + if(ata.WRVSectorCountMode2Specified) + identifyDevice.WRVSectorCountMode2 = ata.WRVSectorCountMode2; + + Identify = Structs.Devices.ATA.Identify.Encode(identifyDevice); + } + + public Identify.IdentifyDevice? IdentifyDevice => Structs.Devices.ATA.Identify.Decode(Identify); + + [JsonIgnore] + public int Id { get; set; } + public byte[] Identify { get; set; } + public virtual TestedMedia ReadCapabilities { get; set; } + public virtual List RemovableMedias { get; set; } + } + + public class Chs + { + public Chs() {} + + public Chs(chsType chs) + { + Cylinders = chs.Cylinders; + Heads = chs.Heads; + Sectors = chs.Sectors; + } + + [JsonIgnore] + public int Id { get; set; } + public ushort Cylinders { get; set; } + public ushort Heads { get; set; } + public ushort Sectors { get; set; } + } + + public class Scsi + { + public Scsi() {} + + public Scsi(scsiType scsi) + { + InquiryData = scsi.Inquiry.Data; + SupportsModeSense6 = scsi.SupportsModeSense6; + SupportsModeSense10 = scsi.SupportsModeSense10; + SupportsModeSubpages = scsi.SupportsModeSubpages; + + if(scsi.ReadCapabilitiesSpecified && + scsi.ReadCapabilities != null) + ReadCapabilities = new TestedMedia(scsi.ReadCapabilities, false); + + if(scsi.RemovableMedias != null) + { + RemovableMedias = new List(); + + foreach(testedMediaType scsiRemovableMedia in scsi.RemovableMedias) + RemovableMedias.Add(new TestedMedia(scsiRemovableMedia, false)); + } + + ModeSense6Data = scsi.ModeSense6Data; + ModeSense10Data = scsi.ModeSense10Data; + + if(scsi.EVPDPages != null) + { + EVPDPages = new List(); + + foreach(pageType evpdPage in scsi.EVPDPages) + EVPDPages.Add(new ScsiPage(evpdPage)); + } + + if(scsi.ModeSense != null) + ModeSense = new ScsiMode(scsi.ModeSense); + + if(scsi.MultiMediaDevice != null) + MultiMediaDevice = new Mmc(scsi.MultiMediaDevice); + + if(scsi.SequentialDevice != null) + SequentialDevice = new Ssc(scsi.SequentialDevice); + + if(InquiryData != null) + return; + + var inq = new Inquiry(); + + if(scsi.Inquiry.ANSIVersionSpecified) + inq.ANSIVersion = scsi.Inquiry.ANSIVersion; + + if(scsi.Inquiry.ECMAVersionSpecified) + inq.ECMAVersion = scsi.Inquiry.ECMAVersion; + + if(scsi.Inquiry.DeviceTypeModifierSpecified) + inq.DeviceTypeModifier = scsi.Inquiry.DeviceTypeModifier; + + if(scsi.Inquiry.ISOVersionSpecified) + inq.ISOVersion = scsi.Inquiry.ISOVersion; + + if(scsi.Inquiry.ProductIdentificationSpecified) + { + byte[] tmp = Encoding.ASCII.GetBytes(scsi.Inquiry.ProductIdentification); + inq.ProductIdentification = new byte[tmp.Length + 1]; + Array.Copy(tmp, 0, inq.ProductIdentification, 0, tmp.Length); + } + + if(scsi.Inquiry.ProductRevisionLevelSpecified) + { + byte[] tmp = Encoding.ASCII.GetBytes(scsi.Inquiry.ProductRevisionLevel); + inq.ProductRevisionLevel = new byte[tmp.Length + 1]; + Array.Copy(tmp, 0, inq.ProductRevisionLevel, 0, tmp.Length); + } + + if(scsi.Inquiry.ResponseDataFormatSpecified) + inq.ResponseDataFormat = scsi.Inquiry.ResponseDataFormat; + + if(scsi.Inquiry.VendorIdentificationSpecified) + { + byte[] tmp = Encoding.ASCII.GetBytes(scsi.Inquiry.VendorIdentification); + inq.VendorIdentification = new byte[tmp.Length + 1]; + Array.Copy(tmp, 0, inq.VendorIdentification, 0, tmp.Length); + } + + inq.ACC = scsi.Inquiry.AccessControlCoordinator; + inq.ACKREQQ = scsi.Inquiry.ACKRequests; + inq.AERC = scsi.Inquiry.AERCSupported; + inq.Addr16 = scsi.Inquiry.Address16; + inq.Addr32 = scsi.Inquiry.Address32; + inq.TPGS = (byte)scsi.Inquiry.AsymmetricalLUNAccess; + inq.BQue = scsi.Inquiry.BasicQueueing; + inq.EncServ = scsi.Inquiry.EnclosureServices; + inq.HiSup = scsi.Inquiry.HierarchicalLUN; + inq.IUS = scsi.Inquiry.IUS; + inq.Linked = scsi.Inquiry.LinkedCommands; + inq.MChngr = scsi.Inquiry.MediumChanger; + inq.MultiP = scsi.Inquiry.MultiPortDevice; + inq.NormACA = scsi.Inquiry.NormalACA; + inq.PeripheralDeviceType = (byte)scsi.Inquiry.PeripheralDeviceType; + inq.PeripheralQualifier = (byte)scsi.Inquiry.PeripheralQualifier; + inq.Protect = scsi.Inquiry.Protection; + inq.QAS = scsi.Inquiry.QAS; + inq.RelAddr = scsi.Inquiry.RelativeAddressing; + inq.RMB = scsi.Inquiry.Removable; + inq.CmdQue = scsi.Inquiry.TaggedCommandQueue; + inq.TrmTsk = scsi.Inquiry.TerminateTaskSupported; + inq.ThreePC = scsi.Inquiry.ThirdPartyCopy; + inq.TranDis = scsi.Inquiry.TranferDisable; + inq.SftRe = scsi.Inquiry.SoftReset; + inq.Clocking = (byte)scsi.Inquiry.SPIClocking; + inq.SCCS = scsi.Inquiry.StorageArrayController; + inq.Sync = scsi.Inquiry.SyncTransfer; + inq.VersionDescriptors = scsi.Inquiry.VersionDescriptors; + inq.WBus16 = scsi.Inquiry.WideBus16; + inq.WBus32 = scsi.Inquiry.WideBus32; + + InquiryData = Structs.Devices.SCSI.Inquiry.Encode(inq); + } + + public Inquiry? Inquiry => Structs.Devices.SCSI.Inquiry.Decode(InquiryData); + + [JsonIgnore] + public int Id { get; set; } + [DisplayName("Data from INQUIRY command")] + public byte[] InquiryData { get; set; } + public virtual List EVPDPages { get; set; } + [DisplayName("Supports MODE SENSE(6)")] + public bool SupportsModeSense6 { get; set; } + [DisplayName("Supports MODE SENSE(10)")] + public bool SupportsModeSense10 { get; set; } + [DisplayName("Supports MODE SENSE with subpages")] + public bool SupportsModeSubpages { get; set; } + public virtual ScsiMode ModeSense { get; set; } + public virtual Mmc MultiMediaDevice { get; set; } + public virtual TestedMedia ReadCapabilities { get; set; } + public virtual List RemovableMedias { get; set; } + public virtual Ssc SequentialDevice { get; set; } + [DisplayName("Data from MODE SENSE(6) command")] + public byte[] ModeSense6Data { get; set; } + [DisplayName("Data from MODE SENSE(10) command")] + public byte[] ModeSense10Data { get; set; } + [DisplayName("Data from MODE SENSE(6) command (current)")] + public byte[] ModeSense6CurrentData { get; set; } + [DisplayName("Data from MODE SENSE(10) command (current)")] + public byte[] ModeSense10CurrentData { get; set; } + [DisplayName("Data from MODE SENSE(6) command (changeable)")] + public byte[] ModeSense6ChangeableData { get; set; } + [DisplayName("Data from MODE SENSE(10) command (changeable)")] + public byte[] ModeSense10ChangeableData { get; set; } + + [JsonIgnore] + public int? SequentialDeviceId { get; set; } + } + + public class ScsiMode + { + public ScsiMode() {} + + public ScsiMode(modeType mode) + { + if(mode.MediumTypeSpecified) + MediumType = mode.MediumType; + + WriteProtected = mode.WriteProtected; + + if(mode.SpeedSpecified) + Speed = mode.Speed; + + if(mode.BufferedModeSpecified) + BufferedMode = mode.BufferedMode; + + BlankCheckEnabled = mode.BlankCheckEnabled; + DPOandFUA = mode.DPOandFUA; + + if(mode.ModePages != null) + { + ModePages = new List(); + + foreach(modePageType modePage in mode.ModePages) + ModePages.Add(new ScsiPage(modePage)); + } + + if(mode.BlockDescriptors == null) + return; + + BlockDescriptors = new List(); + + foreach(blockDescriptorType blockDescriptor in mode.BlockDescriptors) + BlockDescriptors.Add(new BlockDescriptor(blockDescriptor)); + } + + [JsonIgnore] + public int Id { get; set; } + [DisplayName("Medium type code")] + public byte? MediumType { get; set; } + [DisplayName("Write protected")] + public bool WriteProtected { get; set; } + public virtual List BlockDescriptors { get; set; } + public byte? Speed { get; set; } + [DisplayName("Buffered mode")] + public byte? BufferedMode { get; set; } + [DisplayName("Blank check enabled")] + public bool BlankCheckEnabled { get; set; } + [DisplayName("DPO and FUA")] + public bool DPOandFUA { get; set; } + public virtual List ModePages { get; set; } + } + + public class BlockDescriptor + { + public BlockDescriptor() {} + + public BlockDescriptor(blockDescriptorType descriptor) + { + Density = descriptor.Density; + + if(descriptor.BlocksSpecified) + Blocks = descriptor.Blocks; + + if(descriptor.BlockLengthSpecified) + BlockLength = descriptor.BlockLength; + } + + [JsonIgnore] + public int Id { get; set; } + public byte Density { get; set; } + public ulong? Blocks { get; set; } + [DisplayName("Block length (bytes)")] + public uint? BlockLength { get; set; } + } + + public class ScsiPage + { + public ScsiPage() {} + + public ScsiPage(pageType evpdPage) + { + page = evpdPage.page; + value = evpdPage.value; + } + + public ScsiPage(modePageType modePage) + { + page = modePage.page; + subpage = modePage.subpage; + value = modePage.value; + } + + [JsonIgnore] + public int Id { get; set; } + public byte page { get; set; } + public byte? subpage { get; set; } + public byte[] value { get; set; } + } + + public class Mmc + { + public Mmc() {} + + public Mmc(mmcType mmc) + { + if(mmc.ModeSense2A != null) + ModeSense2AData = ModePage_2A.Encode(new ModePage_2A + { + AccurateCDDA = mmc.ModeSense2A.AccurateCDDA, + BCK = mmc.ModeSense2A.BCK, + BufferSize = mmc.ModeSense2A.BufferSize, + BUF = mmc.ModeSense2A.BufferUnderRunProtection, + Eject = mmc.ModeSense2A.CanEject, + Lock = mmc.ModeSense2A.CanLockMedia, + CDDACommand = mmc.ModeSense2A.CDDACommand, + Composite = mmc.ModeSense2A.CompositeAudioVideo, + CMRSupported = (ushort)(mmc.ModeSense2A.CSSandCPPMSupported ? 1 : 0), + CurrentSpeed = mmc.ModeSense2A.CurrentSpeed, + CurrentWriteSpeed = mmc.ModeSense2A.CurrentWriteSpeed, + CurrentWriteSpeedSelected = mmc.ModeSense2A.CurrentWriteSpeedSelected, + SDP = mmc.ModeSense2A.DeterministicSlotChanger, + DigitalPort1 = mmc.ModeSense2A.DigitalPort1, + DigitalPort2 = mmc.ModeSense2A.DigitalPort2, + LeadInPW = mmc.ModeSense2A.LeadInPW, + LoadingMechanism = mmc.ModeSense2A.LoadingMechanismType, + LockState = mmc.ModeSense2A.LockStatus, + LSBF = mmc.ModeSense2A.LSBF, + MaximumSpeed = mmc.ModeSense2A.MaximumSpeed, + MaxWriteSpeed = mmc.ModeSense2A.MaximumWriteSpeed, + AudioPlay = mmc.ModeSense2A.PlaysAudio, + PreventJumper = mmc.ModeSense2A.PreventJumperStatus, + RCK = mmc.ModeSense2A.RCK, + ReadBarcode = mmc.ModeSense2A.ReadsBarcode, + SCC = mmc.ModeSense2A.ReadsBothSides, + ReadCDR = mmc.ModeSense2A.ReadsCDR, + ReadCDRW = mmc.ModeSense2A.ReadsCDRW, + DeinterlaveSubchannel = mmc.ModeSense2A.ReadsDeinterlavedSubchannel, + ReadDVDR = mmc.ModeSense2A.ReadsDVDR, + ReadDVDRAM = mmc.ModeSense2A.ReadsDVDRAM, + ReadDVDROM = mmc.ModeSense2A.ReadsDVDROM, + ISRC = mmc.ModeSense2A.ReadsISRC, + Mode2Form2 = mmc.ModeSense2A.ReadsMode2Form2, + Mode2Form1 = mmc.ModeSense2A.ReadsMode2Form1, + Method2 = mmc.ModeSense2A.ReadsPacketCDR, + Subchannel = mmc.ModeSense2A.ReadsSubchannel, + UPC = mmc.ModeSense2A.ReadsUPC, + C2Pointer = mmc.ModeSense2A.ReturnsC2Pointers, + RotationControlSelected = mmc.ModeSense2A.RotationControlSelected, + SeparateChannelMute = mmc.ModeSense2A.SeparateChannelMute, + SeparateChannelVolume = mmc.ModeSense2A.SeparateChannelVolume, + SSS = mmc.ModeSense2A.SSS, + MultiSession = mmc.ModeSense2A.SupportsMultiSession, + SupportedVolumeLevels = mmc.ModeSense2A.SupportedVolumeLevels, + TestWrite = mmc.ModeSense2A.TestWrite, + WriteCDR = mmc.ModeSense2A.WritesCDR, + WriteCDRW = mmc.ModeSense2A.WritesCDRW, + WriteDVDR = mmc.ModeSense2A.WritesDVDR, + WriteDVDRAM = mmc.ModeSense2A.WritesDVDRAM, + WriteSpeedPerformanceDescriptors = mmc.ModeSense2A.WriteSpeedPerformanceDescriptors + }); + + if(mmc.Features != null) + Features = new MmcFeatures(mmc.Features); + + if(mmc.TestedMedia == null) + return; + + TestedMedia = new List(); + + foreach(testedMediaType mediaType in mmc.TestedMedia) + TestedMedia.Add(new TestedMedia(mediaType, false)); + } + + [JsonIgnore] + public int Id { get; set; } + public virtual ModePage_2A ModeSense2A => ModePage_2A.Decode(ModeSense2AData); + public virtual MmcFeatures Features { get; set; } + public virtual List TestedMedia { get; set; } + public byte[] ModeSense2AData { get; set; } + [JsonIgnore] + public int? FeaturesId { get; set; } + } + + public class MmcFeatures + { + public MmcFeatures() {} + + public MmcFeatures(mmcFeaturesType features) + { + if(features.PhysicalInterfaceStandardSpecified && + !features.PhysicalInterfaceStandardNumberSpecified) + PhysicalInterfaceStandardNumber = (uint?)features.PhysicalInterfaceStandard; + + if(features.PhysicalInterfaceStandardNumberSpecified) + PhysicalInterfaceStandardNumber = features.PhysicalInterfaceStandardNumber; + + if(features.AACSVersionSpecified) + AACSVersion = features.AACSVersion; + + if(features.AGIDsSpecified) + AGIDs = features.AGIDs; + + if(features.BindingNonceBlocksSpecified) + BindingNonceBlocks = features.BindingNonceBlocks; + + if(features.CPRMVersionSpecified) + CPRMVersion = features.CPRMVersion; + + if(features.CSSVersionSpecified) + CSSVersion = features.CSSVersion; + + if(features.LoadingMechanismTypeSpecified) + LoadingMechanismType = features.LoadingMechanismType; + + if(features.LogicalBlockSizeSpecified) + LogicalBlockSize = features.LogicalBlockSize; + + if(features.BlocksPerReadableUnitSpecified) + BlocksPerReadableUnit = features.BlocksPerReadableUnit; + + if(features.FirmwareDateSpecified) + FirmwareDate = features.FirmwareDate; + + if(features.VolumeLevelsSpecified) + VolumeLevels = features.VolumeLevels; + + BufferUnderrunFreeInDVD = features.BufferUnderrunFreeInDVD; + BufferUnderrunFreeInSAO = features.BufferUnderrunFreeInSAO; + BufferUnderrunFreeInTAO = features.BufferUnderrunFreeInTAO; + CanAudioScan = features.CanAudioScan; + CanEject = features.CanEject; + CanEraseSector = features.CanEraseSector; + CanExpandBDRESpareArea = features.CanExpandBDRESpareArea; + CanFormat = features.CanFormat; + CanFormatBDREWithoutSpare = features.CanFormatBDREWithoutSpare; + CanFormatCert = features.CanFormatCert; + CanFormatFRF = features.CanFormatFRF; + CanFormatQCert = features.CanFormatQCert; + CanFormatRRM = features.CanFormatRRM; + CanGenerateBindingNonce = features.CanGenerateBindingNonce; + CanLoad = features.CanLoad; + CanMuteSeparateChannels = features.CanMuteSeparateChannels; + CanOverwriteSAOTrack = features.CanOverwriteSAOTrack; + CanOverwriteTAOTrack = features.CanOverwriteTAOTrack; + CanPlayCDAudio = features.CanPlayCDAudio; + CanPseudoOverwriteBDR = features.CanPseudoOverwriteBDR; + CanReadAllDualR = features.CanReadAllDualR; + CanReadAllDualRW = features.CanReadAllDualRW; + CanReadBD = features.CanReadBD; + CanReadBDR = features.CanReadBDR; + CanReadBDRE1 = features.CanReadBDRE1; + CanReadBDRE2 = features.CanReadBDRE2; + CanReadBDROM = features.CanReadBDROM; + CanReadBluBCA = features.CanReadBluBCA; + CanReadCD = features.CanReadCD; + CanReadCDMRW = features.CanReadCDMRW; + CanReadCPRM_MKB = features.CanReadCPRM_MKB; + CanReadDDCD = features.CanReadDDCD; + CanReadDVD = features.CanReadDVD; + CanReadDVDPlusMRW = features.CanReadDVDPlusMRW; + CanReadDVDPlusR = features.CanReadDVDPlusR; + CanReadDVDPlusRDL = features.CanReadDVDPlusRDL; + CanReadDVDPlusRW = features.CanReadDVDPlusRW; + CanReadDVDPlusRWDL = features.CanReadDVDPlusRWDL; + CanReadDriveAACSCertificate = features.CanReadDriveAACSCertificate; + CanReadHDDVD = features.CanReadHDDVD; + CanReadHDDVDR = features.CanReadHDDVDR; + CanReadHDDVDRAM = features.CanReadHDDVDRAM; + CanReadLeadInCDText = features.CanReadLeadInCDText; + CanReadOldBDR = features.CanReadOldBDR; + CanReadOldBDRE = features.CanReadOldBDRE; + CanReadOldBDROM = features.CanReadOldBDROM; + CanReadSpareAreaInformation = features.CanReadSpareAreaInformation; + CanReportDriveSerial = features.CanReportDriveSerial; + CanReportMediaSerial = features.CanReportMediaSerial; + CanTestWriteDDCDR = features.CanTestWriteDDCDR; + CanTestWriteDVD = features.CanTestWriteDVD; + CanTestWriteInSAO = features.CanTestWriteInSAO; + CanTestWriteInTAO = features.CanTestWriteInTAO; + CanUpgradeFirmware = features.CanUpgradeFirmware; + CanWriteBD = features.CanWriteBD; + CanWriteBDR = features.CanWriteBDR; + CanWriteBDRE1 = features.CanWriteBDRE1; + CanWriteBDRE2 = features.CanWriteBDRE2; + CanWriteBusEncryptedBlocks = features.CanWriteBusEncryptedBlocks; + CanWriteCDMRW = features.CanWriteCDMRW; + CanWriteCDRW = features.CanWriteCDRW; + CanWriteCDRWCAV = features.CanWriteCDRWCAV; + CanWriteCDSAO = features.CanWriteCDSAO; + CanWriteCDTAO = features.CanWriteCDTAO; + CanWriteCSSManagedDVD = features.CanWriteCSSManagedDVD; + CanWriteDDCDR = features.CanWriteDDCDR; + CanWriteDDCDRW = features.CanWriteDDCDRW; + CanWriteDVDPlusMRW = features.CanWriteDVDPlusMRW; + CanWriteDVDPlusR = features.CanWriteDVDPlusR; + CanWriteDVDPlusRDL = features.CanWriteDVDPlusRDL; + CanWriteDVDPlusRW = features.CanWriteDVDPlusRW; + CanWriteDVDPlusRWDL = features.CanWriteDVDPlusRWDL; + CanWriteDVDR = features.CanWriteDVDR; + CanWriteDVDRDL = features.CanWriteDVDRDL; + CanWriteDVDRW = features.CanWriteDVDRW; + CanWriteHDDVDR = features.CanWriteHDDVDR; + CanWriteHDDVDRAM = features.CanWriteHDDVDRAM; + CanWriteOldBDR = features.CanWriteOldBDR; + CanWriteOldBDRE = features.CanWriteOldBDRE; + CanWritePackedSubchannelInTAO = features.CanWritePackedSubchannelInTAO; + CanWriteRWSubchannelInSAO = features.CanWriteRWSubchannelInSAO; + CanWriteRWSubchannelInTAO = features.CanWriteRWSubchannelInTAO; + CanWriteRaw = features.CanWriteRaw; + CanWriteRawMultiSession = features.CanWriteRawMultiSession; + CanWriteRawSubchannelInTAO = features.CanWriteRawSubchannelInTAO; + ChangerIsSideChangeCapable = features.ChangerIsSideChangeCapable; + ChangerSlots = features.ChangerSlots; + ChangerSupportsDiscPresent = features.ChangerSupportsDiscPresent; + DBML = features.DBML; + DVDMultiRead = features.DVDMultiRead; + EmbeddedChanger = features.EmbeddedChanger; + ErrorRecoveryPage = features.ErrorRecoveryPage; + Locked = features.Locked; + MultiRead = features.MultiRead; + PreventJumper = features.PreventJumper; + SupportsAACS = features.SupportsAACS; + SupportsBusEncryption = features.SupportsBusEncryption; + SupportsC2 = features.SupportsC2; + SupportsCPRM = features.SupportsCPRM; + SupportsCSS = features.SupportsCSS; + SupportsDAP = features.SupportsDAP; + SupportsDeviceBusyEvent = features.SupportsDeviceBusyEvent; + SupportsHybridDiscs = features.SupportsHybridDiscs; + SupportsModePage1Ch = features.SupportsModePage1Ch; + SupportsOSSC = features.SupportsOSSC; + SupportsPWP = features.SupportsPWP; + SupportsSWPP = features.SupportsSWPP; + SupportsSecurDisc = features.SupportsSecurDisc; + SupportsSeparateVolume = features.SupportsSeparateVolume; + SupportsVCPS = features.SupportsVCPS; + SupportsWriteInhibitDCB = features.SupportsWriteInhibitDCB; + SupportsWriteProtectPAC = features.SupportsWriteProtectPAC; + } + + [JsonIgnore] + public int Id { get; set; } + [DisplayName("AACS version")] + public byte? AACSVersion { get; set; } + [DisplayName("AGIDs")] + public byte? AGIDs { get; set; } + [DisplayName("Binding nonce blocks")] + public byte? BindingNonceBlocks { get; set; } + [DisplayName("Blocks per redable unit")] + public ushort? BlocksPerReadableUnit { get; set; } + [DisplayName("Buffer under-run free in DVD writing")] + public bool BufferUnderrunFreeInDVD { get; set; } + [DisplayName("Buffer under-run free in SAO writing")] + public bool BufferUnderrunFreeInSAO { get; set; } + [DisplayName("Buffer under-run free in TAO writing")] + public bool BufferUnderrunFreeInTAO { get; set; } + [DisplayName("Can audio scan")] + public bool CanAudioScan { get; set; } + [DisplayName("Can eject")] + public bool CanEject { get; set; } + [DisplayName("Can erase sectors")] + public bool CanEraseSector { get; set; } + [DisplayName("Can expand BD-RE spare area")] + public bool CanExpandBDRESpareArea { get; set; } + [DisplayName("Can format media")] + public bool CanFormat { get; set; } + [DisplayName("Can format BD-RE without spare area")] + public bool CanFormatBDREWithoutSpare { get; set; } + [DisplayName("Can do a fully certified format")] + public bool CanFormatCert { get; set; } + [DisplayName("Can do a FRF format")] + public bool CanFormatFRF { get; set; } + [DisplayName("Can do a quick certified format")] + public bool CanFormatQCert { get; set; } + [DisplayName("Can do a RRM format")] + public bool CanFormatRRM { get; set; } + [DisplayName("Can generate binding nonce")] + public bool CanGenerateBindingNonce { get; set; } + [DisplayName("Can load")] + public bool CanLoad { get; set; } + [DisplayName("Can mute separate channels")] + public bool CanMuteSeparateChannels { get; set; } + [DisplayName("Can overwrite track in SAO")] + public bool CanOverwriteSAOTrack { get; set; } + [DisplayName("Can overwrite track in TAO")] + public bool CanOverwriteTAOTrack { get; set; } + [DisplayName("Can play CD-DA")] + public bool CanPlayCDAudio { get; set; } + [DisplayName("Can pseudo-overwrite BD-R")] + public bool CanPseudoOverwriteBDR { get; set; } + [DisplayName("Can read all dual-layer recordables")] + public bool CanReadAllDualR { get; set; } + [DisplayName("Can read all dual-layer rewritables")] + public bool CanReadAllDualRW { get; set; } + [DisplayName("Can read Blu-ray")] + public bool CanReadBD { get; set; } + [DisplayName("Can read BD-R")] + public bool CanReadBDR { get; set; } + [DisplayName("Can read BD-RE v1")] + public bool CanReadBDRE1 { get; set; } + [DisplayName("Can read BD-RE v2")] + public bool CanReadBDRE2 { get; set; } + [DisplayName("Can read BD-ROM")] + public bool CanReadBDROM { get; set; } + [DisplayName("Can read BCA from Blu-ray")] + public bool CanReadBluBCA { get; set; } + [DisplayName("Can read CD")] + public bool CanReadCD { get; set; } + [DisplayName("Can read CD-MRW")] + public bool CanReadCDMRW { get; set; } + [DisplayName("Can read CPRM's MKB")] + public bool CanReadCPRM_MKB { get; set; } + [DisplayName("Can read DDCD")] + public bool CanReadDDCD { get; set; } + [DisplayName("Can read DVD")] + public bool CanReadDVD { get; set; } + [DisplayName("Can read DVD+MRW")] + public bool CanReadDVDPlusMRW { get; set; } + [DisplayName("Can read DVD+R")] + public bool CanReadDVDPlusR { get; set; } + [DisplayName("Can read DVD+R DL")] + public bool CanReadDVDPlusRDL { get; set; } + [DisplayName("Can read DVD+RW")] + public bool CanReadDVDPlusRW { get; set; } + [DisplayName("Can read DVD+RW DL")] + public bool CanReadDVDPlusRWDL { get; set; } + [DisplayName("Can read drive's AACS certificate")] + public bool CanReadDriveAACSCertificate { get; set; } + [DisplayName("Can read HD DVD")] + public bool CanReadHDDVD { get; set; } + [DisplayName("Can read HD DVD-R")] + public bool CanReadHDDVDR { get; set; } + [DisplayName("Can read HD DVD-RAM")] + public bool CanReadHDDVDRAM { get; set; } + [DisplayName("Can read Lead-In's CD-TEXT")] + public bool CanReadLeadInCDText { get; set; } + [DisplayName("Can read old generation BD-R")] + public bool CanReadOldBDR { get; set; } + [DisplayName("Can read old generation BD-RE")] + public bool CanReadOldBDRE { get; set; } + [DisplayName("Can read old generation BD-ROM")] + public bool CanReadOldBDROM { get; set; } + [DisplayName("Can read spare area information")] + public bool CanReadSpareAreaInformation { get; set; } + [DisplayName("Can report drive serial number")] + public bool CanReportDriveSerial { get; set; } + [DisplayName("Can report media serial number")] + public bool CanReportMediaSerial { get; set; } + [DisplayName("Can test write DDCD-R")] + public bool CanTestWriteDDCDR { get; set; } + [DisplayName("Can test write DVD")] + public bool CanTestWriteDVD { get; set; } + [DisplayName("Can test write in SAO mode")] + public bool CanTestWriteInSAO { get; set; } + [DisplayName("Can test write in TAO mode")] + public bool CanTestWriteInTAO { get; set; } + [DisplayName("Can upgrade firmware")] + public bool CanUpgradeFirmware { get; set; } + [DisplayName("Can write Blu-ray")] + public bool CanWriteBD { get; set; } + [DisplayName("Can write BD-R")] + public bool CanWriteBDR { get; set; } + [DisplayName("Can write BD-RE v1")] + public bool CanWriteBDRE1 { get; set; } + [DisplayName("Can write BD-RE v2")] + public bool CanWriteBDRE2 { get; set; } + [DisplayName("Can write bus encrypted blocks")] + public bool CanWriteBusEncryptedBlocks { get; set; } + [DisplayName("Can write CD-MRW")] + public bool CanWriteCDMRW { get; set; } + [DisplayName("Can write CD-RW")] + public bool CanWriteCDRW { get; set; } + [DisplayName("Can write CD-RW CAV")] + public bool CanWriteCDRWCAV { get; set; } + [DisplayName("Can write CD in SAO mode")] + public bool CanWriteCDSAO { get; set; } + [DisplayName("Can write CD in TAO mode")] + public bool CanWriteCDTAO { get; set; } + [DisplayName("Can write CSS managed DVD")] + public bool CanWriteCSSManagedDVD { get; set; } + [DisplayName("Can write DDCD-R")] + public bool CanWriteDDCDR { get; set; } + [DisplayName("Can write DDCD-RW")] + public bool CanWriteDDCDRW { get; set; } + [DisplayName("Can write DVD+MRW")] + public bool CanWriteDVDPlusMRW { get; set; } + [DisplayName("Can write DVD+R")] + public bool CanWriteDVDPlusR { get; set; } + [DisplayName("Can write DVD+R DL")] + public bool CanWriteDVDPlusRDL { get; set; } + [DisplayName("Can write DVD+RW")] + public bool CanWriteDVDPlusRW { get; set; } + [DisplayName("Can write DVD+RW DL")] + public bool CanWriteDVDPlusRWDL { get; set; } + [DisplayName("Can write DVD-R")] + public bool CanWriteDVDR { get; set; } + [DisplayName("Can write DVD-R DL")] + public bool CanWriteDVDRDL { get; set; } + [DisplayName("Can write DVD-RW")] + public bool CanWriteDVDRW { get; set; } + [DisplayName("Can write HD DVD-R")] + public bool CanWriteHDDVDR { get; set; } + [DisplayName("Can write HD DVD-RAM")] + public bool CanWriteHDDVDRAM { get; set; } + [DisplayName("Can write old generation BD-R")] + public bool CanWriteOldBDR { get; set; } + [DisplayName("Can write old generation BD-RE")] + public bool CanWriteOldBDRE { get; set; } + [DisplayName("Can write packet subchannel in TAO")] + public bool CanWritePackedSubchannelInTAO { get; set; } + [DisplayName("Can write RW subchannel in SAO")] + public bool CanWriteRWSubchannelInSAO { get; set; } + [DisplayName("Can write RW subchannel in TAO")] + public bool CanWriteRWSubchannelInTAO { get; set; } + [DisplayName("Can write RAW-96 sectors")] + public bool CanWriteRaw { get; set; } + [DisplayName("Can write RAW-96 sectors in multisession")] + public bool CanWriteRawMultiSession { get; set; } + [DisplayName("Can write RAW-96 sectors in TAO")] + public bool CanWriteRawSubchannelInTAO { get; set; } + [DisplayName("Changer is side change capable")] + public bool ChangerIsSideChangeCapable { get; set; } + [DisplayName("Changer slots")] + public byte ChangerSlots { get; set; } + [DisplayName("Changer supports disc present")] + public bool ChangerSupportsDiscPresent { get; set; } + [DisplayName("CPRM version")] + public byte? CPRMVersion { get; set; } + [DisplayName("CSS version")] + public byte? CSSVersion { get; set; } + [DisplayName("DBML")] + public bool DBML { get; set; } + [DisplayName("DVD Multi-Read Specification")] + public bool DVDMultiRead { get; set; } + [DisplayName("Has an embedded changer")] + public bool EmbeddedChanger { get; set; } + [DisplayName("Has error recovery page")] + public bool ErrorRecoveryPage { get; set; } + [DisplayName("Firmware date")] + public DateTime? FirmwareDate { get; set; } + [DisplayName("Loading mechanism type")] + public byte? LoadingMechanismType { get; set; } + [DisplayName("Locked")] + public bool Locked { get; set; } + [DisplayName("Logical block size")] + public uint? LogicalBlockSize { get; set; } + [DisplayName("Multi-Read Specification")] + public bool MultiRead { get; set; } + [DisplayName("Physical interface standard")] + public PhysicalInterfaces? PhysicalInterfaceStandard => (PhysicalInterfaces?)PhysicalInterfaceStandardNumber; + [DisplayName("Physical interface standard number")] + public uint? PhysicalInterfaceStandardNumber { get; set; } + [DisplayName("Prevent eject jumper")] + public bool PreventJumper { get; set; } + [DisplayName("Supports AACS")] + public bool SupportsAACS { get; set; } + [DisplayName("Supports bus encryption")] + public bool SupportsBusEncryption { get; set; } + [DisplayName("Supports C2 pointers")] + public bool SupportsC2 { get; set; } + [DisplayName("Supports CPRM")] + public bool SupportsCPRM { get; set; } + [DisplayName("Supports CSS")] + public bool SupportsCSS { get; set; } + [DisplayName("Supports DAP")] + public bool SupportsDAP { get; set; } + [DisplayName("Supports device busy event")] + public bool SupportsDeviceBusyEvent { get; set; } + [DisplayName("Supports hybrid discs")] + public bool SupportsHybridDiscs { get; set; } + [DisplayName("Supports MODE PAGE 1Ch")] + public bool SupportsModePage1Ch { get; set; } + [DisplayName("Supports OSSC")] + public bool SupportsOSSC { get; set; } + [DisplayName("Supports PWP")] + public bool SupportsPWP { get; set; } + [DisplayName("Supports SWPP")] + public bool SupportsSWPP { get; set; } + [DisplayName("Supports SecurDisc")] + public bool SupportsSecurDisc { get; set; } + [DisplayName("Support separate volume levels")] + public bool SupportsSeparateVolume { get; set; } + [DisplayName("Supports VCPS")] + public bool SupportsVCPS { get; set; } + [DisplayName("Supports write inhibit DCB")] + public bool SupportsWriteInhibitDCB { get; set; } + [DisplayName("Supports write protect PAC")] + public bool SupportsWriteProtectPAC { get; set; } + [DisplayName("Volume levels")] + public ushort? VolumeLevels { get; set; } + [DisplayName("MMC FEATURES binary data")] + public byte[] BinaryData { get; set; } + } + + public class TestedMedia + { + public Identify.IdentifyDevice? IdentifyDevice; + + public TestedMedia() {} + + public TestedMedia(testedMediaType mediaType, bool ata) + { + if(mediaType.BlocksSpecified) + Blocks = mediaType.Blocks; + + if(mediaType.BlockSizeSpecified) + BlockSize = mediaType.BlockSize; + + if(mediaType.CanReadAACSSpecified) + CanReadAACS = mediaType.CanReadAACS; + + if(mediaType.CanReadADIPSpecified) + CanReadADIP = mediaType.CanReadADIP; + + if(mediaType.CanReadATIPSpecified) + CanReadATIP = mediaType.CanReadATIP; + + if(mediaType.CanReadBCASpecified) + CanReadBCA = mediaType.CanReadBCA; + + if(mediaType.CanReadC2PointersSpecified) + CanReadC2Pointers = mediaType.CanReadC2Pointers; + + if(mediaType.CanReadCMISpecified) + CanReadCMI = mediaType.CanReadCMI; + + if(mediaType.CanReadCorrectedSubchannelSpecified) + CanReadCorrectedSubchannel = mediaType.CanReadCorrectedSubchannel; + + if(mediaType.CanReadCorrectedSubchannelWithC2Specified) + CanReadCorrectedSubchannelWithC2 = mediaType.CanReadCorrectedSubchannelWithC2; + + if(mediaType.CanReadDCBSpecified) + CanReadDCB = mediaType.CanReadDCB; + + if(mediaType.CanReadDDSSpecified) + CanReadDDS = mediaType.CanReadDDS; + + if(mediaType.CanReadDMISpecified) + CanReadDMI = mediaType.CanReadDMI; + + if(mediaType.CanReadDiscInformationSpecified) + CanReadDiscInformation = mediaType.CanReadDiscInformation; + + if(mediaType.CanReadFullTOCSpecified) + CanReadFullTOC = mediaType.CanReadFullTOC; + + if(mediaType.CanReadHDCMISpecified) + CanReadHDCMI = mediaType.CanReadHDCMI; + + if(mediaType.CanReadLayerCapacitySpecified) + CanReadLayerCapacity = mediaType.CanReadLayerCapacity; + + if(mediaType.CanReadLeadInSpecified) + CanReadFirstTrackPreGap = mediaType.CanReadLeadIn; + + if(mediaType.CanReadLeadOutSpecified) + CanReadLeadOut = mediaType.CanReadLeadOut; + + if(mediaType.CanReadMediaIDSpecified) + CanReadMediaID = mediaType.CanReadMediaID; + + if(mediaType.CanReadMediaSerialSpecified) + CanReadMediaSerial = mediaType.CanReadMediaSerial; + + if(mediaType.CanReadPACSpecified) + CanReadPAC = mediaType.CanReadPAC; + + if(mediaType.CanReadPFISpecified) + CanReadPFI = mediaType.CanReadPFI; + + if(mediaType.CanReadPMASpecified) + CanReadPMA = mediaType.CanReadPMA; + + if(mediaType.CanReadPQSubchannelSpecified) + CanReadPQSubchannel = mediaType.CanReadPQSubchannel; + + if(mediaType.CanReadPQSubchannelWithC2Specified) + CanReadPQSubchannelWithC2 = mediaType.CanReadPQSubchannelWithC2; + + if(mediaType.CanReadPRISpecified) + CanReadPRI = mediaType.CanReadPRI; + + if(mediaType.CanReadRWSubchannelSpecified) + CanReadRWSubchannel = mediaType.CanReadRWSubchannel; + + if(mediaType.CanReadRWSubchannelWithC2Specified) + CanReadRWSubchannelWithC2 = mediaType.CanReadRWSubchannelWithC2; + + if(mediaType.CanReadRecordablePFISpecified) + CanReadRecordablePFI = mediaType.CanReadRecordablePFI; + + if(mediaType.CanReadSpareAreaInformationSpecified) + CanReadSpareAreaInformation = mediaType.CanReadSpareAreaInformation; + + if(mediaType.CanReadTOCSpecified) + CanReadTOC = mediaType.CanReadTOC; + + if(mediaType.DensitySpecified) + Density = mediaType.Density; + + if(mediaType.LongBlockSizeSpecified) + LongBlockSize = mediaType.LongBlockSize; + + if(mediaType.ManufacturerSpecified) + Manufacturer = mediaType.Manufacturer; + + if(mediaType.MediumTypeSpecified) + MediumType = mediaType.MediumType; + + if(mediaType.ModelSpecified) + Model = mediaType.Model; + + if(mediaType.SupportsHLDTSTReadRawDVDSpecified) + SupportsHLDTSTReadRawDVD = mediaType.SupportsHLDTSTReadRawDVD; + + if(mediaType.SupportsNECReadCDDASpecified) + SupportsNECReadCDDA = mediaType.SupportsNECReadCDDA; + + if(mediaType.SupportsPioneerReadCDDASpecified) + SupportsPioneerReadCDDA = mediaType.SupportsPioneerReadCDDA; + + if(mediaType.SupportsPioneerReadCDDAMSFSpecified) + SupportsPioneerReadCDDAMSF = mediaType.SupportsPioneerReadCDDAMSF; + + if(mediaType.SupportsPlextorReadCDDASpecified) + SupportsPlextorReadCDDA = mediaType.SupportsPlextorReadCDDA; + + if(mediaType.SupportsPlextorReadRawDVDSpecified) + SupportsPlextorReadRawDVD = mediaType.SupportsPlextorReadRawDVD; + + if(mediaType.SupportsRead10Specified) + SupportsRead10 = mediaType.SupportsRead10; + + if(mediaType.SupportsRead12Specified) + SupportsRead12 = mediaType.SupportsRead12; + + if(mediaType.SupportsRead16Specified) + SupportsRead16 = mediaType.SupportsRead16; + + if(mediaType.SupportsReadSpecified) + { + if(ata) + SupportsReadSectors = mediaType.SupportsRead; + else + SupportsRead6 = mediaType.SupportsRead; + } + + if(mediaType.SupportsReadCapacity16Specified) + SupportsReadCapacity16 = mediaType.SupportsReadCapacity16; + + if(mediaType.SupportsReadCapacitySpecified) + SupportsReadCapacity = mediaType.SupportsReadCapacity; + + if(mediaType.SupportsReadCdSpecified) + SupportsReadCd = mediaType.SupportsReadCd; + + if(mediaType.SupportsReadCdMsfSpecified) + SupportsReadCdMsf = mediaType.SupportsReadCdMsf; + + if(mediaType.SupportsReadCdRawSpecified) + SupportsReadCdRaw = mediaType.SupportsReadCdRaw; + + if(mediaType.SupportsReadCdMsfRawSpecified) + SupportsReadCdMsfRaw = mediaType.SupportsReadCdMsfRaw; + + if(mediaType.SupportsReadLong16Specified) + SupportsReadLong16 = mediaType.SupportsReadLong16; + + if(mediaType.SupportsReadLongSpecified) + SupportsReadLong = mediaType.SupportsReadLong; + + if(mediaType.LBASectorsSpecified) + LBASectors = mediaType.LBASectors; + + if(mediaType.LBA48SectorsSpecified) + LBA48Sectors = mediaType.LBA48Sectors; + + if(mediaType.LogicalAlignmentSpecified) + LogicalAlignment = mediaType.LogicalAlignment; + + if(mediaType.NominalRotationRateSpecified) + NominalRotationRate = mediaType.NominalRotationRate; + + if(mediaType.PhysicalBlockSizeSpecified) + PhysicalBlockSize = mediaType.PhysicalBlockSize; + + if(mediaType.SolidStateDeviceSpecified) + SolidStateDevice = mediaType.SolidStateDevice; + + if(mediaType.UnformattedBPTSpecified) + UnformattedBPT = mediaType.UnformattedBPT; + + if(mediaType.UnformattedBPSSpecified) + UnformattedBPS = mediaType.UnformattedBPS; + + if(mediaType.SupportsReadDmaLbaSpecified) + SupportsReadDmaLba = mediaType.SupportsReadDmaLba; + + if(mediaType.SupportsReadDmaRetryLbaSpecified) + SupportsReadDmaRetryLba = mediaType.SupportsReadDmaRetryLba; + + if(mediaType.SupportsReadLbaSpecified) + SupportsReadLba = mediaType.SupportsReadLba; + + if(mediaType.SupportsReadRetryLbaSpecified) + SupportsReadRetryLba = mediaType.SupportsReadRetryLba; + + if(mediaType.SupportsReadLongLbaSpecified) + SupportsReadLongLba = mediaType.SupportsReadLongLba; + + if(mediaType.SupportsReadLongRetryLbaSpecified) + SupportsReadLongRetryLba = mediaType.SupportsReadLongRetryLba; + + if(mediaType.SupportsSeekLbaSpecified) + SupportsSeekLba = mediaType.SupportsSeekLba; + + if(mediaType.SupportsReadDmaLba48Specified) + SupportsReadDmaLba48 = mediaType.SupportsReadDmaLba48; + + if(mediaType.SupportsReadLba48Specified) + SupportsReadLba48 = mediaType.SupportsReadLba48; + + if(mediaType.SupportsReadDmaSpecified) + SupportsReadDma = mediaType.SupportsReadDma; + + if(mediaType.SupportsReadDmaRetrySpecified) + SupportsReadDmaRetry = mediaType.SupportsReadDmaRetry; + + if(mediaType.SupportsReadRetrySpecified) + SupportsReadRetry = mediaType.SupportsReadRetry; + + if(mediaType.SupportsReadLongRetrySpecified) + SupportsReadLongRetry = mediaType.SupportsReadLongRetry; + + if(mediaType.SupportsSeekSpecified) + SupportsSeek = mediaType.SupportsSeek; + + if(mediaType.CHS != null) + CHS = new Chs(mediaType.CHS); + + if(mediaType.CurrentCHS != null) + CurrentCHS = new Chs(mediaType.CurrentCHS); + + MediaIsRecognized = mediaType.MediaIsRecognized; + MediumTypeName = mediaType.MediumTypeName; + ModeSense6Data = mediaType.ModeSense6Data; + ModeSense10Data = mediaType.ModeSense10Data; + } + + [JsonIgnore] + public int Id { get; set; } + [DisplayName("IDENTIFY DEVICE data")] + public byte[] IdentifyData { get; set; } + [DisplayName("Blocks")] + public ulong? Blocks { get; set; } + [DisplayName("Bytes per block")] + public uint? BlockSize { get; set; } + [DisplayName("Can read AACS")] + public bool? CanReadAACS { get; set; } + [DisplayName("Can read ADIP")] + public bool? CanReadADIP { get; set; } + [DisplayName("Can read ATIP")] + public bool? CanReadATIP { get; set; } + [DisplayName("Can read BCA")] + public bool? CanReadBCA { get; set; } + [DisplayName("Can read C2 pointers")] + public bool? CanReadC2Pointers { get; set; } + [DisplayName("Can read Copyright Management Information")] + public bool? CanReadCMI { get; set; } + [DisplayName("Can read corrected subchannel")] + public bool? CanReadCorrectedSubchannel { get; set; } + [DisplayName("Can read corrected subchannel with C2 pointers")] + public bool? CanReadCorrectedSubchannelWithC2 { get; set; } + [DisplayName("Can read DCBs")] + public bool? CanReadDCB { get; set; } + [DisplayName("Can read DDS")] + public bool? CanReadDDS { get; set; } + [DisplayName("Can read DMI")] + public bool? CanReadDMI { get; set; } + [DisplayName("Can read disc information")] + public bool? CanReadDiscInformation { get; set; } + [DisplayName("Can read full TOC")] + public bool? CanReadFullTOC { get; set; } + [DisplayName("Can read HD-DVD Copyright Management Information")] + public bool? CanReadHDCMI { get; set; } + [DisplayName("Can read layer capacity")] + public bool? CanReadLayerCapacity { get; set; } + [DisplayName("Can read into first track pregap")] + public bool? CanReadFirstTrackPreGap { get; set; } + [DisplayName("Can read into Lead-In")] + public bool? CanReadLeadIn { get; set; } + [DisplayName("Can read into Lead-Out")] + public bool? CanReadLeadOut { get; set; } + [DisplayName("Can read media ID")] + public bool? CanReadMediaID { get; set; } + [DisplayName("Can read media serial number")] + public bool? CanReadMediaSerial { get; set; } + [DisplayName("Can read PAC")] + public bool? CanReadPAC { get; set; } + [DisplayName("Can read PFI")] + public bool? CanReadPFI { get; set; } + [DisplayName("Can read PMA")] + public bool? CanReadPMA { get; set; } + [DisplayName("Can read PQ subchannel")] + public bool? CanReadPQSubchannel { get; set; } + [DisplayName("Can read PQ subchannel with C2 pointers")] + public bool? CanReadPQSubchannelWithC2 { get; set; } + [DisplayName("Can read pre-recorded information")] + public bool? CanReadPRI { get; set; } + [DisplayName("Can read RW subchannel")] + public bool? CanReadRWSubchannel { get; set; } + [DisplayName("Can read RW subchannel with C2 pointers")] + public bool? CanReadRWSubchannelWithC2 { get; set; } + [DisplayName("Can read recordable PFI")] + public bool? CanReadRecordablePFI { get; set; } + [DisplayName("Can read spare area information")] + public bool? CanReadSpareAreaInformation { get; set; } + [DisplayName("Can read TOC")] + public bool? CanReadTOC { get; set; } + [DisplayName("Density code")] + public byte? Density { get; set; } + [DisplayName("Bytes per block in READ LONG commands")] + public uint? LongBlockSize { get; set; } + [DisplayName("Media manufacturer")] + public string Manufacturer { get; set; } + [DisplayName("Media recognized by drive?")] + public bool MediaIsRecognized { get; set; } + [DisplayName("Medium type code")] + public byte? MediumType { get; set; } + [DisplayName("Media type")] + public string MediumTypeName { get; set; } + [DisplayName("Media model")] + public string Model { get; set; } + [DisplayName("Can read scrambled DVD sectors using HL-DT-ST cache trick")] + public bool? SupportsHLDTSTReadRawDVD { get; set; } + [DisplayName("Supports NEC READ CD-DA command")] + public bool? SupportsNECReadCDDA { get; set; } + [DisplayName("Supports Pioneer READ CD-DA command")] + public bool? SupportsPioneerReadCDDA { get; set; } + [DisplayName("Supports Pioneer READ CD-DA MSF command")] + public bool? SupportsPioneerReadCDDAMSF { get; set; } + [DisplayName("Supports Plextor READ CD-DA command")] + public bool? SupportsPlextorReadCDDA { get; set; } + [DisplayName("Can read scrambled DVD sectors using Plextor vendor command")] + public bool? SupportsPlextorReadRawDVD { get; set; } + [DisplayName("Supports READ(10) command")] + public bool? SupportsRead10 { get; set; } + [DisplayName("Supports READ(12) command")] + public bool? SupportsRead12 { get; set; } + [DisplayName("Supports READ(16) command")] + public bool? SupportsRead16 { get; set; } + [DisplayName("Supports READ(6) command")] + public bool? SupportsRead6 { get; set; } + [DisplayName("Supports READ CAPACITY(16) command")] + public bool? SupportsReadCapacity16 { get; set; } + [DisplayName("Supports READ CAPACITY command")] + public bool? SupportsReadCapacity { get; set; } + [DisplayName("Supports READ CD command")] + public bool? SupportsReadCd { get; set; } + [DisplayName("Supports READ CD MSF command")] + public bool? SupportsReadCdMsf { get; set; } + [DisplayName("Supports full sector in READ CD command")] + public bool? SupportsReadCdRaw { get; set; } + [DisplayName("Supports full sector in READ CD MSF command")] + public bool? SupportsReadCdMsfRaw { get; set; } + [DisplayName("Supports READ LONG(16) command")] + public bool? SupportsReadLong16 { get; set; } + [DisplayName("Supports READ LONG command")] + public bool? SupportsReadLong { get; set; } + + [DisplayName("Data from MODE SENSE(6) command")] + public byte[] ModeSense6Data { get; set; } + [DisplayName("Data from MODE SENSE(10) command")] + public byte[] ModeSense10Data { get; set; } + + public virtual Chs CHS { get; set; } + public virtual Chs CurrentCHS { get; set; } + [DisplayName("Sectors in 28-bit LBA mode")] + public uint? LBASectors { get; set; } + [DisplayName("Sectors in 48-bit LBA mode")] + public ulong? LBA48Sectors { get; set; } + [DisplayName("Logical alignment")] + public ushort? LogicalAlignment { get; set; } + [DisplayName("Nominal rotation rate")] + public ushort? NominalRotationRate { get; set; } + [DisplayName("Bytes per block, physical")] + public uint? PhysicalBlockSize { get; set; } + [DisplayName("Is it a SSD?")] + public bool? SolidStateDevice { get; set; } + [DisplayName("Bytes per unformatted track")] + public ushort? UnformattedBPT { get; set; } + [DisplayName("Bytes per unformatted sector")] + public ushort? UnformattedBPS { get; set; } + + [DisplayName("Supports READ DMA (LBA) command")] + public bool? SupportsReadDmaLba { get; set; } + [DisplayName("Supports READ DMA RETRY (LBA) command")] + public bool? SupportsReadDmaRetryLba { get; set; } + [DisplayName("Supports READ SECTORS (LBA) command")] + public bool? SupportsReadLba { get; set; } + [DisplayName("Supports READ SECTORS RETRY (LBA) command")] + public bool? SupportsReadRetryLba { get; set; } + [DisplayName("Supports READ SECTORS LONG (LBA) command")] + public bool? SupportsReadLongLba { get; set; } + [DisplayName("Supports READ SECTORS LONG RETRY (LBA) command")] + public bool? SupportsReadLongRetryLba { get; set; } + [DisplayName("Supports SEEK (LBA) command")] + public bool? SupportsSeekLba { get; set; } + + [DisplayName("Supports READ DMA EXT command")] + public bool? SupportsReadDmaLba48 { get; set; } + [DisplayName("Supports READ SECTORS EXT command")] + public bool? SupportsReadLba48 { get; set; } + + [DisplayName("Supports READ DMA command")] + public bool? SupportsReadDma { get; set; } + [DisplayName("Supports READ DMA RETRY command")] + public bool? SupportsReadDmaRetry { get; set; } + [DisplayName("Supports READ SECTORS RETRY command")] + public bool? SupportsReadRetry { get; set; } + [DisplayName("Supports READ SECTORS command")] + public bool? SupportsReadSectors { get; set; } + [DisplayName("Supports READ SECTORS LONG RETRY command")] + public bool? SupportsReadLongRetry { get; set; } + [DisplayName("Supports SEEK command")] + public bool? SupportsSeek { get; set; } + + [DisplayName("Can read into inter-session Lead-In")] + public bool? CanReadingIntersessionLeadIn { get; set; } + [DisplayName("Can read into inter-session Lead-Out")] + public bool? CanReadingIntersessionLeadOut { get; set; } + [DisplayName("Data from inter-session Lead-In")] + public byte[] IntersessionLeadInData { get; set; } + [DisplayName("Data from inter-session Lead-Out")] + public byte[] IntersessionLeadOutData { get; set; } + + [DisplayName("Can read scrambled data using READ CD command")] + public bool? CanReadCdScrambled { get; set; } + [DisplayName("Data from scrambled READ CD command")] + public byte[] ReadCdScrambledData { get; set; } + + [DisplayName("Can read from cache using F1h command subcommand 06h")] + public bool? CanReadF1_06 { get; set; } + [DisplayName("Can read from cache using F1h command subcommand 06h")] + public byte[] ReadF1_06Data { get; set; } + [DisplayName("Can read from cache using F1h command subcommand 06h targeting Lead-Out")] + public bool? CanReadF1_06LeadOut { get; set; } + [DisplayName("Can read from cache using F1h command subcommand 06h targeting Lead-Out")] + public byte[] ReadF1_06LeadOutData { get; set; } + + [JsonIgnore] + public int? AtaId { get; set; } + [JsonIgnore] + public int? ScsiId { get; set; } + [JsonIgnore] + public int? MmcId { get; set; } + + #region SCSI data + [DisplayName("Data from READ(6) command")] + public byte[] Read6Data { get; set; } + [DisplayName("Data from READ(10) command")] + public byte[] Read10Data { get; set; } + [DisplayName("Data from READ(12) command")] + public byte[] Read12Data { get; set; } + [DisplayName("Data from READ(16) command")] + public byte[] Read16Data { get; set; } + [DisplayName("Data from READ LONG(10) command")] + public byte[] ReadLong10Data { get; set; } + [DisplayName("Data from READ LONG(16) command")] + public byte[] ReadLong16Data { get; set; } + #endregion + + #region ATA data + [DisplayName("Data from READ SECTORS command")] + public byte[] ReadSectorsData { get; set; } + [DisplayName("Data from READ SECTORS RETRY command")] + public byte[] ReadSectorsRetryData { get; set; } + [DisplayName("Data from READ DMA command")] + public byte[] ReadDmaData { get; set; } + [DisplayName("Data from READ DMA RETRY command")] + public byte[] ReadDmaRetryData { get; set; } + [DisplayName("Data from READ SECTORS (LBA) command")] + public byte[] ReadLbaData { get; set; } + [DisplayName("Data from READ SECTORS RETRY (LBA) command")] + public byte[] ReadRetryLbaData { get; set; } + [DisplayName("Data from READ DMA (LBA) command")] + public byte[] ReadDmaLbaData { get; set; } + [DisplayName("Data from READ DMA RETRY (LBA) command")] + public byte[] ReadDmaRetryLbaData { get; set; } + [DisplayName("Data from READ SECTORS EXT command")] + public byte[] ReadLba48Data { get; set; } + [DisplayName("Data from READ DMA EXT command")] + public byte[] ReadDmaLba48Data { get; set; } + [DisplayName("Data from READ SECTORS LONG command")] + public byte[] ReadLongData { get; set; } + [DisplayName("Data from READ SECTORS LONG RETRY command")] + public byte[] ReadLongRetryData { get; set; } + [DisplayName("Data from READ SECTORS LONG (LBA) command")] + public byte[] ReadLongLbaData { get; set; } + [DisplayName("Data from READ SECTORS LONG RETRY (LBA) command")] + public byte[] ReadLongRetryLbaData { get; set; } + #endregion + + #region CompactDisc data + [DisplayName("Data from READ TOC command")] + public byte[] TocData { get; set; } + [DisplayName("Data from READ FULL TOC command")] + public byte[] FullTocData { get; set; } + [DisplayName("Data from READ ATIP command")] + public byte[] AtipData { get; set; } + [DisplayName("Data from READ PMA command")] + public byte[] PmaData { get; set; } + [DisplayName("Data from READ CD command")] + public byte[] ReadCdData { get; set; } + [DisplayName("Data from READ CD MSF command")] + public byte[] ReadCdMsfData { get; set; } + [DisplayName("Data from READ CD (full sector) command")] + public byte[] ReadCdFullData { get; set; } + [DisplayName("Data from READ CD MSF (full sector) command")] + public byte[] ReadCdMsfFullData { get; set; } + [DisplayName("Data from track 1 pregap")] + public byte[] Track1PregapData { get; set; } + [DisplayName("Data from Lead-In")] + public byte[] LeadInData { get; set; } + [DisplayName("Data from Lead-Out")] + public byte[] LeadOutData { get; set; } + [DisplayName("Data from reading C2 pointers")] + public byte[] C2PointersData { get; set; } + [DisplayName("Data from reading with PQ subchannels")] + public byte[] PQSubchannelData { get; set; } + [DisplayName("Data from reading with RW subchannels")] + public byte[] RWSubchannelData { get; set; } + [DisplayName("Data from reading with corrected subchannels")] + public byte[] CorrectedSubchannelData { get; set; } + [DisplayName("Data from reading with PQ subchannels and C2 pointers")] + public byte[] PQSubchannelWithC2Data { get; set; } + [DisplayName("Data from reading with RW subchannels and C2 pointers")] + public byte[] RWSubchannelWithC2Data { get; set; } + [DisplayName("Data from reading with corrected subchannels and C2 pointers")] + public byte[] CorrectedSubchannelWithC2Data { get; set; } + #endregion + + #region DVD data + [DisplayName("Data from PFI")] + public byte[] PfiData { get; set; } + [DisplayName("Data from DMI")] + public byte[] DmiData { get; set; } + [DisplayName("Data from DVD's Copyright Management Information")] + public byte[] CmiData { get; set; } + [DisplayName("Data from DVD's BCA")] + public byte[] DvdBcaData { get; set; } + [DisplayName("Data from DVD's AACS")] + public byte[] DvdAacsData { get; set; } + [DisplayName("Data from DVD's DDS")] + public byte[] DvdDdsData { get; set; } + [DisplayName("Data from DVD's Spare Area Information")] + public byte[] DvdSaiData { get; set; } + [DisplayName("Data from DVD's pre-recorded information")] + public byte[] PriData { get; set; } + [DisplayName("Data from embossed PFI")] + public byte[] EmbossedPfiData { get; set; } + [DisplayName("Data from ADIP")] + public byte[] AdipData { get; set; } + [DisplayName("Data from DCBs")] + public byte[] DcbData { get; set; } + [DisplayName("Data from HD-DVD's Copyright Management Information")] + public byte[] HdCmiData { get; set; } + [DisplayName("Data from DVD's layer information")] + public byte[] DvdLayerData { get; set; } + #endregion + + #region Blu-ray data + [DisplayName("Data from Blu-ray's BCA")] + public byte[] BluBcaData { get; set; } + [DisplayName("Data from Blu-ray's DDS")] + public byte[] BluDdsData { get; set; } + [DisplayName("Data from Blu-ray's Spare Area Information")] + public byte[] BluSaiData { get; set; } + [DisplayName("Data from Blu-ray's Disc Information")] + public byte[] BluDiData { get; set; } + [DisplayName("Data from Blu-ray's PAC")] + public byte[] BluPacData { get; set; } + #endregion + + #region Vendor data + [DisplayName("Data from Plextor's READ CD-DA command")] + public byte[] PlextorReadCddaData { get; set; } + [DisplayName("Data from Pioneer's READ CD-DA command")] + public byte[] PioneerReadCddaData { get; set; } + [DisplayName("Data from Pioneer's READ CD-DA MSF command")] + public byte[] PioneerReadCddaMsfData { get; set; } + [DisplayName("Data from NEC's READ CD-DA command")] + public byte[] NecReadCddaData { get; set; } + [DisplayName("Data from Plextor's scrambled DVD reading command")] + public byte[] PlextorReadRawDVDData { get; set; } + [DisplayName("Data from HL-DT-ST's scrambled DVD reading trick")] + public byte[] HLDTSTReadRawDVDData { get; set; } + #endregion + } + + public class Ssc + { + public Ssc() {} + + public Ssc(sscType ssc) + { + if(ssc.BlockSizeGranularitySpecified) + BlockSizeGranularity = ssc.BlockSizeGranularity; + + if(ssc.MaxBlockLengthSpecified) + MaxBlockLength = ssc.MaxBlockLength; + + if(ssc.MinBlockLengthSpecified) + MinBlockLength = ssc.MinBlockLength; + + if(ssc.SupportedDensities != null) + SupportedDensities = new List(ssc.SupportedDensities); + + if(ssc.SupportedMediaTypes != null) + { + SupportedMediaTypes = new List(); + + foreach(SupportedMedia mediaType in ssc.SupportedMediaTypes) + SupportedMediaTypes.Add(new SscSupportedMedia(mediaType)); + } + + if(ssc.TestedMedia == null) + return; + + TestedMedia = new List(); + + foreach(SequentialMedia testedMedia in ssc.TestedMedia) + TestedMedia.Add(new TestedSequentialMedia(testedMedia)); + } + + [JsonIgnore] + public int Id { get; set; } + [DisplayName("Block size granularity")] + public byte? BlockSizeGranularity { get; set; } + [DisplayName("Maximum block length")] + public uint? MaxBlockLength { get; set; } + [DisplayName("Minimum block length")] + public uint? MinBlockLength { get; set; } + + public virtual List SupportedDensities { get; set; } + public virtual List SupportedMediaTypes { get; set; } + public virtual List TestedMedia { get; set; } + } + + public class TestedSequentialMedia + { + public TestedSequentialMedia() {} + + public TestedSequentialMedia(SequentialMedia media) + { + if(media.CanReadMediaSerialSpecified) + CanReadMediaSerial = media.CanReadMediaSerial; + + if(media.DensitySpecified) + Density = media.Density; + + Manufacturer = media.Manufacturer; + MediaIsRecognized = media.MediaIsRecognized; + + if(media.MediumTypeSpecified) + MediumType = media.MediumType; + + MediumTypeName = media.MediumTypeName; + Model = media.Model; + + if(media.SupportedDensities != null) + SupportedDensities = new List(media.SupportedDensities); + + if(media.SupportedMediaTypes != null) + { + SupportedMediaTypes = new List(); + + foreach(SupportedMedia supportedMedia in media.SupportedMediaTypes) + SupportedMediaTypes.Add(new SscSupportedMedia(supportedMedia)); + } + + ModeSense6Data = media.ModeSense6Data; + ModeSense10Data = media.ModeSense10Data; + } + + [JsonIgnore] + public int Id { get; set; } + [DisplayName("Can read media serial?")] + public bool? CanReadMediaSerial { get; set; } + [DisplayName("Density code")] + public byte? Density { get; set; } + public string Manufacturer { get; set; } + [DisplayName("Media recognized by drive?")] + public bool MediaIsRecognized { get; set; } + [DisplayName("Medium type code")] + public byte? MediumType { get; set; } + [DisplayName("Medium type")] + public string MediumTypeName { get; set; } + public string Model { get; set; } + public virtual List SupportedDensities { get; set; } + public virtual List SupportedMediaTypes { get; set; } + + public byte[] ModeSense6Data { get; set; } + public byte[] ModeSense10Data { get; set; } + + [JsonIgnore] + public int? SscId { get; set; } + } + + public class Pcmcia + { + public string[] AdditionalInformation; + + public Pcmcia() {} + + public Pcmcia(pcmciaType pcmcia) + { + AdditionalInformation = pcmcia.AdditionalInformation; + CIS = pcmcia.CIS; + Compliance = pcmcia.Compliance; + + if(pcmcia.ManufacturerCodeSpecified) + ManufacturerCode = pcmcia.ManufacturerCode; + + if(pcmcia.CardCodeSpecified) + CardCode = pcmcia.CardCode; + + Manufacturer = pcmcia.Manufacturer; + ProductName = pcmcia.ProductName; + } + + [JsonIgnore] + public int Id { get; set; } + public byte[] CIS { get; set; } + public string Compliance { get; set; } + [DisplayName("Manufacturer code")] + public ushort? ManufacturerCode { get; set; } + [DisplayName("Card code")] + public ushort? CardCode { get; set; } + public string Manufacturer { get; set; } + [DisplayName("Product name")] + public string ProductName { get; set; } + } + + public class MmcSd + { + public MmcSd() {} + + public MmcSd(mmcsdType mmcSd) + { + CID = mmcSd.CID; + CSD = mmcSd.CSD; + OCR = mmcSd.OCR; + SCR = mmcSd.SCR; + ExtendedCSD = mmcSd.ExtendedCSD; + } + + [JsonIgnore] + public int Id { get; set; } + public byte[] CID { get; set; } + public byte[] CSD { get; set; } + public byte[] OCR { get; set; } + public byte[] SCR { get; set; } + public byte[] ExtendedCSD { get; set; } + } + + public class SscSupportedMedia + { + public SscSupportedMedia() {} + + public SscSupportedMedia(SupportedMedia media) + { + MediumType = media.MediumType; + Width = media.Width; + Length = media.Length; + Organization = media.Organization; + Name = media.Name; + Description = media.Description; + + if(media.DensityCodes == null) + return; + + DensityCodes = new List(); + + foreach(int densityCode in media.DensityCodes) + DensityCodes.Add(new DensityCode + { + Code = densityCode + }); + } + + [JsonIgnore] + public int Id { get; set; } + public byte MediumType { get; set; } + public virtual List DensityCodes { get; set; } + public ushort Width { get; set; } + public ushort Length { get; set; } + public string Organization { get; set; } + public string Name { get; set; } + public string Description { get; set; } + } + + public class DensityCode : IEquatable + { + [JsonIgnore, Key] + public int Id { get; set; } + + public int Code { get; set; } + + public bool Equals(DensityCode other) + { + if(ReferenceEquals(null, other)) + return false; + + if(ReferenceEquals(this, other)) + return true; + + return Code == other.Code; + } + + public override bool Equals(object obj) + { + if(ReferenceEquals(null, obj)) + return false; + + if(ReferenceEquals(this, obj)) + return true; + + return obj.GetType() == GetType() && Equals((DensityCode)obj); + } + + // ReSharper disable once NonReadonlyMemberInGetHashCode + public override int GetHashCode() => Code; + } + + public class GdRomSwapDiscCapabilities + { + [JsonIgnore, Key] + public int Id { get; set; } + + public bool RecognizedSwapDisc { get; set; } + public bool TestCrashed { get; set; } + public byte SwapDiscLeadOutPMIN { get; set; } + public byte SwapDiscLeadOutPSEC { get; set; } + public byte SwapDiscLeadOutPFRAM { get; set; } + public int SwapDiscLeadOutStart { get; set; } + public bool Lba0Readable { get; set; } + public byte[] Lba0Data { get; set; } + public byte[] Lba0Sense { get; set; } + public string Lba0DecodedSense { get; set; } + public bool Lba0ScrambledReadable { get; set; } + public byte[] Lba0ScrambledData { get; set; } + public byte[] Lba0ScrambledSense { get; set; } + public string Lba0ScrambledDecodedSense { get; set; } + public bool Lba44990Readable { get; set; } + public byte[] Lba44990Data { get; set; } + public byte[] Lba44990Sense { get; set; } + public string Lba44990DecodedSense { get; set; } + public int Lba44990ReadableCluster { get; set; } + public bool Lba45000Readable { get; set; } + public byte[] Lba45000Data { get; set; } + public byte[] Lba45000Sense { get; set; } + public string Lba45000DecodedSense { get; set; } + public int Lba45000ReadableCluster { get; set; } + public bool Lba50000Readable { get; set; } + public byte[] Lba50000Data { get; set; } + public byte[] Lba50000Sense { get; set; } + public string Lba50000DecodedSense { get; set; } + public int Lba50000ReadableCluster { get; set; } + public bool Lba100000Readable { get; set; } + public byte[] Lba100000Data { get; set; } + public byte[] Lba100000Sense { get; set; } + public string Lba100000DecodedSense { get; set; } + public int Lba100000ReadableCluster { get; set; } + public bool Lba400000Readable { get; set; } + public byte[] Lba400000Data { get; set; } + public byte[] Lba400000Sense { get; set; } + public string Lba400000DecodedSense { get; set; } + public int Lba400000ReadableCluster { get; set; } + public bool Lba450000Readable { get; set; } + public byte[] Lba450000Data { get; set; } + public byte[] Lba450000Sense { get; set; } + public string Lba450000DecodedSense { get; set; } + public int Lba450000ReadableCluster { get; set; } + public bool Lba44990PqReadable { get; set; } + public byte[] Lba44990PqData { get; set; } + public byte[] Lba44990PqSense { get; set; } + public string Lba44990PqDecodedSense { get; set; } + public int Lba44990PqReadableCluster { get; set; } + public bool Lba45000PqReadable { get; set; } + public byte[] Lba45000PqData { get; set; } + public byte[] Lba45000PqSense { get; set; } + public string Lba45000PqDecodedSense { get; set; } + public int Lba45000PqReadableCluster { get; set; } + public bool Lba50000PqReadable { get; set; } + public byte[] Lba50000PqData { get; set; } + public byte[] Lba50000PqSense { get; set; } + public string Lba50000PqDecodedSense { get; set; } + public int Lba50000PqReadableCluster { get; set; } + public bool Lba100000PqReadable { get; set; } + public byte[] Lba100000PqData { get; set; } + public byte[] Lba100000PqSense { get; set; } + public string Lba100000PqDecodedSense { get; set; } + public int Lba100000PqReadableCluster { get; set; } + public bool Lba400000PqReadable { get; set; } + public byte[] Lba400000PqData { get; set; } + public byte[] Lba400000PqSense { get; set; } + public string Lba400000PqDecodedSense { get; set; } + public int Lba400000PqReadableCluster { get; set; } + public bool Lba450000PqReadable { get; set; } + public byte[] Lba450000PqData { get; set; } + public byte[] Lba450000PqSense { get; set; } + public string Lba450000PqDecodedSense { get; set; } + public int Lba450000PqReadableCluster { get; set; } + public bool Lba44990RwReadable { get; set; } + public byte[] Lba44990RwData { get; set; } + public byte[] Lba44990RwSense { get; set; } + public string Lba44990RwDecodedSense { get; set; } + public int Lba44990RwReadableCluster { get; set; } + public bool Lba45000RwReadable { get; set; } + public byte[] Lba45000RwData { get; set; } + public byte[] Lba45000RwSense { get; set; } + public string Lba45000RwDecodedSense { get; set; } + public int Lba45000RwReadableCluster { get; set; } + public bool Lba50000RwReadable { get; set; } + public byte[] Lba50000RwData { get; set; } + public byte[] Lba50000RwSense { get; set; } + public string Lba50000RwDecodedSense { get; set; } + public int Lba50000RwReadableCluster { get; set; } + public bool Lba100000RwReadable { get; set; } + public byte[] Lba100000RwData { get; set; } + public byte[] Lba100000RwSense { get; set; } + public string Lba100000RwDecodedSense { get; set; } + public int Lba100000RwReadableCluster { get; set; } + public bool Lba400000RwReadable { get; set; } + public byte[] Lba400000RwData { get; set; } + public byte[] Lba400000RwSense { get; set; } + public string Lba400000RwDecodedSense { get; set; } + public int Lba400000RwReadableCluster { get; set; } + public bool Lba450000RwReadable { get; set; } + public byte[] Lba450000RwData { get; set; } + public byte[] Lba450000RwSense { get; set; } + public string Lba450000RwDecodedSense { get; set; } + public int Lba450000RwReadableCluster { get; set; } + public bool Lba44990AudioReadable { get; set; } + public byte[] Lba44990AudioData { get; set; } + public byte[] Lba44990AudioSense { get; set; } + public string Lba44990AudioDecodedSense { get; set; } + public int Lba44990AudioReadableCluster { get; set; } + public bool Lba45000AudioReadable { get; set; } + public byte[] Lba45000AudioData { get; set; } + public byte[] Lba45000AudioSense { get; set; } + public string Lba45000AudioDecodedSense { get; set; } + public int Lba45000AudioReadableCluster { get; set; } + public bool Lba50000AudioReadable { get; set; } + public byte[] Lba50000AudioData { get; set; } + public byte[] Lba50000AudioSense { get; set; } + public string Lba50000AudioDecodedSense { get; set; } + public int Lba50000AudioReadableCluster { get; set; } + public bool Lba100000AudioReadable { get; set; } + public byte[] Lba100000AudioData { get; set; } + public byte[] Lba100000AudioSense { get; set; } + public string Lba100000AudioDecodedSense { get; set; } + public int Lba100000AudioReadableCluster { get; set; } + public bool Lba400000AudioReadable { get; set; } + public byte[] Lba400000AudioData { get; set; } + public byte[] Lba400000AudioSense { get; set; } + public string Lba400000AudioDecodedSense { get; set; } + public int Lba400000AudioReadableCluster { get; set; } + public bool Lba450000AudioReadable { get; set; } + public byte[] Lba450000AudioData { get; set; } + public byte[] Lba450000AudioSense { get; set; } + public string Lba450000AudioDecodedSense { get; set; } + public int Lba450000AudioReadableCluster { get; set; } + public bool Lba44990AudioPqReadable { get; set; } + public byte[] Lba44990AudioPqData { get; set; } + public byte[] Lba44990AudioPqSense { get; set; } + public string Lba44990AudioPqDecodedSense { get; set; } + public int Lba44990AudioPqReadableCluster { get; set; } + public bool Lba45000AudioPqReadable { get; set; } + public byte[] Lba45000AudioPqData { get; set; } + public byte[] Lba45000AudioPqSense { get; set; } + public string Lba45000AudioPqDecodedSense { get; set; } + public int Lba45000AudioPqReadableCluster { get; set; } + public bool Lba50000AudioPqReadable { get; set; } + public byte[] Lba50000AudioPqData { get; set; } + public byte[] Lba50000AudioPqSense { get; set; } + public string Lba50000AudioPqDecodedSense { get; set; } + public int Lba50000AudioPqReadableCluster { get; set; } + public bool Lba100000AudioPqReadable { get; set; } + public byte[] Lba100000AudioPqData { get; set; } + public byte[] Lba100000AudioPqSense { get; set; } + public string Lba100000AudioPqDecodedSense { get; set; } + public int Lba100000AudioPqReadableCluster { get; set; } + public bool Lba400000AudioPqReadable { get; set; } + public byte[] Lba400000AudioPqData { get; set; } + public byte[] Lba400000AudioPqSense { get; set; } + public string Lba400000AudioPqDecodedSense { get; set; } + public int Lba400000AudioPqReadableCluster { get; set; } + public bool Lba450000AudioPqReadable { get; set; } + public byte[] Lba450000AudioPqData { get; set; } + public byte[] Lba450000AudioPqSense { get; set; } + public string Lba450000AudioPqDecodedSense { get; set; } + public int Lba450000AudioPqReadableCluster { get; set; } + public bool Lba44990AudioRwReadable { get; set; } + public byte[] Lba44990AudioRwData { get; set; } + public byte[] Lba44990AudioRwSense { get; set; } + public string Lba44990AudioRwDecodedSense { get; set; } + public int Lba44990AudioRwReadableCluster { get; set; } + public bool Lba45000AudioRwReadable { get; set; } + public byte[] Lba45000AudioRwData { get; set; } + public byte[] Lba45000AudioRwSense { get; set; } + public string Lba45000AudioRwDecodedSense { get; set; } + public int Lba45000AudioRwReadableCluster { get; set; } + public bool Lba50000AudioRwReadable { get; set; } + public byte[] Lba50000AudioRwData { get; set; } + public byte[] Lba50000AudioRwSense { get; set; } + public string Lba50000AudioRwDecodedSense { get; set; } + public int Lba50000AudioRwReadableCluster { get; set; } + public bool Lba100000AudioRwReadable { get; set; } + public byte[] Lba100000AudioRwData { get; set; } + public byte[] Lba100000AudioRwSense { get; set; } + public string Lba100000AudioRwDecodedSense { get; set; } + public int Lba100000AudioRwReadableCluster { get; set; } + public bool Lba400000AudioRwReadable { get; set; } + public byte[] Lba400000AudioRwData { get; set; } + public byte[] Lba400000AudioRwSense { get; set; } + public string Lba400000AudioRwDecodedSense { get; set; } + public int Lba400000AudioRwReadableCluster { get; set; } + public bool Lba450000AudioRwReadable { get; set; } + public byte[] Lba450000AudioRwData { get; set; } + public byte[] Lba450000AudioRwSense { get; set; } + public string Lba450000AudioRwDecodedSense { get; set; } + public int Lba450000AudioRwReadableCluster { get; set; } + public uint MinimumReadableSectorInHdArea { get; set; } + public uint MaximumReadableSectorInHdArea { get; set; } + public byte[] MaximumReadablePqInHdArea { get; set; } + public byte[] MaximumReadableRwInHdArea { get; set; } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Metadata/Dimensions.cs b/Aaru.CommonTypes/Metadata/Dimensions.cs new file mode 100644 index 000000000..153c2c782 --- /dev/null +++ b/Aaru.CommonTypes/Metadata/Dimensions.cs @@ -0,0 +1,1105 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Dimensions.cs +// Author(s) : Natalia Portillo +// +// Component : XML metadata. +// +// --[ Description ] ---------------------------------------------------------- +// +// Gets physical dimensions of a device/media based on its media type. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using Schemas; + +#pragma warning disable 612 + +namespace Aaru.CommonTypes.Metadata +{ + /// Physical dimensions for media types + public static class Dimensions + { + /// Gets the physical dimensions, in metadata expected format, for a given media type + /// Media type + /// Dimensions metadata + public static DimensionsType DimensionsFromMediaType(CommonTypes.MediaType dskType) + { + var dmns = new DimensionsType(); + + switch(dskType) + { + #region 5.25" floppy disk + case CommonTypes.MediaType.Apple32SS: + case CommonTypes.MediaType.Apple32DS: + case CommonTypes.MediaType.Apple33SS: + case CommonTypes.MediaType.Apple33DS: + case CommonTypes.MediaType.AppleFileWare: + case CommonTypes.MediaType.DOS_525_SS_DD_8: + case CommonTypes.MediaType.DOS_525_SS_DD_9: + case CommonTypes.MediaType.DOS_525_DS_DD_8: + case CommonTypes.MediaType.DOS_525_DS_DD_9: + case CommonTypes.MediaType.DOS_525_HD: + case CommonTypes.MediaType.XDF_525: + case CommonTypes.MediaType.ACORN_525_SS_SD_40: + case CommonTypes.MediaType.ACORN_525_SS_SD_80: + case CommonTypes.MediaType.ACORN_525_SS_DD_40: + case CommonTypes.MediaType.ACORN_525_SS_DD_80: + case CommonTypes.MediaType.ACORN_525_DS_DD: + case CommonTypes.MediaType.ATARI_525_SD: + case CommonTypes.MediaType.ATARI_525_ED: + case CommonTypes.MediaType.ATARI_525_DD: + case CommonTypes.MediaType.CBM_1540: + case CommonTypes.MediaType.CBM_1540_Ext: + case CommonTypes.MediaType.CBM_1571: + case CommonTypes.MediaType.ECMA_66: + case CommonTypes.MediaType.ECMA_70: + case CommonTypes.MediaType.NEC_525_HD: + case CommonTypes.MediaType.ECMA_78: + case CommonTypes.MediaType.ECMA_78_2: + case CommonTypes.MediaType.ECMA_99_8: + case CommonTypes.MediaType.ECMA_99_15: + case CommonTypes.MediaType.ECMA_99_26: + case CommonTypes.MediaType.FDFORMAT_525_DD: + case CommonTypes.MediaType.FDFORMAT_525_HD: + case CommonTypes.MediaType.MetaFloppy_Mod_I: + case CommonTypes.MediaType.MetaFloppy_Mod_II: + // According to ECMA-99 et al + dmns.Height = 133.3; + dmns.HeightSpecified = true; + dmns.Width = 133.3; + dmns.WidthSpecified = true; + dmns.Thickness = 1.65; + + return dmns; + #endregion 5.25" floppy disk + + #region 3.5" floppy disk + case CommonTypes.MediaType.AppleSonySS: + case CommonTypes.MediaType.AppleSonyDS: + case CommonTypes.MediaType.DOS_35_SS_DD_8: + case CommonTypes.MediaType.DOS_35_SS_DD_9: + case CommonTypes.MediaType.DOS_35_DS_DD_8: + case CommonTypes.MediaType.DOS_35_DS_DD_9: + case CommonTypes.MediaType.DOS_35_HD: + case CommonTypes.MediaType.DOS_35_ED: + case CommonTypes.MediaType.DMF: + case CommonTypes.MediaType.DMF_82: + case CommonTypes.MediaType.XDF_35: + case CommonTypes.MediaType.ACORN_35_DS_DD: + case CommonTypes.MediaType.CBM_35_DD: + case CommonTypes.MediaType.CBM_AMIGA_35_DD: + case CommonTypes.MediaType.CBM_AMIGA_35_HD: + case CommonTypes.MediaType.FDFORMAT_35_DD: + case CommonTypes.MediaType.FDFORMAT_35_HD: + case CommonTypes.MediaType.NEC_35_HD_8: + case CommonTypes.MediaType.NEC_35_HD_15: + case CommonTypes.MediaType.Floptical: + case CommonTypes.MediaType.HiFD: + case CommonTypes.MediaType.UHD144: + case CommonTypes.MediaType.Apricot_35: + case CommonTypes.MediaType.FD32MB: + // According to ECMA-100 et al + dmns.Height = 94; + dmns.HeightSpecified = true; + dmns.Width = 90; + dmns.WidthSpecified = true; + dmns.Thickness = 3.3; + + return dmns; + #endregion 3.5" floppy disk + + #region 8" floppy disk + case CommonTypes.MediaType.IBM23FD: + case CommonTypes.MediaType.IBM33FD_128: + case CommonTypes.MediaType.IBM33FD_256: + case CommonTypes.MediaType.IBM33FD_512: + case CommonTypes.MediaType.IBM43FD_128: + case CommonTypes.MediaType.IBM43FD_256: + case CommonTypes.MediaType.IBM53FD_256: + case CommonTypes.MediaType.IBM53FD_512: + case CommonTypes.MediaType.IBM53FD_1024: + case CommonTypes.MediaType.RX01: + case CommonTypes.MediaType.RX02: + case CommonTypes.MediaType.NEC_8_SD: + case CommonTypes.MediaType.NEC_8_DD: + case CommonTypes.MediaType.ECMA_54: + case CommonTypes.MediaType.ECMA_59: + case CommonTypes.MediaType.ECMA_69_8: + case CommonTypes.MediaType.ECMA_69_15: + case CommonTypes.MediaType.ECMA_69_26: + // According to ECMA-59 et al + dmns.Height = 203.2; + dmns.HeightSpecified = true; + dmns.Width = 203.2; + dmns.WidthSpecified = true; + dmns.Thickness = 1.65; + + return dmns; + #endregion 8" floppy disk + + #region 356mm magneto optical + case CommonTypes.MediaType.ECMA_260: + case CommonTypes.MediaType.ECMA_260_Double: + // According to ECMA-260 et al + dmns.Height = 421.84; + dmns.HeightSpecified = true; + dmns.Width = 443.76; + dmns.WidthSpecified = true; + dmns.Thickness = 25.4; + + return dmns; + #endregion 356mm magneto optical + + #region 300mm magneto optical + case CommonTypes.MediaType.ECMA_189: + case CommonTypes.MediaType.ECMA_190: + case CommonTypes.MediaType.ECMA_317: + // According to ECMA-317 et al + dmns.Height = 340; + dmns.HeightSpecified = true; + dmns.Width = 320; + dmns.WidthSpecified = true; + dmns.Thickness = 17; + + return dmns; + #endregion 300mm magneto optical + + #region 5.25" magneto optical + case CommonTypes.MediaType.ECMA_153: + case CommonTypes.MediaType.ECMA_153_512: + case CommonTypes.MediaType.ECMA_183_512: + case CommonTypes.MediaType.ECMA_183: + case CommonTypes.MediaType.ECMA_184_512: + case CommonTypes.MediaType.ECMA_184: + case CommonTypes.MediaType.ECMA_195: + case CommonTypes.MediaType.ECMA_195_512: + case CommonTypes.MediaType.ECMA_238: + case CommonTypes.MediaType.ECMA_280: + case CommonTypes.MediaType.ECMA_322: + case CommonTypes.MediaType.ECMA_322_2k: + case CommonTypes.MediaType.UDO: + case CommonTypes.MediaType.UDO2: + case CommonTypes.MediaType.UDO2_WORM: + case CommonTypes.MediaType.ISO_15286: + case CommonTypes.MediaType.ISO_15286_1024: + case CommonTypes.MediaType.ISO_15286_512: + case CommonTypes.MediaType.ISO_10089: + case CommonTypes.MediaType.ISO_10089_512: + case CommonTypes.MediaType.ECMA_322_1k: + case CommonTypes.MediaType.ECMA_322_512: + case CommonTypes.MediaType.ISO_14517: + case CommonTypes.MediaType.ISO_14517_512: + // According to ECMA-183 et al + dmns.Height = 153; + dmns.HeightSpecified = true; + dmns.Width = 135; + dmns.WidthSpecified = true; + dmns.Thickness = 11; + + return dmns; + #endregion 5.25" magneto optical + + #region 3.5" magneto optical + case CommonTypes.MediaType.ECMA_154: + case CommonTypes.MediaType.ECMA_201: + case CommonTypes.MediaType.ECMA_201_ROM: + case CommonTypes.MediaType.ECMA_223: + case CommonTypes.MediaType.ECMA_223_512: + case CommonTypes.MediaType.GigaMo: + case CommonTypes.MediaType.GigaMo2: + case CommonTypes.MediaType.ISO_15041_512: + // According to ECMA-154 et al + dmns.Height = 94; + dmns.HeightSpecified = true; + dmns.Width = 90; + dmns.WidthSpecified = true; + dmns.Thickness = 6; + + return dmns; + #endregion 3.5" magneto optical + + case CommonTypes.MediaType.PD650: + case CommonTypes.MediaType.PD650_WORM: + dmns.Height = 135; + dmns.HeightSpecified = true; + dmns.Width = 124; + dmns.WidthSpecified = true; + dmns.Thickness = 7.8; + + return dmns; + case CommonTypes.MediaType.ECMA_239: + dmns.Height = 97; + dmns.HeightSpecified = true; + dmns.Width = 92; + dmns.WidthSpecified = true; + dmns.Thickness = 5; + + return dmns; + case CommonTypes.MediaType.MMCmicro: + dmns.Height = 14; + dmns.HeightSpecified = true; + dmns.Width = 12; + dmns.WidthSpecified = true; + dmns.Thickness = 1.1; + + return dmns; + case CommonTypes.MediaType.MemoryStickMicro: + dmns.Height = 15; + dmns.HeightSpecified = true; + dmns.Width = 12.5; + dmns.WidthSpecified = true; + dmns.Thickness = 1.2; + + return dmns; + case CommonTypes.MediaType.microSD: + dmns.Height = 11; + dmns.HeightSpecified = true; + dmns.Width = 15; + dmns.WidthSpecified = true; + dmns.Thickness = 1; + + return dmns; + case CommonTypes.MediaType.miniSD: + dmns.Height = 21.5; + dmns.HeightSpecified = true; + dmns.Width = 20; + dmns.WidthSpecified = true; + dmns.Thickness = 1.4; + + return dmns; + case CommonTypes.MediaType.QIC3010: + case CommonTypes.MediaType.QIC3020: + case CommonTypes.MediaType.QIC3080: + case CommonTypes.MediaType.QIC3095: + case CommonTypes.MediaType.QIC320: + case CommonTypes.MediaType.QIC40: + case CommonTypes.MediaType.QIC80: + dmns.Height = 20; + dmns.HeightSpecified = true; + dmns.Width = 21.5; + dmns.WidthSpecified = true; + dmns.Thickness = 1.6; + + return dmns; + case CommonTypes.MediaType.RSMMC: + dmns.Height = 18; + dmns.HeightSpecified = true; + dmns.Width = 24; + dmns.WidthSpecified = true; + dmns.Thickness = 1.4; + + return dmns; + case CommonTypes.MediaType.MMC: + dmns.Height = 32; + dmns.HeightSpecified = true; + dmns.Width = 24; + dmns.WidthSpecified = true; + dmns.Thickness = 1.4; + + return dmns; + case CommonTypes.MediaType.SecureDigital: + dmns.Height = 32; + dmns.HeightSpecified = true; + dmns.Width = 24; + dmns.WidthSpecified = true; + dmns.Thickness = 2.1; + + return dmns; + case CommonTypes.MediaType.xD: + dmns.Height = 20; + dmns.HeightSpecified = true; + dmns.Width = 25; + dmns.WidthSpecified = true; + dmns.Thickness = 1.78; + + return dmns; + case CommonTypes.MediaType.XQD: + dmns.Height = 38.5; + dmns.HeightSpecified = true; + dmns.Width = 29.8; + dmns.WidthSpecified = true; + dmns.Thickness = 3.8; + + return dmns; + case CommonTypes.MediaType.MemoryStickDuo: + case CommonTypes.MediaType.MemoryStickProDuo: + dmns.Height = 20; + dmns.HeightSpecified = true; + dmns.Width = 31; + dmns.WidthSpecified = true; + dmns.Thickness = 1.6; + + return dmns; + case CommonTypes.MediaType.Nintendo3DSGameCard: + case CommonTypes.MediaType.NintendoDSGameCard: + case CommonTypes.MediaType.NintendoDSiGameCard: + dmns.Height = 35; + dmns.HeightSpecified = true; + dmns.Width = 33; + dmns.WidthSpecified = true; + dmns.Thickness = 3.8; + + return dmns; + case CommonTypes.MediaType.DataPlay: + dmns.Height = 42; + dmns.HeightSpecified = true; + dmns.Width = 33.5; + dmns.WidthSpecified = true; + dmns.Thickness = 3; + + return dmns; + case CommonTypes.MediaType.Microdrive: + dmns.Height = 44; + dmns.HeightSpecified = true; + dmns.Width = 34; + dmns.WidthSpecified = true; + dmns.Thickness = 8; + + return dmns; + case CommonTypes.MediaType.ExpressCard34: + dmns.Height = 75; + dmns.HeightSpecified = true; + dmns.Width = 34; + dmns.WidthSpecified = true; + dmns.Thickness = 5; + + return dmns; + case CommonTypes.MediaType.SmartMedia: + dmns.Height = 45; + dmns.HeightSpecified = true; + dmns.Width = 37; + dmns.WidthSpecified = true; + dmns.Thickness = 0.76; + + return dmns; + case CommonTypes.MediaType.MiniCard: + dmns.Height = 45; + dmns.HeightSpecified = true; + dmns.Width = 37; + dmns.WidthSpecified = true; + dmns.Thickness = 3.5; + + return dmns; + case CommonTypes.MediaType.PlayStationMemoryCard: + case CommonTypes.MediaType.PlayStationMemoryCard2: + dmns.Height = 55.7; + dmns.HeightSpecified = true; + dmns.Width = 41.5; + dmns.WidthSpecified = true; + dmns.Thickness = 7; + + return dmns; + case CommonTypes.MediaType.CFast: + case CommonTypes.MediaType.CompactFlash: + dmns.Height = 36; + dmns.HeightSpecified = true; + dmns.Width = 43; + dmns.WidthSpecified = true; + dmns.Thickness = 3.3; + + return dmns; + case CommonTypes.MediaType.CompactFlashType2: + dmns.Height = 36; + dmns.HeightSpecified = true; + dmns.Width = 43; + dmns.WidthSpecified = true; + dmns.Thickness = 5; + + return dmns; + case CommonTypes.MediaType.ZXMicrodrive: + dmns.Height = 36; + dmns.HeightSpecified = true; + dmns.Width = 43; + dmns.WidthSpecified = true; + dmns.Thickness = 5; + + return dmns; + case CommonTypes.MediaType.MemoryStick: + case CommonTypes.MediaType.MemoryStickPro: + dmns.Height = 21; + dmns.HeightSpecified = true; + dmns.Width = 50; + dmns.WidthSpecified = true; + dmns.Thickness = 2.6; + + return dmns; + case CommonTypes.MediaType.PocketZip: + dmns.Height = 54.5; + dmns.HeightSpecified = true; + dmns.Width = 50; + dmns.WidthSpecified = true; + dmns.Thickness = 2; + + return dmns; + case CommonTypes.MediaType.ExpressCard54: + dmns.Height = 75; + dmns.HeightSpecified = true; + dmns.Width = 54; + dmns.WidthSpecified = true; + dmns.Thickness = 5; + + return dmns; + case CommonTypes.MediaType.PCCardTypeI: + dmns.Height = 85.6; + dmns.HeightSpecified = true; + dmns.Width = 54; + dmns.WidthSpecified = true; + dmns.Thickness = 3.3; + + return dmns; + case CommonTypes.MediaType.PCCardTypeII: + dmns.Height = 85.6; + dmns.HeightSpecified = true; + dmns.Width = 54; + dmns.WidthSpecified = true; + dmns.Thickness = 5; + + return dmns; + case CommonTypes.MediaType.PCCardTypeIII: + dmns.Height = 85.6; + dmns.HeightSpecified = true; + dmns.Width = 54; + dmns.WidthSpecified = true; + dmns.Thickness = 10.5; + + return dmns; + case CommonTypes.MediaType.PCCardTypeIV: + dmns.Height = 85.6; + dmns.HeightSpecified = true; + dmns.Width = 54; + dmns.WidthSpecified = true; + dmns.Thickness = 16; + + return dmns; + case CommonTypes.MediaType.DataStore: + dmns.Height = 86.5; + dmns.HeightSpecified = true; + dmns.Width = 54; + dmns.WidthSpecified = true; + dmns.Thickness = 2.5; + + return dmns; + case CommonTypes.MediaType.VideoFloppy: + dmns.Height = 54; + dmns.HeightSpecified = true; + dmns.Width = 60; + dmns.WidthSpecified = true; + dmns.Thickness = 3.5; + + return dmns; + case CommonTypes.MediaType.VXA1: + case CommonTypes.MediaType.VXA2: + case CommonTypes.MediaType.VXA3: + dmns.Height = 95; + dmns.HeightSpecified = true; + dmns.Width = 62.5; + dmns.WidthSpecified = true; + dmns.Thickness = 15; + + return dmns; + case CommonTypes.MediaType.MiniDV: + dmns.Height = 47.5; + dmns.HeightSpecified = true; + dmns.Width = 66; + dmns.WidthSpecified = true; + dmns.Thickness = 12; + + return dmns; + case CommonTypes.MediaType.Wafer: + dmns.Height = 46.8; + dmns.HeightSpecified = true; + dmns.Width = 67.1; + dmns.WidthSpecified = true; + dmns.Thickness = 7.9; + + return dmns; + case CommonTypes.MediaType.NintendoDiskCard: + dmns.Height = 76.2; + dmns.HeightSpecified = true; + dmns.Width = 71.12; + dmns.WidthSpecified = true; + dmns.Thickness = 0; + + return dmns; + case CommonTypes.MediaType.HiMD: + case CommonTypes.MediaType.MD: + case CommonTypes.MediaType.MDData: + case CommonTypes.MediaType.MDData2: + case CommonTypes.MediaType.MD60: + case CommonTypes.MediaType.MD74: + case CommonTypes.MediaType.MD80: + dmns.Height = 68; + dmns.HeightSpecified = true; + dmns.Width = 71.5; + dmns.WidthSpecified = true; + dmns.Thickness = 4.8; + + return dmns; + case CommonTypes.MediaType.DAT160: + case CommonTypes.MediaType.DAT320: + case CommonTypes.MediaType.DAT72: + case CommonTypes.MediaType.DDS1: + case CommonTypes.MediaType.DDS2: + case CommonTypes.MediaType.DDS3: + case CommonTypes.MediaType.DDS4: + case CommonTypes.MediaType.DigitalAudioTape: + dmns.Height = 54; + dmns.HeightSpecified = true; + dmns.Width = 73; + dmns.WidthSpecified = true; + dmns.Thickness = 10.5; + + return dmns; + case CommonTypes.MediaType.CompactFloppy: + dmns.Height = 100; + dmns.HeightSpecified = true; + dmns.Width = 80; + dmns.WidthSpecified = true; + dmns.Thickness = 5; + + return dmns; + case CommonTypes.MediaType.DECtapeII: + dmns.Height = 60; + dmns.HeightSpecified = true; + dmns.Width = 81; + dmns.WidthSpecified = true; + dmns.Thickness = 13; + + return dmns; + case CommonTypes.MediaType.Ditto: + dmns.Height = 60; + dmns.HeightSpecified = true; + dmns.Width = 81; + dmns.WidthSpecified = true; + dmns.Thickness = 14; + + return dmns; + case CommonTypes.MediaType.DittoMax: + dmns.Height = 126; + dmns.HeightSpecified = true; + dmns.Width = 81; + dmns.WidthSpecified = true; + dmns.Thickness = 14; + + return dmns; + case CommonTypes.MediaType.RDX: + case CommonTypes.MediaType.RDX320: + dmns.Height = 119; + dmns.HeightSpecified = true; + dmns.Width = 87; + dmns.WidthSpecified = true; + dmns.Thickness = 23; + + return dmns; + case CommonTypes.MediaType.LS120: + case CommonTypes.MediaType.LS240: + dmns.Height = 94; + dmns.HeightSpecified = true; + dmns.Width = 90; + dmns.WidthSpecified = true; + dmns.Thickness = 3.5; + + return dmns; + case CommonTypes.MediaType.Travan: + case CommonTypes.MediaType.Travan3: + case CommonTypes.MediaType.Travan4: + case CommonTypes.MediaType.Travan5: + case CommonTypes.MediaType.Travan7: + dmns.Height = 72; + dmns.HeightSpecified = true; + dmns.Width = 92; + dmns.WidthSpecified = true; + dmns.Thickness = 15; + + return dmns; + case CommonTypes.MediaType.Travan1Ex: + dmns.Height = 0; + dmns.HeightSpecified = true; + dmns.Width = 92; + dmns.WidthSpecified = true; + dmns.Thickness = 15; + + return dmns; + case CommonTypes.MediaType.Travan3Ex: + dmns.Height = 0; + dmns.HeightSpecified = true; + dmns.Width = 92; + dmns.WidthSpecified = true; + dmns.Thickness = 15; + + return dmns; + case CommonTypes.MediaType.ADR2120: + case CommonTypes.MediaType.ADR260: + case CommonTypes.MediaType.ADR30: + case CommonTypes.MediaType.ADR50: + dmns.Height = 129; + dmns.HeightSpecified = true; + dmns.Width = 93; + dmns.WidthSpecified = true; + dmns.Thickness = 14.5; + + return dmns; + case CommonTypes.MediaType.Data8: + case CommonTypes.MediaType.AIT1: + case CommonTypes.MediaType.AIT1Turbo: + case CommonTypes.MediaType.AIT2: + case CommonTypes.MediaType.AIT2Turbo: + case CommonTypes.MediaType.AIT3: + case CommonTypes.MediaType.AIT3Ex: + case CommonTypes.MediaType.AIT3Turbo: + case CommonTypes.MediaType.AIT4: + case CommonTypes.MediaType.AIT5: + case CommonTypes.MediaType.AITETurbo: + case CommonTypes.MediaType.Exatape106m: + case CommonTypes.MediaType.Exatape160mXL: + case CommonTypes.MediaType.Exatape112m: + case CommonTypes.MediaType.Exatape125m: + case CommonTypes.MediaType.Exatape150m: + case CommonTypes.MediaType.Exatape15m: + case CommonTypes.MediaType.Exatape170m: + case CommonTypes.MediaType.Exatape225m: + case CommonTypes.MediaType.Exatape22m: + case CommonTypes.MediaType.Exatape22mAME: + case CommonTypes.MediaType.Exatape28m: + case CommonTypes.MediaType.Exatape40m: + case CommonTypes.MediaType.Exatape45m: + case CommonTypes.MediaType.Exatape54m: + case CommonTypes.MediaType.Exatape75m: + case CommonTypes.MediaType.Exatape76m: + case CommonTypes.MediaType.Exatape80m: + dmns.Height = 62.5; + dmns.HeightSpecified = true; + dmns.Width = 95; + dmns.WidthSpecified = true; + dmns.Thickness = 15; + + return dmns; + case CommonTypes.MediaType.EZ135: + case CommonTypes.MediaType.EZ230: + case CommonTypes.MediaType.SQ327: + dmns.Height = 97; + dmns.HeightSpecified = true; + dmns.Width = 98; + dmns.WidthSpecified = true; + dmns.Thickness = 9.5; + + return dmns; + case CommonTypes.MediaType.SQ400: + case CommonTypes.MediaType.SQ800: + case CommonTypes.MediaType.SQ2000: + dmns.Height = 137; + dmns.HeightSpecified = true; + dmns.Width = 137; + dmns.WidthSpecified = true; + dmns.Thickness = 12; + + return dmns; + case CommonTypes.MediaType.ZIP100: + case CommonTypes.MediaType.ZIP250: + case CommonTypes.MediaType.ZIP750: + dmns.Height = 98.5; + dmns.HeightSpecified = true; + dmns.Width = 98; + dmns.WidthSpecified = true; + dmns.Thickness = 6.5; + + return dmns; + case CommonTypes.MediaType.Jaz: + case CommonTypes.MediaType.Jaz2: + dmns.Height = 102; + dmns.HeightSpecified = true; + dmns.Width = 98; + dmns.WidthSpecified = true; + dmns.Thickness = 12; + + return dmns; + case CommonTypes.MediaType.Orb: + case CommonTypes.MediaType.Orb5: + dmns.Height = 104; + dmns.HeightSpecified = true; + dmns.Width = 98; + dmns.WidthSpecified = true; + dmns.Thickness = 8; + + return dmns; + case CommonTypes.MediaType.SparQ: + dmns.Height = 98; + dmns.HeightSpecified = true; + dmns.Width = 100; + dmns.WidthSpecified = true; + dmns.Thickness = 9.7; + + return dmns; + case CommonTypes.MediaType.ProfessionalDisc: + case CommonTypes.MediaType.ProfessionalDiscDual: + case CommonTypes.MediaType.ProfessionalDiscTriple: + case CommonTypes.MediaType.ProfessionalDiscQuad: + case CommonTypes.MediaType.PDD: + case CommonTypes.MediaType.PDD_WORM: + dmns.Height = 130; + dmns.HeightSpecified = true; + dmns.Width = 128.5; + dmns.WidthSpecified = true; + dmns.Thickness = 9; + + return dmns; + case CommonTypes.MediaType.SLR1: + case CommonTypes.MediaType.SLR2: + case CommonTypes.MediaType.SLR3: + case CommonTypes.MediaType.SLR32: + case CommonTypes.MediaType.SLR32SL: + case CommonTypes.MediaType.SLR4: + case CommonTypes.MediaType.SLR5: + case CommonTypes.MediaType.SLR5SL: + case CommonTypes.MediaType.SLR6: + case CommonTypes.MediaType.SLRtape100: + case CommonTypes.MediaType.SLRtape140: + case CommonTypes.MediaType.SLRtape24: + case CommonTypes.MediaType.SLRtape24SL: + case CommonTypes.MediaType.SLRtape40: + case CommonTypes.MediaType.SLRtape50: + case CommonTypes.MediaType.SLRtape60: + case CommonTypes.MediaType.SLRtape7: + case CommonTypes.MediaType.SLRtape75: + case CommonTypes.MediaType.SLRtape7SL: + dmns.Height = 150; + dmns.HeightSpecified = true; + dmns.Width = 100; + dmns.WidthSpecified = true; + dmns.Thickness = 18; + + return dmns; + case CommonTypes.MediaType.N64DD: + dmns.Height = 103.124; + dmns.HeightSpecified = true; + dmns.Width = 101.092; + dmns.WidthSpecified = true; + dmns.Thickness = 10.16; + + return dmns; + case CommonTypes.MediaType.CompactTapeI: + case CommonTypes.MediaType.CompactTapeII: + case CommonTypes.MediaType.DLTtapeIII: + case CommonTypes.MediaType.DLTtapeIIIxt: + case CommonTypes.MediaType.DLTtapeIV: + case CommonTypes.MediaType.DLTtapeS4: + case CommonTypes.MediaType.SDLT1: + case CommonTypes.MediaType.SDLT2: + case CommonTypes.MediaType.VStapeI: + dmns.Height = 105; + dmns.HeightSpecified = true; + dmns.Width = 105; + dmns.WidthSpecified = true; + dmns.Thickness = 25; + + return dmns; + case CommonTypes.MediaType.LTO: + case CommonTypes.MediaType.LTO2: + case CommonTypes.MediaType.LTO3: + case CommonTypes.MediaType.LTO3WORM: + case CommonTypes.MediaType.LTO4: + case CommonTypes.MediaType.LTO4WORM: + case CommonTypes.MediaType.LTO5: + case CommonTypes.MediaType.LTO5WORM: + case CommonTypes.MediaType.LTO6: + case CommonTypes.MediaType.LTO6WORM: + case CommonTypes.MediaType.LTO7: + case CommonTypes.MediaType.LTO7WORM: + dmns.Height = 101.6; + dmns.HeightSpecified = true; + dmns.Width = 105.41; + dmns.WidthSpecified = true; + dmns.Thickness = 21.59; + + return dmns; + case CommonTypes.MediaType.IBM3480: + case CommonTypes.MediaType.IBM3490: + case CommonTypes.MediaType.IBM3490E: + case CommonTypes.MediaType.IBM3592: + dmns.Height = 125.73; + dmns.HeightSpecified = true; + dmns.Width = 107.95; + dmns.WidthSpecified = true; + dmns.Thickness = 25.4; + + return dmns; + case CommonTypes.MediaType.T9840A: + case CommonTypes.MediaType.T9840B: + case CommonTypes.MediaType.T9840C: + case CommonTypes.MediaType.T9840D: + case CommonTypes.MediaType.T9940A: + case CommonTypes.MediaType.T9940B: + dmns.Height = 124.46; + dmns.HeightSpecified = true; + dmns.Width = 109.22; + dmns.WidthSpecified = true; + dmns.Thickness = 25.4; + + return dmns; + case CommonTypes.MediaType.CompactCassette: + case CommonTypes.MediaType.Dcas25: + case CommonTypes.MediaType.Dcas85: + case CommonTypes.MediaType.Dcas103: + dmns.Height = 63.5; + dmns.HeightSpecified = true; + dmns.Width = 128; + dmns.WidthSpecified = true; + dmns.Thickness = 12; + + return dmns; + case CommonTypes.MediaType.IBM3470: + dmns.Height = 58.42; + dmns.HeightSpecified = true; + dmns.Width = 137.16; + dmns.WidthSpecified = true; + dmns.Thickness = 16.51; + + return dmns; + case CommonTypes.MediaType.MLR1: + case CommonTypes.MediaType.MLR3: + case CommonTypes.MediaType.MLR1SL: + dmns.Height = 101.6; + dmns.HeightSpecified = true; + dmns.Width = 152.4; + dmns.WidthSpecified = true; + dmns.Thickness = 15.24; + + return dmns; + case CommonTypes.MediaType.QIC11: + case CommonTypes.MediaType.QIC120: + case CommonTypes.MediaType.QIC1350: + case CommonTypes.MediaType.QIC150: + case CommonTypes.MediaType.QIC24: + case CommonTypes.MediaType.QIC525: + dmns.Height = 101.6; + dmns.HeightSpecified = true; + dmns.Width = 154.2; + dmns.WidthSpecified = true; + dmns.Thickness = 16.6; + + return dmns; + case CommonTypes.MediaType.Bernoulli: + case CommonTypes.MediaType.Bernoulli10: + case CommonTypes.MediaType.Bernoulli20: + dmns.Height = 280; + dmns.HeightSpecified = true; + dmns.Width = 209; + dmns.WidthSpecified = true; + dmns.Thickness = 18; + + return dmns; + case CommonTypes.MediaType.Bernoulli2: + case CommonTypes.MediaType.BernoulliBox2_20: + case CommonTypes.MediaType.Bernoulli35: + case CommonTypes.MediaType.Bernoulli44: + case CommonTypes.MediaType.Bernoulli65: + case CommonTypes.MediaType.Bernoulli90: + case CommonTypes.MediaType.Bernoulli105: + case CommonTypes.MediaType.Bernoulli150: + case CommonTypes.MediaType.Bernoulli230: + dmns.Height = 138; + dmns.HeightSpecified = true; + dmns.Width = 136; + dmns.WidthSpecified = true; + dmns.Thickness = 9; + + return dmns; + case CommonTypes.MediaType.DTF: + case CommonTypes.MediaType.DTF2: + dmns.Height = 144.78; + dmns.HeightSpecified = true; + dmns.Width = 254; + dmns.WidthSpecified = true; + dmns.Thickness = 25.4; + + return dmns; + case CommonTypes.MediaType.LD: + case CommonTypes.MediaType.LDROM: + case CommonTypes.MediaType.LDROM2: + case CommonTypes.MediaType.MegaLD: + case CommonTypes.MediaType.LVROM: + dmns.Diameter = 300; + dmns.DiameterSpecified = true; + dmns.Thickness = 2.5; + + return dmns; + case CommonTypes.MediaType.CRVdisc: + dmns.Height = 344; + dmns.HeightSpecified = true; + dmns.Width = 325; + dmns.WidthSpecified = true; + dmns.Thickness = 15.6; + + return dmns; + case CommonTypes.MediaType.REV35: + case CommonTypes.MediaType.REV70: + case CommonTypes.MediaType.REV120: + dmns.Height = 74.8; + dmns.HeightSpecified = true; + dmns.Width = 76.8; + dmns.WidthSpecified = true; + dmns.Thickness = 10; + + return dmns; + + #region CD/DVD/BD + case CommonTypes.MediaType.CDDA: + case CommonTypes.MediaType.CDG: + case CommonTypes.MediaType.CDEG: + case CommonTypes.MediaType.CDI: + case CommonTypes.MediaType.CDROM: + case CommonTypes.MediaType.CDROMXA: + case CommonTypes.MediaType.CDPLUS: + case CommonTypes.MediaType.CDMO: + case CommonTypes.MediaType.CDR: + case CommonTypes.MediaType.CDRW: + case CommonTypes.MediaType.CDMRW: + case CommonTypes.MediaType.VCD: + case CommonTypes.MediaType.SVCD: + case CommonTypes.MediaType.PCD: + case CommonTypes.MediaType.SACD: + case CommonTypes.MediaType.DDCD: + case CommonTypes.MediaType.DDCDR: + case CommonTypes.MediaType.DDCDRW: + case CommonTypes.MediaType.DTSCD: + case CommonTypes.MediaType.CDMIDI: + case CommonTypes.MediaType.CDV: + case CommonTypes.MediaType.CD: + case CommonTypes.MediaType.DVDROM: + case CommonTypes.MediaType.DVDR: + case CommonTypes.MediaType.DVDRW: + case CommonTypes.MediaType.DVDPR: + case CommonTypes.MediaType.DVDPRW: + case CommonTypes.MediaType.DVDPRWDL: + case CommonTypes.MediaType.DVDRDL: + case CommonTypes.MediaType.DVDPRDL: + case CommonTypes.MediaType.DVDRAM: + case CommonTypes.MediaType.DVDRWDL: + case CommonTypes.MediaType.DVDDownload: + case CommonTypes.MediaType.HDDVDROM: + case CommonTypes.MediaType.HDDVDRAM: + case CommonTypes.MediaType.HDDVDR: + case CommonTypes.MediaType.HDDVDRW: + case CommonTypes.MediaType.HDDVDRDL: + case CommonTypes.MediaType.HDDVDRWDL: + case CommonTypes.MediaType.BDROM: + case CommonTypes.MediaType.BDR: + case CommonTypes.MediaType.BDRE: + case CommonTypes.MediaType.BDRXL: + case CommonTypes.MediaType.BDREXL: + case CommonTypes.MediaType.PS1CD: + case CommonTypes.MediaType.PS2CD: + case CommonTypes.MediaType.PS2DVD: + case CommonTypes.MediaType.PS3DVD: + case CommonTypes.MediaType.PS3BD: + case CommonTypes.MediaType.PS4BD: + case CommonTypes.MediaType.PS5BD: + case CommonTypes.MediaType.XGD: + case CommonTypes.MediaType.XGD2: + case CommonTypes.MediaType.XGD3: + case CommonTypes.MediaType.XGD4: + case CommonTypes.MediaType.MEGACD: + case CommonTypes.MediaType.SATURNCD: + case CommonTypes.MediaType.GDROM: + case CommonTypes.MediaType.GDR: + case CommonTypes.MediaType.SuperCDROM2: + case CommonTypes.MediaType.JaguarCD: + case CommonTypes.MediaType.ThreeDO: + case CommonTypes.MediaType.WOD: + case CommonTypes.MediaType.WUOD: + case CommonTypes.MediaType.PCFX: + case CommonTypes.MediaType.CDIREADY: + case CommonTypes.MediaType.FMTOWNS: + case CommonTypes.MediaType.CDTV: + case CommonTypes.MediaType.CD32: + case CommonTypes.MediaType.Nuon: + case CommonTypes.MediaType.Playdia: + case CommonTypes.MediaType.Pippin: + case CommonTypes.MediaType.MilCD: + case CommonTypes.MediaType.CVD: + case CommonTypes.MediaType.UHDBD: + dmns.Diameter = 120; + dmns.DiameterSpecified = true; + dmns.Thickness = 1.2; + + return dmns; + case CommonTypes.MediaType.GOD: + dmns.Diameter = 80; + dmns.DiameterSpecified = true; + dmns.Thickness = 1.2; + + return dmns; + case CommonTypes.MediaType.VideoNow: + dmns.Diameter = 85; + dmns.DiameterSpecified = true; + dmns.Thickness = 1.2; + + return dmns; + case CommonTypes.MediaType.VideoNowColor: + case CommonTypes.MediaType.VideoNowXp: + dmns.Diameter = 108; + dmns.DiameterSpecified = true; + dmns.Thickness = 1.2; + + return dmns; + #endregion CD/DVD/BD + + #region Apple Hard Disks + // TODO: Find Apple Widget size + case CommonTypes.MediaType.AppleProfile: + dmns.Height = 223.8; + dmns.HeightSpecified = true; + dmns.Width = 438.9; + dmns.WidthSpecified = true; + dmns.Thickness = 111.5; + + return dmns; + case CommonTypes.MediaType.AppleHD20: + dmns.Height = 246.4; + dmns.HeightSpecified = true; + dmns.Width = 266.7; + dmns.WidthSpecified = true; + dmns.Thickness = 78.7; + + return dmns; + #endregion Apple Hard Disks + + case CommonTypes.MediaType.UMD: + dmns.Height = 64; + dmns.HeightSpecified = true; + dmns.Width = 63; + dmns.WidthSpecified = true; + dmns.Thickness = 4; + + return dmns; + default: return null; + } + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Metadata/MediaType.cs b/Aaru.CommonTypes/Metadata/MediaType.cs new file mode 100644 index 000000000..82a606997 --- /dev/null +++ b/Aaru.CommonTypes/Metadata/MediaType.cs @@ -0,0 +1,2559 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : MediaType.cs +// Author(s) : Natalia Portillo +// +// Component : XML metadata. +// +// --[ Description ] ---------------------------------------------------------- +// +// Converts a common media type to the XML equivalent. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +#pragma warning disable 612 +namespace Aaru.CommonTypes.Metadata +{ + /// Handles media type for metadata + public static class MediaType + { + /// Converts a media type of a pair of type and subtype strings to use in metadata + /// Media type + /// Media type and subtype for metadata + public static (string type, string subType) MediaTypeToString(CommonTypes.MediaType dskType) + { + string discType; + string discSubType; + + switch(dskType) + { + case CommonTypes.MediaType.BDR: + discType = "Blu-ray"; + discSubType = "BD-R"; + + break; + case CommonTypes.MediaType.BDRE: + discType = "Blu-ray"; + discSubType = "BD-RE"; + + break; + case CommonTypes.MediaType.BDREXL: + discType = "Blu-ray"; + discSubType = "BD-RE XL"; + + break; + case CommonTypes.MediaType.BDROM: + discType = "Blu-ray"; + discSubType = "BD-ROM"; + + break; + case CommonTypes.MediaType.BDRXL: + discType = "Blu-ray"; + discSubType = "BD-R XL"; + + break; + case CommonTypes.MediaType.UHDBD: + discType = "Blu-ray"; + discSubType = "Ultra HD Blu-ray"; + + break; + case CommonTypes.MediaType.CBHD: + discType = "Blu-ray"; + discSubType = "CBHD"; + + break; + case CommonTypes.MediaType.CD: + discType = "Compact Disc"; + discSubType = "CD"; + + break; + case CommonTypes.MediaType.CDDA: + discType = "Compact Disc"; + discSubType = "CD Digital Audio"; + + break; + case CommonTypes.MediaType.CDEG: + discType = "Compact Disc"; + discSubType = "CD+EG"; + + break; + case CommonTypes.MediaType.CDG: + discType = "Compact Disc"; + discSubType = "CD+G"; + + break; + case CommonTypes.MediaType.CDI: + discType = "Compact Disc"; + discSubType = "CD-i"; + + break; + case CommonTypes.MediaType.CDIREADY: + discType = "Compact Disc"; + discSubType = "CD-i Ready"; + + break; + case CommonTypes.MediaType.CDMIDI: + discType = "Compact Disc"; + discSubType = "CD+MIDI"; + + break; + case CommonTypes.MediaType.CDMO: + discType = "Compact Disc"; + discSubType = "CD-MO"; + + break; + case CommonTypes.MediaType.CDMRW: + discType = "Compact Disc"; + discSubType = "CD-MRW"; + + break; + case CommonTypes.MediaType.CDPLUS: + discType = "Compact Disc"; + discSubType = "CD+"; + + break; + case CommonTypes.MediaType.CDR: + discType = "Compact Disc"; + discSubType = "CD-R"; + + break; + case CommonTypes.MediaType.CDROM: + discType = "Compact Disc"; + discSubType = "CD-ROM"; + + break; + case CommonTypes.MediaType.CDROMXA: + discType = "Compact Disc"; + discSubType = "CD-ROM XA"; + + break; + case CommonTypes.MediaType.CDRW: + discType = "Compact Disc"; + discSubType = "CD-RW"; + + break; + case CommonTypes.MediaType.CDV: + discType = "Compact Disc"; + discSubType = "CD-Video"; + + break; + case CommonTypes.MediaType.DDCD: + discType = "DDCD"; + discSubType = "DDCD"; + + break; + case CommonTypes.MediaType.DDCDR: + discType = "DDCD"; + discSubType = "DDCD-R"; + + break; + case CommonTypes.MediaType.DDCDRW: + discType = "DDCD"; + discSubType = "DDCD-RW"; + + break; + case CommonTypes.MediaType.DTSCD: + discType = "Compact Disc"; + discSubType = "DTS CD"; + + break; + case CommonTypes.MediaType.DVDDownload: + discType = "DVD"; + discSubType = "DVD-Download"; + + break; + case CommonTypes.MediaType.DVDPR: + discType = "DVD"; + discSubType = "DVD+R"; + + break; + case CommonTypes.MediaType.DVDPRDL: + discType = "DVD"; + discSubType = "DVD+R DL"; + + break; + case CommonTypes.MediaType.DVDPRW: + discType = "DVD"; + discSubType = "DVD+RW"; + + break; + case CommonTypes.MediaType.DVDPRWDL: + discType = "DVD"; + discSubType = "DVD+RW DL"; + + break; + case CommonTypes.MediaType.DVDR: + discType = "DVD"; + discSubType = "DVD-R"; + + break; + case CommonTypes.MediaType.DVDRAM: + discType = "DVD"; + discSubType = "DVD-RAM"; + + break; + case CommonTypes.MediaType.DVDRDL: + discType = "DVD"; + discSubType = "DVD-R DL"; + + break; + case CommonTypes.MediaType.DVDROM: + discType = "DVD"; + discSubType = "DVD-ROM"; + + break; + case CommonTypes.MediaType.DVDRW: + discType = "DVD"; + discSubType = "DVD-RW"; + + break; + case CommonTypes.MediaType.DVDRWDL: + discType = "DVD"; + discSubType = "DVD-RW DL"; + + break; + case CommonTypes.MediaType.EVD: + discType = "EVD"; + discSubType = "EVD"; + + break; + case CommonTypes.MediaType.FDDVD: + discType = "FDDVD"; + discSubType = "FDDVD"; + + break; + case CommonTypes.MediaType.FVD: + discType = "FVD"; + discSubType = "FVD"; + + break; + case CommonTypes.MediaType.GDR: + discType = "GD"; + discSubType = "GD-R"; + + break; + case CommonTypes.MediaType.GDROM: + discType = "GD"; + discSubType = "GD-ROM"; + + break; + case CommonTypes.MediaType.GOD: + discType = "DVD"; + discSubType = "GameCube Game Disc"; + + break; + case CommonTypes.MediaType.WOD: + discType = "DVD"; + discSubType = "Wii Optical Disc"; + + break; + case CommonTypes.MediaType.WUOD: + discType = "Blu-ray"; + discSubType = "Wii U Optical Disc"; + + break; + case CommonTypes.MediaType.HDDVDR: + discType = "HD DVD"; + discSubType = "HD DVD-R"; + + break; + case CommonTypes.MediaType.HDDVDRAM: + discType = "HD DVD"; + discSubType = "HD DVD-RAM"; + + break; + case CommonTypes.MediaType.HDDVDRDL: + discType = "HD DVD"; + discSubType = "HD DVD-R DL"; + + break; + case CommonTypes.MediaType.HDDVDROM: + discType = "HD DVD"; + discSubType = "HD DVD-ROM"; + + break; + case CommonTypes.MediaType.HDDVDRW: + discType = "HD DVD"; + discSubType = "HD DVD-RW"; + + break; + case CommonTypes.MediaType.HDDVDRWDL: + discType = "HD DVD"; + discSubType = "HD DVD-RW DL"; + + break; + case CommonTypes.MediaType.HDVMD: + discType = "HD VMD"; + discSubType = "HD VMD"; + + break; + case CommonTypes.MediaType.HiMD: + discType = "MiniDisc"; + discSubType = "Hi-MD"; + + break; + case CommonTypes.MediaType.HVD: + discType = "HVD"; + discSubType = "HVD"; + + break; + case CommonTypes.MediaType.LD: + discType = "LaserDisc"; + discSubType = "LaserDisc"; + + break; + case CommonTypes.MediaType.CRVdisc: + discType = "CRVdisc"; + discSubType = "CRVdisc"; + + break; + case CommonTypes.MediaType.LDROM: + discType = "LaserDisc"; + discSubType = "LD-ROM"; + + break; + case CommonTypes.MediaType.LVROM: + discType = "LaserDisc"; + discSubType = "LV-ROM"; + + break; + case CommonTypes.MediaType.MegaLD: + discType = "LaserDisc"; + discSubType = "MegaLD"; + + break; + case CommonTypes.MediaType.MD: + discType = "MiniDisc"; + discSubType = "MiniDisc"; + + break; + case CommonTypes.MediaType.MD60: + discType = "MiniDisc"; + discSubType = "MiniDisc (60 minute)"; + + break; + case CommonTypes.MediaType.MD74: + discType = "MiniDisc"; + discSubType = "MiniDisc (74 minute)"; + + break; + case CommonTypes.MediaType.MD80: + discType = "MiniDisc"; + discSubType = "MiniDisc (80 minute)"; + + break; + case CommonTypes.MediaType.MEGACD: + discType = "Compact Disc"; + discSubType = "Sega Mega CD"; + + break; + case CommonTypes.MediaType.PCD: + discType = "Compact Disc"; + discSubType = "Photo CD"; + + break; + case CommonTypes.MediaType.PlayStationMemoryCard: + discType = "PlayStation Memory Card"; + discSubType = "PlayStation Memory Card"; + + break; + case CommonTypes.MediaType.PlayStationMemoryCard2: + discType = "PlayStation Memory Card"; + discSubType = "PlayStation 2 Memory Card"; + + break; + case CommonTypes.MediaType.PS1CD: + discType = "Compact Disc"; + discSubType = "PlayStation Game Disc"; + + break; + case CommonTypes.MediaType.PS2CD: + discType = "Compact Disc"; + discSubType = "PlayStation 2 Game Disc"; + + break; + case CommonTypes.MediaType.PS2DVD: + discType = "DVD"; + discSubType = "PlayStation 2 Game Disc"; + + break; + case CommonTypes.MediaType.PS3BD: + discType = "Blu-ray"; + discSubType = "PlayStation 3 Game Disc"; + + break; + case CommonTypes.MediaType.PS3DVD: + discType = "DVD"; + discSubType = "PlayStation 3 Game Disc"; + + break; + case CommonTypes.MediaType.PS4BD: + discType = "Blu-ray"; + discSubType = "PlayStation 4 Game Disc"; + + break; + case CommonTypes.MediaType.PS5BD: + discType = "Blu-ray"; + discSubType = "PlayStation 5 Game Disc"; + + break; + case CommonTypes.MediaType.SACD: + discType = "SACD"; + discSubType = "Super Audio CD"; + + break; + case CommonTypes.MediaType.SegaCard: + discType = "Sega Card"; + discSubType = "Sega Card"; + + break; + case CommonTypes.MediaType.SATURNCD: + discType = "Compact Disc"; + discSubType = "Sega Saturn CD"; + + break; + case CommonTypes.MediaType.SVCD: + discType = "Compact Disc"; + discSubType = "Super Video CD"; + + break; + case CommonTypes.MediaType.CVD: + discType = "Compact Disc"; + discSubType = "China Video Disc"; + + break; + case CommonTypes.MediaType.SVOD: + discType = "SVOD"; + discSubType = "SVOD"; + + break; + case CommonTypes.MediaType.UDO: + discType = "UDO"; + discSubType = "UDO"; + + break; + case CommonTypes.MediaType.UMD: + discType = "UMD"; + discSubType = "Universal Media Disc"; + + break; + case CommonTypes.MediaType.VCD: + discType = "Compact Disc"; + discSubType = "Video CD"; + + break; + case CommonTypes.MediaType.Nuon: + discType = "DVD"; + discSubType = "Nuon"; + + break; + case CommonTypes.MediaType.XGD: + discType = "DVD"; + discSubType = "Xbox Game Disc (XGD)"; + + break; + case CommonTypes.MediaType.XGD2: + discType = "DVD"; + discSubType = "Xbox 360 Game Disc (XGD2)"; + + break; + case CommonTypes.MediaType.XGD3: + discType = "DVD"; + discSubType = "Xbox 360 Game Disc (XGD3)"; + + break; + case CommonTypes.MediaType.XGD4: + discType = "Blu-ray"; + discSubType = "Xbox One Game Disc (XGD4)"; + + break; + case CommonTypes.MediaType.FMTOWNS: + discType = "Compact Disc"; + discSubType = "FM-Towns"; + + break; + case CommonTypes.MediaType.Apple32SS: + discType = "5.25\" floppy"; + discSubType = "Apple DOS 3.2"; + + break; + case CommonTypes.MediaType.Apple32DS: + discType = "5.25\" floppy"; + discSubType = "Apple DOS 3.2 (double-sided)"; + + break; + case CommonTypes.MediaType.Apple33SS: + discType = "5.25\" floppy"; + discSubType = "Apple DOS 3.3"; + + break; + case CommonTypes.MediaType.Apple33DS: + discType = "5.25\" floppy"; + discSubType = "Apple DOS 3.3 (double-sided)"; + + break; + case CommonTypes.MediaType.AppleSonySS: + discType = "3.5\" floppy"; + discSubType = "Apple 400K"; + + break; + case CommonTypes.MediaType.AppleSonyDS: + discType = "3.5\" floppy"; + discSubType = "Apple 800K"; + + break; + case CommonTypes.MediaType.AppleFileWare: + discType = "5.25\" floppy"; + discSubType = "Apple FileWare"; + + break; + case CommonTypes.MediaType.RX50: + discType = "5.25\" floppy"; + discSubType = "DEC RX50"; + + break; + case CommonTypes.MediaType.DOS_525_SS_DD_8: + discType = "5.25\" floppy"; + discSubType = "IBM double-density, single-sided, 8 sectors"; + + break; + case CommonTypes.MediaType.DOS_525_SS_DD_9: + discType = "5.25\" floppy"; + discSubType = "IBM double-density, single-sided, 9 sectors"; + + break; + case CommonTypes.MediaType.DOS_525_DS_DD_8: + discType = "5.25\" floppy"; + discSubType = "IBM double-density, double-sided, 8 sectors"; + + break; + case CommonTypes.MediaType.DOS_525_DS_DD_9: + discType = "5.25\" floppy"; + discSubType = "IBM double-density, double-sided, 9 sectors"; + + break; + case CommonTypes.MediaType.DOS_525_HD: + discType = "5.25\" floppy"; + discSubType = "IBM high-density"; + + break; + case CommonTypes.MediaType.DOS_35_SS_DD_8: + discType = "3.5\" floppy"; + discSubType = "IBM double-density, single-sided, 8 sectors"; + + break; + case CommonTypes.MediaType.DOS_35_SS_DD_9: + discType = "3.5\" floppy"; + discSubType = "IBM double-density, single-sided, 9 sectors"; + + break; + case CommonTypes.MediaType.DOS_35_DS_DD_8: + discType = "3.5\" floppy"; + discSubType = "IBM double-density, double-sided, 8 sectors"; + + break; + case CommonTypes.MediaType.DOS_35_DS_DD_9: + discType = "3.5\" floppy"; + discSubType = "IBM double-density, double-sided, 9 sectors"; + + break; + case CommonTypes.MediaType.DOS_35_HD: + discType = "3.5\" floppy"; + discSubType = "IBM high-density"; + + break; + case CommonTypes.MediaType.DOS_35_ED: + discType = "3.5\" floppy"; + discSubType = "IBM extra-density"; + + break; + case CommonTypes.MediaType.Apricot_35: + discType = "3.5\" floppy"; + discSubType = "Apricot double-density, single-sided, 70 tracks"; + + break; + case CommonTypes.MediaType.DMF: + discType = "3.5\" floppy"; + discSubType = "Microsoft DMF"; + + break; + case CommonTypes.MediaType.DMF_82: + discType = "3.5\" floppy"; + discSubType = "Microsoft DMF (82-track)"; + + break; + case CommonTypes.MediaType.XDF_35: + discType = "3.5\" floppy"; + discSubType = "IBM XDF"; + + break; + case CommonTypes.MediaType.XDF_525: + discType = "5.25\" floppy"; + discSubType = "IBM XDF"; + + break; + case CommonTypes.MediaType.IBM23FD: + discType = "8\" floppy"; + discSubType = "IBM 23FD"; + + break; + case CommonTypes.MediaType.IBM33FD_128: + discType = "8\" floppy"; + discSubType = "IBM 33FD (128 bytes/sector)"; + + break; + case CommonTypes.MediaType.IBM33FD_256: + discType = "8\" floppy"; + discSubType = "IBM 33FD (256 bytes/sector)"; + + break; + case CommonTypes.MediaType.IBM33FD_512: + discType = "8\" floppy"; + discSubType = "IBM 33FD (512 bytes/sector)"; + + break; + case CommonTypes.MediaType.IBM43FD_128: + discType = "8\" floppy"; + discSubType = "IBM 43FD (128 bytes/sector)"; + + break; + case CommonTypes.MediaType.IBM43FD_256: + discType = "8\" floppy"; + discSubType = "IBM 43FD (256 bytes/sector)"; + + break; + case CommonTypes.MediaType.IBM53FD_256: + discType = "8\" floppy"; + discSubType = "IBM 53FD (256 bytes/sector)"; + + break; + case CommonTypes.MediaType.IBM53FD_512: + discType = "8\" floppy"; + discSubType = "IBM 53FD (512 bytes/sector)"; + + break; + case CommonTypes.MediaType.IBM53FD_1024: + discType = "8\" floppy"; + discSubType = "IBM 53FD (1024 bytes/sector)"; + + break; + case CommonTypes.MediaType.RX01: + discType = "8\" floppy"; + discSubType = "DEC RX-01"; + + break; + case CommonTypes.MediaType.RX02: + discType = "8\" floppy"; + discSubType = "DEC RX-02"; + + break; + case CommonTypes.MediaType.RX03: + discType = "8\" floppy"; + discSubType = "DEC RX-03"; + + break; + case CommonTypes.MediaType.ACORN_525_SS_SD_40: + discType = "5.25\" floppy"; + discSubType = "BBC Micro 100K"; + + break; + case CommonTypes.MediaType.ACORN_525_SS_SD_80: + discType = "5.25\" floppy"; + discSubType = "BBC Micro 200K"; + + break; + case CommonTypes.MediaType.ACORN_525_SS_DD_40: + discType = "5.25\" floppy"; + discSubType = "Acorn S"; + + break; + case CommonTypes.MediaType.ACORN_525_SS_DD_80: + discType = "5.25\" floppy"; + discSubType = "Acorn M"; + + break; + case CommonTypes.MediaType.ACORN_525_DS_DD: + discType = "5.25\" floppy"; + discSubType = "Acorn L"; + + break; + case CommonTypes.MediaType.ACORN_35_DS_DD: + discType = "3.5\" floppy"; + discSubType = "Acorn Archimedes"; + + break; + case CommonTypes.MediaType.ACORN_35_DS_HD: + discType = "3.5\" floppy"; + discSubType = "Acorn Archimedes high-density"; + + break; + case CommonTypes.MediaType.ATARI_525_SD: + discType = "5.25\" floppy"; + discSubType = "Atari single-density"; + + break; + case CommonTypes.MediaType.ATARI_525_ED: + discType = "5.25\" floppy"; + discSubType = "Atari enhanced-density"; + + break; + case CommonTypes.MediaType.ATARI_525_DD: + discType = "5.25\" floppy"; + discSubType = "Atari double-density"; + + break; + case CommonTypes.MediaType.ATARI_35_SS_DD: + discType = "3.5\" floppy"; + discSubType = "Atari ST double-density, single-sided, 10 sectors"; + + break; + case CommonTypes.MediaType.ATARI_35_DS_DD: + discType = "3.5\" floppy"; + discSubType = "Atari ST double-density, double-sided, 10 sectors"; + + break; + case CommonTypes.MediaType.ATARI_35_SS_DD_11: + discType = "3.5\" floppy"; + discSubType = "Atari ST double-density, single-sided, 11 sectors"; + + break; + case CommonTypes.MediaType.ATARI_35_DS_DD_11: + discType = "3.5\" floppy"; + discSubType = "Atari ST double-density, double-sided, 11 sectors"; + + break; + case CommonTypes.MediaType.CBM_1540: + case CommonTypes.MediaType.CBM_1540_Ext: + discType = "5.25\" floppy"; + discSubType = "Commodore 1540/1541"; + + break; + case CommonTypes.MediaType.CBM_1571: + discType = "5.25\" floppy"; + discSubType = "Commodore 1571"; + + break; + case CommonTypes.MediaType.CBM_35_DD: + discType = "3.5\" floppy"; + discSubType = "Commodore 1581"; + + break; + case CommonTypes.MediaType.CBM_AMIGA_35_DD: + discType = "3.5\" floppy"; + discSubType = "Amiga double-density"; + + break; + case CommonTypes.MediaType.CBM_AMIGA_35_HD: + discType = "3.5\" floppy"; + discSubType = "Amiga high-density"; + + break; + case CommonTypes.MediaType.NEC_8_SD: + discType = "8\" floppy"; + discSubType = "NEC single-sided"; + + break; + case CommonTypes.MediaType.NEC_8_DD: + discType = "8\" floppy"; + discSubType = "NEC double-sided"; + + break; + case CommonTypes.MediaType.NEC_525_SS: + discType = "5.25\" floppy"; + discSubType = "NEC single-sided"; + + break; + case CommonTypes.MediaType.NEC_525_HD: + discType = "5.25\" floppy"; + discSubType = "NEC high-density"; + + break; + case CommonTypes.MediaType.NEC_35_HD_8: + discType = "3.5\" floppy"; + discSubType = "NEC high-density"; + + break; + case CommonTypes.MediaType.NEC_35_HD_15: + discType = "3.5\" floppy"; + discSubType = "NEC high-density"; + + break; + case CommonTypes.MediaType.NEC_35_TD: + discType = "3.5\" floppy"; + discSubType = "NEC triple-density"; + + break; + case CommonTypes.MediaType.SHARP_525_9: + discType = "5.25\" floppy"; + discSubType = "Sharp (9 sectors per track)"; + + break; + case CommonTypes.MediaType.SHARP_35_9: + discType = "3.5\" floppy"; + discSubType = "Sharp (9 sectors per track)"; + + break; + case CommonTypes.MediaType.ECMA_54: + discType = "8\" floppy"; + discSubType = "ECMA-54"; + + break; + case CommonTypes.MediaType.ECMA_59: + discType = "8\" floppy"; + discSubType = "ECMA-59"; + + break; + case CommonTypes.MediaType.ECMA_69_8: + case CommonTypes.MediaType.ECMA_69_15: + case CommonTypes.MediaType.ECMA_69_26: + discType = "8\" floppy"; + discSubType = "ECMA-69"; + + break; + case CommonTypes.MediaType.ECMA_66: + discType = "5.25\" floppy"; + discSubType = "ECMA-66"; + + break; + case CommonTypes.MediaType.ECMA_70: + discType = "5.25\" floppy"; + discSubType = "ECMA-70"; + + break; + case CommonTypes.MediaType.ECMA_78: + case CommonTypes.MediaType.ECMA_78_2: + discType = "5.25\" floppy"; + discSubType = "ECMA-78"; + + break; + case CommonTypes.MediaType.ECMA_99_8: + case CommonTypes.MediaType.ECMA_99_15: + case CommonTypes.MediaType.ECMA_99_26: + discType = "5.25\" floppy"; + discSubType = "ECMA-99"; + + break; + case CommonTypes.MediaType.FDFORMAT_525_DD: + discType = "5.25\" floppy"; + discSubType = "FDFORMAT double-density"; + + break; + case CommonTypes.MediaType.FDFORMAT_525_HD: + discType = "5.25\" floppy"; + discSubType = "FDFORMAT high-density"; + + break; + case CommonTypes.MediaType.FDFORMAT_35_DD: + discType = "3.5\" floppy"; + discSubType = "FDFORMAT double-density"; + + break; + case CommonTypes.MediaType.FDFORMAT_35_HD: + discType = "3.5\" floppy"; + discSubType = "FDFORMAT high-density"; + + break; + case CommonTypes.MediaType.ECMA_260: + case CommonTypes.MediaType.ECMA_260_Double: + discType = "356mm magneto-optical"; + discSubType = "ECMA-260 / ISO 15898"; + + break; + case CommonTypes.MediaType.ECMA_183_512: + case CommonTypes.MediaType.ECMA_183: + discType = "5.25\" magneto-optical"; + discSubType = "ECMA-183"; + + break; + case CommonTypes.MediaType.ISO_10089: + case CommonTypes.MediaType.ISO_10089_512: + discType = "5.25\" magneto-optical"; + discSubType = "ISO 10089"; + + break; + case CommonTypes.MediaType.ECMA_184_512: + case CommonTypes.MediaType.ECMA_184: + discType = "5.25\" magneto-optical"; + discSubType = "ECMA-184"; + + break; + case CommonTypes.MediaType.ECMA_154: + discType = "3.5\" magneto-optical"; + discSubType = "ECMA-154"; + + break; + case CommonTypes.MediaType.ECMA_201: + case CommonTypes.MediaType.ECMA_201_ROM: + discType = "3.5\" magneto-optical"; + discSubType = "ECMA-201"; + + break; + case CommonTypes.MediaType.ISO_15041_512: + discType = "3.5\" magneto-optical"; + discSubType = "ISO 15041"; + + break; + case CommonTypes.MediaType.FlashDrive: + discType = "USB flash drive"; + discSubType = "USB flash drive"; + + break; + case CommonTypes.MediaType.SuperCDROM2: + discType = "Compact Disc"; + discSubType = "Super CD-ROM²"; + + break; + case CommonTypes.MediaType.LDROM2: + discType = "LaserDisc"; + discSubType = "LD-ROM²"; + + break; + case CommonTypes.MediaType.JaguarCD: + discType = "Compact Disc"; + discSubType = "Atari Jaguar CD"; + + break; + case CommonTypes.MediaType.MilCD: + discType = "Compact Disc"; + discSubType = "Sega MilCD"; + + break; + case CommonTypes.MediaType.ThreeDO: + discType = "Compact Disc"; + discSubType = "3DO"; + + break; + case CommonTypes.MediaType.PCFX: + discType = "Compact Disc"; + discSubType = "PC-FX"; + + break; + case CommonTypes.MediaType.NeoGeoCD: + discType = "Compact Disc"; + discSubType = "NEO-GEO CD"; + + break; + case CommonTypes.MediaType.CDTV: + discType = "Compact Disc"; + discSubType = "Commodore CDTV"; + + break; + case CommonTypes.MediaType.CD32: + discType = "Compact Disc"; + discSubType = "Amiga CD32"; + + break; + case CommonTypes.MediaType.Playdia: + discType = "Compact Disc"; + discSubType = "Bandai Playdia"; + + break; + case CommonTypes.MediaType.Pippin: + discType = "Compact Disc"; + discSubType = "Apple Pippin"; + + break; + case CommonTypes.MediaType.ZIP100: + discType = "Iomega ZIP"; + discSubType = "Iomega ZIP100"; + + break; + case CommonTypes.MediaType.ZIP250: + discType = "Iomega ZIP"; + discSubType = "Iomega ZIP250"; + + break; + case CommonTypes.MediaType.ZIP750: + discType = "Iomega ZIP"; + discSubType = "Iomega ZIP750"; + + break; + case CommonTypes.MediaType.AppleProfile: + discType = "Hard Disk Drive"; + discSubType = "Apple Profile"; + + break; + case CommonTypes.MediaType.AppleWidget: + discType = "Hard Disk Drive"; + discSubType = "Apple Widget"; + + break; + case CommonTypes.MediaType.AppleHD20: + discType = "Hard Disk Drive"; + discSubType = "Apple HD20"; + + break; + case CommonTypes.MediaType.PriamDataTower: + discType = "Hard Disk Drive"; + discSubType = "Priam DataTower"; + + break; + case CommonTypes.MediaType.DDS1: + discType = "Digital Data Storage"; + discSubType = "DDS"; + + break; + case CommonTypes.MediaType.DDS2: + discType = "Digital Data Storage"; + discSubType = "DDS-2"; + + break; + case CommonTypes.MediaType.DDS3: + discType = "Digital Data Storage"; + discSubType = "DDS-3"; + + break; + case CommonTypes.MediaType.DDS4: + discType = "Digital Data Storage"; + discSubType = "DDS-4"; + + break; + case CommonTypes.MediaType.PocketZip: + discType = "Iomega PocketZip"; + discSubType = "Iomega PocketZip"; + + break; + case CommonTypes.MediaType.CompactFloppy: + discType = "3\" floppy"; + discSubType = "Compact Floppy"; + + break; + case CommonTypes.MediaType.GENERIC_HDD: + discType = "Hard Disk Drive"; + discSubType = "Unknown"; + + break; + case CommonTypes.MediaType.MDData: + discType = "MiniDisc"; + discSubType = "MD-DATA"; + + break; + case CommonTypes.MediaType.MDData2: + discType = "MiniDisc"; + discSubType = "MD-DATA2"; + + break; + case CommonTypes.MediaType.UDO2: + discType = "UDO"; + discSubType = "UDO2"; + + break; + case CommonTypes.MediaType.UDO2_WORM: + discType = "UDO"; + discSubType = "UDO2 (WORM)"; + + break; + case CommonTypes.MediaType.ADR30: + discType = "Advanced Digital Recording"; + discSubType = "ADR 30"; + + break; + case CommonTypes.MediaType.ADR50: + discType = "Advanced Digital Recording"; + discSubType = "ADR 50"; + + break; + case CommonTypes.MediaType.ADR260: + discType = "Advanced Digital Recording"; + discSubType = "ADR 2.60"; + + break; + case CommonTypes.MediaType.ADR2120: + discType = "Advanced Digital Recording"; + discSubType = "ADR 2.120"; + + break; + case CommonTypes.MediaType.AIT1: + discType = "Advanced Intelligent Tape"; + discSubType = "AIT-1"; + + break; + case CommonTypes.MediaType.AIT1Turbo: + discType = "Advanced Intelligent Tape"; + discSubType = "AIT-1 Turbo"; + + break; + case CommonTypes.MediaType.AIT2: + discType = "Advanced Intelligent Tape"; + discSubType = "AIT-2"; + + break; + case CommonTypes.MediaType.AIT2Turbo: + discType = "Advanced Intelligent Tape"; + discSubType = "AIT-2 Turbo"; + + break; + case CommonTypes.MediaType.AIT3: + discType = "Advanced Intelligent Tape"; + discSubType = "AIT-3"; + + break; + case CommonTypes.MediaType.AIT3Ex: + discType = "Advanced Intelligent Tape"; + discSubType = "AIT-3Ex"; + + break; + case CommonTypes.MediaType.AIT3Turbo: + discType = "Advanced Intelligent Tape"; + discSubType = "AIT-3 Turbo"; + + break; + case CommonTypes.MediaType.AIT4: + discType = "Advanced Intelligent Tape"; + discSubType = "AIT-4"; + + break; + case CommonTypes.MediaType.AIT5: + discType = "Advanced Intelligent Tape"; + discSubType = "AIT-5"; + + break; + case CommonTypes.MediaType.AITETurbo: + discType = "Advanced Intelligent Tape"; + discSubType = "AIT-E Turbo"; + + break; + case CommonTypes.MediaType.SAIT1: + discType = "Super Advanced Intelligent Tape"; + discSubType = "SAIT-1"; + + break; + case CommonTypes.MediaType.SAIT2: + discType = "Super Advanced Intelligent Tape"; + discSubType = "SAIT-2"; + + break; + case CommonTypes.MediaType.Bernoulli: + case CommonTypes.MediaType.Bernoulli10: + discType = "Iomega Bernoulli Box"; + discSubType = "Iomega Bernoulli Box 10Mb"; + + break; + case CommonTypes.MediaType.Bernoulli20: + discType = "Iomega Bernoulli Box"; + discSubType = "Iomega Bernoulli Box 20Mb"; + + break; + case CommonTypes.MediaType.BernoulliBox2_20: + case CommonTypes.MediaType.Bernoulli2: + discType = "Iomega Bernoulli Box II"; + discSubType = "Iomega Bernoulli Box II 20Mb"; + + break; + case CommonTypes.MediaType.Bernoulli35: + discType = "Iomega Bernoulli Box II"; + discSubType = "Iomega Bernoulli Box II 35Mb"; + + break; + case CommonTypes.MediaType.Bernoulli44: + discType = "Iomega Bernoulli Box II"; + discSubType = "Iomega Bernoulli Box II 44Mb"; + + break; + case CommonTypes.MediaType.Bernoulli65: + discType = "Iomega Bernoulli Box II"; + discSubType = "Iomega Bernoulli Box II 65Mb"; + + break; + case CommonTypes.MediaType.Bernoulli90: + discType = "Iomega Bernoulli Box II"; + discSubType = "Iomega Bernoulli Box II 90Mb"; + + break; + case CommonTypes.MediaType.Bernoulli105: + discType = "Iomega Bernoulli Box II"; + discSubType = "Iomega Bernoulli Box II 105Mb"; + + break; + case CommonTypes.MediaType.Bernoulli150: + discType = "Iomega Bernoulli Box II"; + discSubType = "Iomega Bernoulli Box II 150Mb"; + + break; + case CommonTypes.MediaType.Bernoulli230: + discType = "Iomega Bernoulli Box II"; + discSubType = "Iomega Bernoulli Box II 230Mb"; + + break; + case CommonTypes.MediaType.Ditto: + discType = "Iomega Ditto"; + discSubType = "Iomega Ditto"; + + break; + case CommonTypes.MediaType.DittoMax: + discType = "Iomega Ditto"; + discSubType = "Iomega Ditto Max"; + + break; + case CommonTypes.MediaType.Jaz: + discType = "Iomega Jaz"; + discSubType = "Iomega Jaz 1GB"; + + break; + case CommonTypes.MediaType.Jaz2: + discType = "Iomega Jaz"; + discSubType = "Iomega Jaz 2GB"; + + break; + case CommonTypes.MediaType.REV35: + discType = "Iomega REV"; + discSubType = "Iomega REV-35"; + + break; + case CommonTypes.MediaType.REV70: + discType = "Iomega REV"; + discSubType = "Iomega REV-70"; + + break; + case CommonTypes.MediaType.REV120: + discType = "Iomega REV"; + discSubType = "Iomega REV-120"; + + break; + case CommonTypes.MediaType.CompactFlash: + discType = "Compact Flash"; + discSubType = "Compact Flash"; + + break; + case CommonTypes.MediaType.CompactFlashType2: + discType = "Compact Flash"; + discSubType = "Compact Flash Type 2"; + + break; + case CommonTypes.MediaType.CFast: + discType = "Compact Flash"; + discSubType = "CFast"; + + break; + case CommonTypes.MediaType.DigitalAudioTape: + discType = "Digital Audio Tape"; + discSubType = "Digital Audio Tape"; + + break; + case CommonTypes.MediaType.DAT72: + discType = "Digital Data Storage"; + discSubType = "DAT-72"; + + break; + case CommonTypes.MediaType.DAT160: + discType = "Digital Data Storage"; + discSubType = "DAT-160"; + + break; + case CommonTypes.MediaType.DAT320: + discType = "Digital Data Storage"; + discSubType = "DAT-320"; + + break; + case CommonTypes.MediaType.DECtapeII: + discType = "DECtape"; + discSubType = "DECtape II"; + + break; + case CommonTypes.MediaType.CompactTapeI: + discType = "CompacTape"; + discSubType = "CompacTape"; + + break; + case CommonTypes.MediaType.CompactTapeII: + discType = "CompacTape"; + discSubType = "CompacTape II"; + + break; + case CommonTypes.MediaType.DLTtapeIII: + discType = "Digital Linear Tape"; + discSubType = "DLTtape III"; + + break; + case CommonTypes.MediaType.DLTtapeIIIxt: + discType = "Digital Linear Tape"; + discSubType = "DLTtape IIIXT"; + + break; + case CommonTypes.MediaType.DLTtapeIV: + discType = "Digital Linear Tape"; + discSubType = "DLTtape IV"; + + break; + case CommonTypes.MediaType.DLTtapeS4: + discType = "Digital Linear Tape"; + discSubType = "DLTtape S4"; + + break; + case CommonTypes.MediaType.SDLT1: + discType = "Super Digital Linear Tape"; + discSubType = "SDLTtape I"; + + break; + case CommonTypes.MediaType.SDLT2: + discType = "Super Digital Linear Tape"; + discSubType = "SDLTtape II"; + + break; + case CommonTypes.MediaType.VStapeI: + discType = "Digital Linear Tape"; + discSubType = "DLTtape VS1"; + + break; + case CommonTypes.MediaType.Data8: + discType = "Data8"; + discSubType = "Data8"; + + break; + case CommonTypes.MediaType.MiniDV: + discType = "DV tape"; + discSubType = "MiniDV"; + + break; + case CommonTypes.MediaType.Exatape15m: + discType = "Exatape"; + discSubType = "Exatape (15m)"; + + break; + case CommonTypes.MediaType.Exatape22m: + discType = "Exatape"; + discSubType = "Exatape (22m)"; + + break; + case CommonTypes.MediaType.Exatape22mAME: + discType = "Exatape"; + discSubType = "Exatape (22m AME)"; + + break; + case CommonTypes.MediaType.Exatape28m: + discType = "Exatape"; + discSubType = "Exatape (28m)"; + + break; + case CommonTypes.MediaType.Exatape40m: + discType = "Exatape"; + discSubType = "Exatape (40m)"; + + break; + case CommonTypes.MediaType.Exatape45m: + discType = "Exatape"; + discSubType = "Exatape (45m)"; + + break; + case CommonTypes.MediaType.Exatape54m: + discType = "Exatape"; + discSubType = "Exatape (54m)"; + + break; + case CommonTypes.MediaType.Exatape75m: + discType = "Exatape"; + discSubType = "Exatape (75m)"; + + break; + case CommonTypes.MediaType.Exatape76m: + discType = "Exatape"; + discSubType = "Exatape (76m)"; + + break; + case CommonTypes.MediaType.Exatape80m: + discType = "Exatape"; + discSubType = "Exatape (80m)"; + + break; + case CommonTypes.MediaType.Exatape106m: + discType = "Exatape"; + discSubType = "Exatape (106m)"; + + break; + case CommonTypes.MediaType.Exatape112m: + discType = "Exatape"; + discSubType = "Exatape (112m)"; + + break; + case CommonTypes.MediaType.Exatape125m: + discType = "Exatape"; + discSubType = "Exatape (125m)"; + + break; + case CommonTypes.MediaType.Exatape150m: + discType = "Exatape"; + discSubType = "Exatape (150m)"; + + break; + case CommonTypes.MediaType.Exatape160mXL: + discType = "Exatape"; + discSubType = "Exatape XL (160m)"; + + break; + case CommonTypes.MediaType.Exatape170m: + discType = "Exatape"; + discSubType = "Exatape (170m)"; + + break; + case CommonTypes.MediaType.Exatape225m: + discType = "Exatape"; + discSubType = "Exatape (225m)"; + + break; + case CommonTypes.MediaType.EZ135: + discType = "3.5\" SyQuest cartridge"; + discSubType = "EZ135"; + + break; + case CommonTypes.MediaType.EZ230: + discType = "3.5\" SyQuest cartridge"; + discSubType = "EZ230"; + + break; + case CommonTypes.MediaType.Quest: + discType = "3.5\" SyQuest cartridge"; + discSubType = "Quest"; + + break; + case CommonTypes.MediaType.SparQ: + discType = "3.5\" SyQuest cartridge"; + discSubType = "SparQ"; + + break; + case CommonTypes.MediaType.SQ100: + discType = "3.9\" SyQuest cartridge"; + discSubType = "SQ100"; + + break; + case CommonTypes.MediaType.SQ200: + discType = "3.9\" SyQuest cartridge"; + discSubType = "SQ200"; + + break; + case CommonTypes.MediaType.SQ300: + discType = "3.9\" SyQuest cartridge"; + discSubType = "SQ300"; + + break; + case CommonTypes.MediaType.SQ310: + discType = "3.5\" SyQuest cartridge"; + discSubType = "SQ310"; + + break; + case CommonTypes.MediaType.SQ327: + discType = "3.5\" SyQuest cartridge"; + discSubType = "SQ327"; + + break; + case CommonTypes.MediaType.SQ400: + discType = "5.25\" SyQuest cartridge"; + discSubType = "SQ400"; + + break; + case CommonTypes.MediaType.SQ800: + discType = "5.25\" SyQuest cartridge"; + discSubType = "SQ800"; + + break; + case CommonTypes.MediaType.SQ1500: + discType = "3.5\" SyQuest cartridge"; + discSubType = "SQ1500"; + + break; + case CommonTypes.MediaType.SQ2000: + discType = "5.25\" SyQuest cartridge"; + discSubType = "SQ2000"; + + break; + case CommonTypes.MediaType.SyJet: + discType = "3.5\" SyQuest cartridge"; + discSubType = "SyJet"; + + break; + case CommonTypes.MediaType.LTO: + discType = "Linear Tape-Open"; + discSubType = "LTO"; + + break; + case CommonTypes.MediaType.LTO2: + discType = "Linear Tape-Open"; + discSubType = "LTO-2"; + + break; + case CommonTypes.MediaType.LTO3: + discType = "Linear Tape-Open"; + discSubType = "LTO-3"; + + break; + case CommonTypes.MediaType.LTO3WORM: + discType = "Linear Tape-Open"; + discSubType = "LTO-3 (WORM)"; + + break; + case CommonTypes.MediaType.LTO4: + discType = "Linear Tape-Open"; + discSubType = "LTO-4"; + + break; + case CommonTypes.MediaType.LTO4WORM: + discType = "Linear Tape-Open"; + discSubType = "LTO-4 (WORM)"; + + break; + case CommonTypes.MediaType.LTO5: + discType = "Linear Tape-Open"; + discSubType = "LTO-5"; + + break; + case CommonTypes.MediaType.LTO5WORM: + discType = "Linear Tape-Open"; + discSubType = "LTO-5 (WORM)"; + + break; + case CommonTypes.MediaType.LTO6: + discType = "Linear Tape-Open"; + discSubType = "LTO-6"; + + break; + case CommonTypes.MediaType.LTO6WORM: + discType = "Linear Tape-Open"; + discSubType = "LTO-6 (WORM)"; + + break; + case CommonTypes.MediaType.LTO7: + discType = "Linear Tape-Open"; + discSubType = "LTO-7"; + + break; + case CommonTypes.MediaType.LTO7WORM: + discType = "Linear Tape-Open"; + discSubType = "LTO-7 (WORM)"; + + break; + case CommonTypes.MediaType.MemoryStick: + discType = "Memory Stick"; + discSubType = "Memory Stick"; + + break; + case CommonTypes.MediaType.MemoryStickDuo: + discType = "Memory Stick"; + discSubType = "Memory Stick Duo"; + + break; + case CommonTypes.MediaType.MemoryStickMicro: + discType = "Memory Stick"; + discSubType = "Memory Stick Micro"; + + break; + case CommonTypes.MediaType.MemoryStickPro: + discType = "Memory Stick"; + discSubType = "Memory Stick Pro"; + + break; + case CommonTypes.MediaType.MemoryStickProDuo: + discType = "Memory Stick"; + discSubType = "Memory Stick PRO Duo"; + + break; + case CommonTypes.MediaType.SecureDigital: + discType = "Secure Digital"; + discSubType = "Secure Digital"; + + break; + case CommonTypes.MediaType.miniSD: + discType = "Secure Digital"; + discSubType = "miniSD"; + + break; + case CommonTypes.MediaType.microSD: + discType = "Secure Digital"; + discSubType = "microSD"; + + break; + case CommonTypes.MediaType.MMC: + discType = "MultiMediaCard"; + discSubType = "MultiMediaCard"; + + break; + case CommonTypes.MediaType.MMCmicro: + discType = "MultiMediaCard"; + discSubType = "MMCmicro"; + + break; + case CommonTypes.MediaType.RSMMC: + discType = "MultiMediaCard"; + discSubType = "Reduced-Size MultiMediaCard"; + + break; + case CommonTypes.MediaType.MMCplus: + discType = "MultiMediaCard"; + discSubType = "MMCplus"; + + break; + case CommonTypes.MediaType.MMCmobile: + discType = "MultiMediaCard"; + discSubType = "MMCmobile"; + + break; + case CommonTypes.MediaType.MLR1: + discType = "Scalable Linear Recording"; + discSubType = "MLR1"; + + break; + case CommonTypes.MediaType.MLR1SL: + discType = "Scalable Linear Recording"; + discSubType = "MLR1 SL"; + + break; + case CommonTypes.MediaType.MLR3: + discType = "Scalable Linear Recording"; + discSubType = "MLR3"; + + break; + case CommonTypes.MediaType.SLR1: + discType = "Scalable Linear Recording"; + discSubType = "SLR1"; + + break; + case CommonTypes.MediaType.SLR2: + discType = "Scalable Linear Recording"; + discSubType = "SLR2"; + + break; + case CommonTypes.MediaType.SLR3: + discType = "Scalable Linear Recording"; + discSubType = "SLR3"; + + break; + case CommonTypes.MediaType.SLR32: + discType = "Scalable Linear Recording"; + discSubType = "SLR32"; + + break; + case CommonTypes.MediaType.SLR32SL: + discType = "Scalable Linear Recording"; + discSubType = "SLR32 SL"; + + break; + case CommonTypes.MediaType.SLR4: + discType = "Scalable Linear Recording"; + discSubType = "SLR4"; + + break; + case CommonTypes.MediaType.SLR5: + discType = "Scalable Linear Recording"; + discSubType = "SLR5"; + + break; + case CommonTypes.MediaType.SLR5SL: + discType = "Scalable Linear Recording"; + discSubType = "SLR5 SL"; + + break; + case CommonTypes.MediaType.SLR6: + discType = "Scalable Linear Recording"; + discSubType = "SLR6"; + + break; + case CommonTypes.MediaType.SLRtape7: + discType = "Scalable Linear Recording"; + discSubType = "SLRtape7"; + + break; + case CommonTypes.MediaType.SLRtape7SL: + discType = "Scalable Linear Recording"; + discSubType = "SLRtape7 SL"; + + break; + case CommonTypes.MediaType.SLRtape24: + discType = "Scalable Linear Recording"; + discSubType = "SLRtape24"; + + break; + case CommonTypes.MediaType.SLRtape24SL: + discType = "Scalable Linear Recording"; + discSubType = "SLRtape24 SL"; + + break; + case CommonTypes.MediaType.SLRtape40: + discType = "Scalable Linear Recording"; + discSubType = "SLRtape40"; + + break; + case CommonTypes.MediaType.SLRtape50: + discType = "Scalable Linear Recording"; + discSubType = "SLRtape50"; + + break; + case CommonTypes.MediaType.SLRtape60: + discType = "Scalable Linear Recording"; + discSubType = "SLRtape60"; + + break; + case CommonTypes.MediaType.SLRtape75: + discType = "Scalable Linear Recording"; + discSubType = "SLRtape75"; + + break; + case CommonTypes.MediaType.SLRtape100: + discType = "Scalable Linear Recording"; + discSubType = "SLRtape100"; + + break; + case CommonTypes.MediaType.SLRtape140: + discType = "Scalable Linear Recording"; + discSubType = "SLRtape140"; + + break; + case CommonTypes.MediaType.QIC11: + discType = "Quarter-inch cartridge"; + discSubType = "QIC-11"; + + break; + case CommonTypes.MediaType.QIC24: + discType = "Quarter-inch cartridge"; + discSubType = "QIC-24"; + + break; + case CommonTypes.MediaType.QIC40: + discType = "Quarter-inch mini cartridge"; + discSubType = "QIC-40"; + + break; + case CommonTypes.MediaType.QIC80: + discType = "Quarter-inch mini cartridge"; + discSubType = "QIC-80"; + + break; + case CommonTypes.MediaType.QIC120: + discType = "Quarter-inch cartridge"; + discSubType = "QIC-120"; + + break; + case CommonTypes.MediaType.QIC150: + discType = "Quarter-inch cartridge"; + discSubType = "QIC-150"; + + break; + case CommonTypes.MediaType.QIC320: + discType = "Quarter-inch cartridge"; + discSubType = "QIC-320"; + + break; + case CommonTypes.MediaType.QIC525: + discType = "Quarter-inch cartridge"; + discSubType = "QIC-525"; + + break; + case CommonTypes.MediaType.QIC1350: + discType = "Quarter-inch cartridge"; + discSubType = "QIC-1350"; + + break; + case CommonTypes.MediaType.QIC3010: + discType = "Quarter-inch cartridge"; + discSubType = "QIC-3010"; + + break; + case CommonTypes.MediaType.QIC3020: + discType = "Quarter-inch cartridge"; + discSubType = "QIC-3020"; + + break; + case CommonTypes.MediaType.QIC3080: + discType = "Quarter-inch cartridge"; + discSubType = "QIC-3080"; + + break; + case CommonTypes.MediaType.QIC3095: + discType = "Quarter-inch cartridge"; + discSubType = "QIC-3095"; + + break; + case CommonTypes.MediaType.Travan: + discType = "Travan"; + discSubType = "TR-1"; + + break; + case CommonTypes.MediaType.Travan1Ex: + discType = "Travan"; + discSubType = "TR-1 Ex"; + + break; + case CommonTypes.MediaType.Travan3: + discType = "Travan"; + discSubType = "TR-3"; + + break; + case CommonTypes.MediaType.Travan3Ex: + discType = "Travan"; + discSubType = "TR-3 Ex"; + + break; + case CommonTypes.MediaType.Travan4: + discType = "Travan"; + discSubType = "TR-4"; + + break; + case CommonTypes.MediaType.Travan5: + discType = "Travan"; + discSubType = "TR-5"; + + break; + case CommonTypes.MediaType.Travan7: + discType = "Travan"; + discSubType = "TR-7"; + + break; + case CommonTypes.MediaType.VXA1: + discType = "VXA"; + discSubType = "VXA-1"; + + break; + case CommonTypes.MediaType.VXA2: + discType = "VXA"; + discSubType = "VXA-2"; + + break; + case CommonTypes.MediaType.VXA3: + discType = "VXA"; + discSubType = "VXA-3"; + + break; + case CommonTypes.MediaType.ECMA_153: + case CommonTypes.MediaType.ECMA_153_512: + discType = "5.25\" magneto-optical"; + discSubType = "ECMA-153"; + + break; + case CommonTypes.MediaType.ECMA_189: + discType = "300mm magneto optical"; + discSubType = "ECMA-189"; + + break; + case CommonTypes.MediaType.ECMA_190: + discType = "300mm magneto optical"; + discSubType = "ECMA-190"; + + break; + case CommonTypes.MediaType.ECMA_195: + case CommonTypes.MediaType.ECMA_195_512: + discType = "5.25\" magneto-optical"; + discSubType = "ECMA-195"; + + break; + case CommonTypes.MediaType.ECMA_223: + case CommonTypes.MediaType.ECMA_223_512: + discType = "3.5\" magneto-optical"; + discSubType = "ECMA-223"; + + break; + case CommonTypes.MediaType.ECMA_238: + discType = "5.25\" magneto-optical"; + discSubType = "ECMA-238"; + + break; + case CommonTypes.MediaType.ECMA_239: + discType = "3.5\" magneto-optical"; + discSubType = "ECMA-239"; + + break; + case CommonTypes.MediaType.ECMA_280: + discType = "5.25\" magneto-optical"; + discSubType = "ECMA-280"; + + break; + case CommonTypes.MediaType.ECMA_317: + discType = "300mm magneto optical"; + discSubType = "ECMA-317"; + + break; + case CommonTypes.MediaType.ECMA_322: + case CommonTypes.MediaType.ECMA_322_512: + case CommonTypes.MediaType.ECMA_322_1k: + case CommonTypes.MediaType.ECMA_322_2k: + discType = "5.25\" magneto-optical"; + discSubType = "ECMA-322 / ISO 22092"; + + break; + case CommonTypes.MediaType.ISO_15286: + case CommonTypes.MediaType.ISO_15286_1024: + case CommonTypes.MediaType.ISO_15286_512: + discType = "5.25\" magneto-optical"; + discSubType = "ISO-15286"; + + break; + case CommonTypes.MediaType.ISO_14517: + case CommonTypes.MediaType.ISO_14517_512: + discType = "5.25\" magneto-optical"; + discSubType = "ISO-14517"; + + break; + case CommonTypes.MediaType.GigaMo: + discType = "3.5\" magneto-optical"; + discSubType = "GIGAMO"; + + break; + case CommonTypes.MediaType.GigaMo2: + discType = "3.5\" magneto-optical"; + discSubType = "2.3GB GIGAMO"; + + break; + case CommonTypes.MediaType.UnknownMO: + discType = "Magneto-optical"; + discSubType = "Unknown"; + + break; + case CommonTypes.MediaType.Floptical: + discType = "Floptical"; + discSubType = "Floptical"; + + break; + case CommonTypes.MediaType.HiFD: + discType = "HiFD"; + discSubType = "HiFD"; + + break; + case CommonTypes.MediaType.LS120: + discType = "SuperDisk"; + discSubType = "LS-120"; + + break; + case CommonTypes.MediaType.LS240: + discType = "SuperDisk"; + discSubType = "LS-240"; + + break; + case CommonTypes.MediaType.FD32MB: + discType = "3.5\" floppy"; + discSubType = "FD32MB"; + + break; + case CommonTypes.MediaType.UHD144: + discType = "UHD144"; + discSubType = "UHD144"; + + break; + case CommonTypes.MediaType.VCDHD: + discType = "VCDHD"; + discSubType = "VCDHD"; + + break; + case CommonTypes.MediaType.HuCard: + discType = "HuCard"; + discSubType = "HuCard"; + + break; + case CommonTypes.MediaType.CompactCassette: + discType = "Compact Cassette"; + discSubType = "Compact Cassette"; + + break; + case CommonTypes.MediaType.Dcas25: + discType = "Compact Cassette"; + discSubType = "D/CAS-25"; + + break; + case CommonTypes.MediaType.Dcas85: + discType = "Compact Cassette"; + discSubType = "D/CAS-85"; + + break; + case CommonTypes.MediaType.Dcas103: + discType = "Compact Cassette"; + discSubType = "D/CAS-103"; + + break; + case CommonTypes.MediaType.PCCardTypeI: + discType = "PCMCIA Card"; + discSubType = "PC-Card Type I"; + + break; + case CommonTypes.MediaType.PCCardTypeII: + discType = "PCMCIA Card"; + discSubType = "PC-Card Type II"; + + break; + case CommonTypes.MediaType.PCCardTypeIII: + discType = "PCMCIA Card"; + discSubType = "PC-Card Type III"; + + break; + case CommonTypes.MediaType.PCCardTypeIV: + discType = "PCMCIA Card"; + discSubType = "PC-Card Type IV"; + + break; + case CommonTypes.MediaType.ExpressCard34: + discType = "Express Card"; + discSubType = "Express Card (34mm)"; + + break; + case CommonTypes.MediaType.ExpressCard54: + discType = "Express Card"; + discSubType = "Express Card (54mm)"; + + break; + case CommonTypes.MediaType.FamicomGamePak: + discType = "Nintendo Famicom Game Pak"; + discSubType = "Nintendo Famicom Game Pak"; + + break; + case CommonTypes.MediaType.GameBoyAdvanceGamePak: + discType = "Nintendo Game Boy Advance Game Pak"; + discSubType = "Nintendo Game Boy Advance Game Pak"; + + break; + case CommonTypes.MediaType.GameBoyGamePak: + discType = "Nintendo Game Boy Game Pak"; + discSubType = "Nintendo Game Boy Game Pak"; + + break; + case CommonTypes.MediaType.N64DD: + discType = "Nintendo 64 Disk"; + discSubType = "Nintendo 64 Disk"; + + break; + case CommonTypes.MediaType.N64GamePak: + discType = "Nintendo 64 Game Pak"; + discSubType = "Nintendo 64 Game Pak"; + + break; + case CommonTypes.MediaType.NESGamePak: + discType = "Nintendo Entertainment System Game Pak"; + discSubType = "Nintendo Entertainment System Game Pak"; + + break; + case CommonTypes.MediaType.Nintendo3DSGameCard: + discType = "Nintendo 3DS Game Card"; + discSubType = "Nintendo 3DS Game Card"; + + break; + case CommonTypes.MediaType.NintendoDiskCard: + discType = "Nintendo Disk Card"; + discSubType = "Nintendo Disk Card"; + + break; + case CommonTypes.MediaType.NintendoDSGameCard: + discType = "Nintendo DS Game Card"; + discSubType = "Nintendo DS Game Card"; + + break; + case CommonTypes.MediaType.NintendoDSiGameCard: + discType = "Nintendo DSi Game Card"; + discSubType = "Nintendo DSi Game Card"; + + break; + case CommonTypes.MediaType.SNESGamePak: + discType = "Super Nintendo Game Pak"; + discSubType = "Super Nintendo Game Pak"; + + break; + case CommonTypes.MediaType.SNESGamePakUS: + discType = "Super Nintendo Game Pak (US)"; + discSubType = "Super Nintendo Game Pak (US)"; + + break; + case CommonTypes.MediaType.SwitchGameCard: + discType = "Nintendo Switch Game Card"; + discSubType = "Nintendo Switch Game Card"; + + break; + case CommonTypes.MediaType.IBM3470: + discType = "IBM 3470"; + discSubType = "IBM 3470"; + + break; + case CommonTypes.MediaType.IBM3480: + discType = "IBM 3480"; + discSubType = "IBM 3480"; + + break; + case CommonTypes.MediaType.IBM3490: + discType = "IBM 3490"; + discSubType = "IBM 3490"; + + break; + case CommonTypes.MediaType.IBM3490E: + discType = "IBM 3490E"; + discSubType = "IBM 3490E"; + + break; + case CommonTypes.MediaType.IBM3592: + discType = "IBM 3592"; + discSubType = "IBM 3592"; + + break; + case CommonTypes.MediaType.STK4480: + discType = "STK 4480"; + discSubType = "STK 4480"; + + break; + case CommonTypes.MediaType.STK4490: + discType = "STK 4490"; + discSubType = "STK 4490"; + + break; + case CommonTypes.MediaType.STK9490: + discType = "STK 9490"; + discSubType = "STK 9490"; + + break; + case CommonTypes.MediaType.T9840A: + discType = "STK T-9840"; + discSubType = "STK T-9840A"; + + break; + case CommonTypes.MediaType.T9840B: + discType = "STK T-9840"; + discSubType = "STK T-9840B"; + + break; + case CommonTypes.MediaType.T9840C: + discType = "STK T-9840"; + discSubType = "STK T-9840C"; + + break; + case CommonTypes.MediaType.T9840D: + discType = "STK T-9840"; + discSubType = "STK T-9840D"; + + break; + case CommonTypes.MediaType.T9940A: + discType = "STK T-9940"; + discSubType = "STK T-9940A"; + + break; + case CommonTypes.MediaType.T9940B: + discType = "STK T-9840"; + discSubType = "STK T-9840B"; + + break; + case CommonTypes.MediaType.T10000A: + discType = "STK T-10000"; + discSubType = "STK T-10000A"; + + break; + case CommonTypes.MediaType.T10000B: + discType = "STK T-10000"; + discSubType = "STK T-10000B"; + + break; + case CommonTypes.MediaType.T10000C: + discType = "STK T-10000"; + discSubType = "STK T-10000C"; + + break; + case CommonTypes.MediaType.T10000D: + discType = "STK T-10000"; + discSubType = "STK T-10000D"; + + break; + case CommonTypes.MediaType.DemiDiskette: + discType = "DemiDiskette"; + discSubType = "DemiDiskette"; + + break; + case CommonTypes.MediaType.QuickDisk: + discType = "QuickDisk"; + discSubType = "QuickDisk"; + + break; + case CommonTypes.MediaType.VideoFloppy: + discType = "VideoFloppy"; + discSubType = "VideoFloppy"; + + break; + case CommonTypes.MediaType.Wafer: + discType = "Wafer"; + discSubType = "Wafer"; + + break; + case CommonTypes.MediaType.ZXMicrodrive: + discType = "ZX Microdrive"; + discSubType = "ZX Microdrive"; + + break; + case CommonTypes.MediaType.BeeCard: + discType = "BeeCard"; + discSubType = "BeeCard"; + + break; + case CommonTypes.MediaType.Borsu: + discType = "Borsu"; + discSubType = "Borsu"; + + break; + case CommonTypes.MediaType.DataStore: + discType = "DataStore"; + discSubType = "DataStore"; + + break; + case CommonTypes.MediaType.DIR: + discType = "DIR"; + discSubType = "DIR"; + + break; + case CommonTypes.MediaType.DST: + discType = "DST"; + discSubType = "DST"; + + break; + case CommonTypes.MediaType.DTF: + discType = "DTF"; + discSubType = "DTF"; + + break; + case CommonTypes.MediaType.DTF2: + discType = "DTF2"; + discSubType = "DTF2"; + + break; + case CommonTypes.MediaType.Flextra3020: + discType = "Flextra"; + discSubType = "Flextra 3020"; + + break; + case CommonTypes.MediaType.Flextra3225: + discType = "Flextra"; + discSubType = "Flextra 3225"; + + break; + case CommonTypes.MediaType.HiTC1: + discType = "HiTC"; + discSubType = "HiTC1"; + + break; + case CommonTypes.MediaType.HiTC2: + discType = "HiTC"; + discSubType = "HiTC2"; + + break; + case CommonTypes.MediaType.LT1: + discType = "LT1"; + discSubType = "LT1"; + + break; + case CommonTypes.MediaType.MiniCard: + discType = "MiniCard"; + discSubType = "MiniCard"; + + break; + case CommonTypes.MediaType.Orb: + discType = "Orb"; + discSubType = "Orb"; + + break; + case CommonTypes.MediaType.Orb5: + discType = "Orb"; + discSubType = "Orb5"; + + break; + case CommonTypes.MediaType.SmartMedia: + discType = "SmartMedia"; + discSubType = "SmartMedia"; + + break; + case CommonTypes.MediaType.xD: + discType = "xD"; + discSubType = "xD"; + + break; + case CommonTypes.MediaType.XQD: + discType = "XQD"; + discSubType = "XQD"; + + break; + case CommonTypes.MediaType.DataPlay: + discType = "DataPlay"; + discSubType = "DataPlay"; + + break; + case CommonTypes.MediaType.PD650: + discType = "PD650"; + discSubType = "PD650"; + + break; + case CommonTypes.MediaType.PD650_WORM: + discType = "PD650"; + discSubType = "PD650 (WORM)"; + + break; + case CommonTypes.MediaType.RA60: + discType = "Hard Disk Drive"; + discSubType = "DEC RA-60"; + + break; + case CommonTypes.MediaType.RA80: + discType = "Hard Disk Drive"; + discSubType = "DEC RA-80"; + + break; + case CommonTypes.MediaType.RA81: + discType = "Hard Disk Drive"; + discSubType = "DEC RA-81"; + + break; + case CommonTypes.MediaType.RC25: + discType = "Hard Disk Drive"; + discSubType = "DEC RC-25"; + + break; + case CommonTypes.MediaType.RD31: + discType = "Hard Disk Drive"; + discSubType = "DEC RD-31"; + + break; + case CommonTypes.MediaType.RD32: + discType = "Hard Disk Drive"; + discSubType = "DEC RD-32"; + + break; + case CommonTypes.MediaType.RD51: + discType = "Hard Disk Drive"; + discSubType = "DEC RD-51"; + + break; + case CommonTypes.MediaType.RD52: + discType = "Hard Disk Drive"; + discSubType = "DEC RD-52"; + + break; + case CommonTypes.MediaType.RD53: + discType = "Hard Disk Drive"; + discSubType = "DEC RD-53"; + + break; + case CommonTypes.MediaType.RD54: + discType = "Hard Disk Drive"; + discSubType = "DEC RD-54"; + + break; + case CommonTypes.MediaType.RK06: + case CommonTypes.MediaType.RK06_18: + discType = "Hard Disk Drive"; + discSubType = "DEC RK-06"; + + break; + case CommonTypes.MediaType.RK07: + case CommonTypes.MediaType.RK07_18: + discType = "Hard Disk Drive"; + discSubType = "DEC RK-07"; + + break; + case CommonTypes.MediaType.RM02: + discType = "Hard Disk Drive"; + discSubType = "DEC RM-02"; + + break; + case CommonTypes.MediaType.RM03: + discType = "Hard Disk Drive"; + discSubType = "DEC RM-03"; + + break; + case CommonTypes.MediaType.RM05: + discType = "Hard Disk Drive"; + discSubType = "DEC RM-05"; + + break; + case CommonTypes.MediaType.RP02: + case CommonTypes.MediaType.RP02_18: + discType = "Hard Disk Drive"; + discSubType = "DEC RP-02"; + + break; + case CommonTypes.MediaType.RP03: + case CommonTypes.MediaType.RP03_18: + discType = "Hard Disk Drive"; + discSubType = "DEC RP-03"; + + break; + case CommonTypes.MediaType.RP04: + case CommonTypes.MediaType.RP04_18: + discType = "Hard Disk Drive"; + discSubType = "DEC RP-04"; + + break; + case CommonTypes.MediaType.RP05: + case CommonTypes.MediaType.RP05_18: + discType = "Hard Disk Drive"; + discSubType = "DEC RP-05"; + + break; + case CommonTypes.MediaType.RP06: + case CommonTypes.MediaType.RP06_18: + discType = "Hard Disk Drive"; + discSubType = "DEC RP-06"; + + break; + case CommonTypes.MediaType.RDX: + discType = "RDX"; + discSubType = "RDX"; + + break; + case CommonTypes.MediaType.RDX320: + discType = "RDX"; + discSubType = "RDX 320"; + + break; + case CommonTypes.MediaType.Zone_HDD: + discType = "Zoned Hard Disk Drive"; + discSubType = "Unknown"; + + break; + case CommonTypes.MediaType.Microdrive: + discType = "Hard Disk Drive"; + discSubType = "Microdrive"; + + break; + case CommonTypes.MediaType.VideoNow: + discType = "VideoNow"; + discSubType = "VideoNow"; + + break; + case CommonTypes.MediaType.VideoNowColor: + discType = "VideoNow"; + discSubType = "VideoNow Color"; + + break; + case CommonTypes.MediaType.VideoNowXp: + discType = "VideoNow"; + discSubType = "VideoNow XP"; + + break; + case CommonTypes.MediaType.KodakVerbatim3: + discType = "Kodak Verbatim"; + discSubType = "Kodak Verbatim (3 Mb)"; + + break; + case CommonTypes.MediaType.KodakVerbatim6: + discType = "Kodak Verbatim"; + discSubType = "Kodak Verbatim (6 Mb)"; + + break; + case CommonTypes.MediaType.KodakVerbatim12: + discType = "Kodak Verbatim"; + discSubType = "Kodak Verbatim (12 Mb)"; + + break; + case CommonTypes.MediaType.ProfessionalDisc: + discType = "Sony Professional Disc"; + discSubType = "Sony Professional Disc (single layer)"; + + break; + case CommonTypes.MediaType.ProfessionalDiscDual: + discType = "Sony Professional Disc"; + discSubType = "Sony Professional Disc (double layer)"; + + break; + case CommonTypes.MediaType.ProfessionalDiscTriple: + discType = "Sony Professional Disc"; + discSubType = "Sony Professional Disc (triple layer)"; + + break; + case CommonTypes.MediaType.ProfessionalDiscQuad: + discType = "Sony Professional Disc"; + discSubType = "Sony Professional Disc (quad layer)"; + + break; + case CommonTypes.MediaType.PDD: + discType = "Sony Professional Disc for DATA"; + discSubType = "Sony Professional Disc for DATA"; + + break; + case CommonTypes.MediaType.PDD_WORM: + discType = "Sony Professional Disc for DATA"; + discSubType = "Sony Professional Disc for DATA (write-once)"; + + break; + case CommonTypes.MediaType.ArchivalDisc: + discType = "Archival Disc"; + discSubType = "Archival Disc"; + + break; + case CommonTypes.MediaType.ArchivalDisc2: + discType = "Archival Disc"; + discSubType = "Archival Disc (2nd generation)"; + + break; + case CommonTypes.MediaType.ArchivalDisc3: + discType = "Archival Disc"; + discSubType = "Archival Disc (3rd generation)"; + + break; + case CommonTypes.MediaType.ODC300R: + discType = "Optical Disc Archive"; + discSubType = "ODC300R"; + + break; + case CommonTypes.MediaType.ODC300RE: + discType = "Optical Disc Archive"; + discSubType = "ODC300RE"; + + break; + case CommonTypes.MediaType.ODC600R: + discType = "Optical Disc Archive"; + discSubType = "ODC600R"; + + break; + case CommonTypes.MediaType.ODC600RE: + discType = "Optical Disc Archive"; + discSubType = "ODC600RE"; + + break; + case CommonTypes.MediaType.ODC1200RE: + discType = "Optical Disc Archive"; + discSubType = "ODC1200RE"; + + break; + case CommonTypes.MediaType.ODC1500R: + discType = "Optical Disc Archive"; + discSubType = "ODC1500R"; + + break; + case CommonTypes.MediaType.ODC3300R: + discType = "Optical Disc Archive"; + discSubType = "ODC3300R"; + + break; + case CommonTypes.MediaType.ODC5500R: + discType = "Optical Disc Archive"; + discSubType = "ODC5500R"; + + break; + case CommonTypes.MediaType.MetaFloppy_Mod_I: + discType = "5.25\" floppy"; + discSubType = "Micropolis MetaFloppy Mod I"; + + break; + case CommonTypes.MediaType.MetaFloppy_Mod_II: + discType = "5.25\" floppy"; + discSubType = "Micropolis MetaFloppy Mod II"; + + break; + default: + discType = "Unknown"; + discSubType = "Unknown"; + + break; + } + + return (discType, discSubType); + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Metadata/Resume.cs b/Aaru.CommonTypes/Metadata/Resume.cs new file mode 100644 index 000000000..0f690c98d --- /dev/null +++ b/Aaru.CommonTypes/Metadata/Resume.cs @@ -0,0 +1,80 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Resume.cs +// Author(s) : Natalia Portillo +// +// Component : XML metadata. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines XML format of a dump resume file. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Xml.Serialization; +using Schemas; + +namespace Aaru.CommonTypes.Metadata +{ + /// Information that allows to resume a dump + [Serializable, XmlRoot("DicResume", Namespace = "", IsNullable = false)] + public class Resume + { + /// List of blocks that returned an error on reading + [XmlArrayItem("Block")] + public List BadBlocks; + /// Date/time this resume file was created + [XmlElement(DataType = "dateTime")] + public DateTime CreationDate; + /// Last block on media + public ulong LastBlock; + /// Date/time this resume file was last written to + [XmlElement(DataType = "dateTime")] + public DateTime LastWriteDate; + /// Next block to read + public ulong NextBlock; + /// Is media removable? + public bool Removable; + /// Is media a tape? + public bool Tape; + /// List of CD subchannels that did not read correctly + [XmlArrayItem("Block")] + public List BadSubchannels; + /// Extents of BLANK sectors for magneto-opticals + [XmlArrayItem("Extent")] + public ExtentType[] BlankExtents; + /// Title keys that has not been read + [XmlArrayItem("Block")] + public List MissingTitleKeys; + /// List of dump tries + [XmlArrayItem("DumpTry")] + public List Tries; + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Metadata/Statistics.cs b/Aaru.CommonTypes/Metadata/Statistics.cs new file mode 100644 index 000000000..211640ae9 --- /dev/null +++ b/Aaru.CommonTypes/Metadata/Statistics.cs @@ -0,0 +1,309 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Statistics.cs +// Author(s) : Natalia Portillo +// +// Component : XML metadata. +// +// --[ Description ] ---------------------------------------------------------- +// +// Define XML for statistics. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Xml.Serialization; + +// ReSharper disable ClassNeverInstantiated.Global +// ReSharper disable UnusedMember.Global + +namespace Aaru.CommonTypes.Metadata +{ + /// Statistics + [XmlRoot("DicStats", Namespace = "", IsNullable = false)] + public class Stats + { + /// Executed commands + public CommandsStats Commands; + /// Operating systems Aaru has run from + [XmlArrayItem("OperatingSystem")] + public List OperatingSystems { get; set; } + /// Aaru versions + [XmlArrayItem("Version")] + public List Versions { get; set; } + /// Detected filesystems + [XmlArrayItem("Filesystem")] + public List Filesystems { get; set; } + /// Detected partitioning schemes + [XmlArrayItem("Scheme")] + public List Partitions { get; set; } + /// Media image formats + [XmlArrayItem("Format")] + public List MediaImages { get; set; } + /// Used filters + [XmlArrayItem("Filter", IsNullable = true)] + public List Filters { get; set; } + /// Found devices + [XmlArrayItem("Device", IsNullable = true)] + public List Devices { get; set; } + /// Found media types, real, and in image + [XmlArrayItem("Media")] + public List Medias { get; set; } + /// Benchmark statistics + public BenchmarkStats Benchmark { get; set; } + /// Media scanning statistics + public MediaScanStats MediaScan { get; set; } + /// Image verification statistics + public VerifyStats Verify { get; set; } + } + + /// DTO for statistics + [SuppressMessage("ReSharper", "CollectionNeverQueried.Global")] + public class StatsDto + { + /// Executed commands + public List Commands { get; set; } + /// Operating systems Aaru has run from + public List OperatingSystems { get; set; } + /// Aaru versions + public List Versions { get; set; } + /// Detected filesystems + public List Filesystems { get; set; } + /// Detected partitioning schemes + public List Partitions { get; set; } + /// Media image formats + public List MediaFormats { get; set; } + /// Used filters + public List Filters { get; set; } + /// Found devices + public List Devices { get; set; } + /// Found media types, real, and in image + public List Medias { get; set; } + /// Remote applications + public List RemoteApplications { get; set; } + /// Remote application architectures + public List RemoteArchitectures { get; set; } + /// Operating systems where a remote application has been running + public List RemoteOperatingSystems { get; set; } + } + + /// Command execution statistics + [SuppressMessage("ReSharper", "UnassignedField.Global")] + public class CommandsStats + { + /// Number of times the filesystem info command has been used + public long Analyze; + /// Number of times the benchmark command has been used + public long Benchmark; + /// Number of times the image checksum command has been used + public long Checksum; + /// Number of times the image compare command has been used + public long Compare; + /// Number of times the image convert command has been used + public long ConvertImage; + /// Number of times the image create-sidecar command has been used + public long CreateSidecar; + /// Number of times the image decode command has been used + public long Decode; + /// Number of times the device info command has been used + public long DeviceInfo; + /// Number of times the device report command has been used + public long DeviceReport; + /// Number of times the media dump command has been used + public long DumpMedia; + /// Number of times the image entropy command has been used + public long Entropy; + /// Number of times the filesystem extract command has been used + public long ExtractFiles; + /// Number of times the list formats command has been used + public long Formats; + /// Number of times the image info command has been used + public long ImageInfo; + /// Number of times the device list command has been used + public long ListDevices; + /// Number of times the list encodings command has been used + public long ListEncodings; + /// Number of times the filesystem ls command has been used + public long Ls; + /// Number of times the media info command has been used + public long MediaInfo; + /// Number of times the media scan command has been used + public long MediaScan; + /// Number of times the image printhex command has been used + public long PrintHex; + /// Number of times the image verify command has been used + public long Verify; + } + + /// Statistics of verified media + public class VerifiedItems + { + /// Number of correct images + public long Correct; + /// Number of failed images + public long Failed; + } + + /// Verification statistics + public class VerifyStats + { + /// Image verification statistics + public VerifiedItems MediaImages; + /// Image contents verification statistics + public ScannedSectors Sectors; + } + + /// Image contents verification statistics + public class ScannedSectors + { + /// Sectors found to be correct + public long Correct; + /// Sectors found to be incorrect + public long Error; + /// Total number of verified sectors + public long Total; + /// Total number of sectors that could not be verified + public long Unverifiable; + } + + /// Media scanning time statistics + [SuppressMessage("ReSharper", "InconsistentNaming")] + public class TimeStats + { + /// Number of sectors that took more than 3ms but less than 100ms to read + public long LessThan10ms; + /// Number of sectors that took more than 50ms but less than 150ms to read + public long LessThan150ms; + /// Number of sectors that took less than 3ms to read + public long LessThan3ms; + /// Number of sectors that took more than 150ms but less than 500ms to read + public long LessThan500ms; + /// Number of sectors that took more than 10ms but less than 50ms to read + public long LessThan50ms; + /// Number of sectors that took more than 500ms to read + public long MoreThan500ms; + } + + /// Media scanning statistics + public class MediaScanStats + { + /// Statistics of scanned sectors + public ScannedSectors Sectors; + /// Scan time statistics + public TimeStats Times; + } + + /// Checksum type statistics + [SuppressMessage("ReSharper", "InconsistentNaming")] + public class ChecksumStats + { + /// Checksum algorithm + [XmlAttribute] + public string algorithm; + /// Time taken to execute algorithm + [XmlText] + public double Value; + } + + /// Benchmark statistics + public class BenchmarkStats + { + /// Total time taken to run the checksum algorithms in parallel + public double All; + /// List of time taken by each checksum algorithm + [XmlElement("Checksum")] + public List Checksum; + /// Time taken to benchmark entropy calculation + public double Entropy; + /// Maximum amount of memory used while running the benchmark + public long MaxMemory; + /// Minimum amount of memory used while running the benchmark + public long MinMemory; + /// Total time taken to run the checksum algorithms sequentially + public double Sequential; + } + + /// Media statistics + [SuppressMessage("ReSharper", "InconsistentNaming")] + public class MediaStats + { + /// Found in a real device? + [XmlAttribute] + public bool real; + /// Media type + [XmlAttribute] + public string type; + /// Number of times it has been found + [XmlText] + public long Value; + } + + /// Device statistics + public class DeviceStats + { + /// Is manufacturer null? + [XmlIgnore] + public bool ManufacturerSpecified; + /// Manufacturer string + public string Manufacturer { get; set; } + /// Model string + public string Model { get; set; } + /// Revision or firmware version + public string Revision { get; set; } + /// Bus the device was attached to + public string Bus { get; set; } + } + + /// Name=value pair statistics + [SuppressMessage("ReSharper", "InconsistentNaming")] + public class NameValueStats + { + /// Name + [XmlAttribute] + public string name { get; set; } + /// Number of times it has been used/found + [XmlText] + public long Value { get; set; } + } + + /// Operating system statistics + [SuppressMessage("ReSharper", "InconsistentNaming")] + public class OsStats + { + /// Operating system name + [XmlAttribute] + public string name { get; set; } + /// Operating system version + [XmlAttribute] + public string version { get; set; } + /// Number of times Aaru run on it + [XmlText] + public long Value { get; set; } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Metadata/Version.cs b/Aaru.CommonTypes/Metadata/Version.cs new file mode 100644 index 000000000..ece9a7881 --- /dev/null +++ b/Aaru.CommonTypes/Metadata/Version.cs @@ -0,0 +1,56 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Statistics.cs +// Author(s) : Natalia Portillo +// +// Component : XML metadata. +// +// --[ Description ] ---------------------------------------------------------- +// +// Returns Aaru version in XML software type format. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using Aaru.CommonTypes.Interop; +using Schemas; + +namespace Aaru.CommonTypes.Metadata +{ + /// Manages Aaru's version for metadata + public static class Version + { + /// Gets XML software type for the running version + /// XML software type + public static SoftwareType GetSoftwareType() => new SoftwareType + { + Name = "Aaru", + OperatingSystem = DetectOS.GetRealPlatformID().ToString(), + Version = typeof(Version).Assembly.GetName().Version?.ToString() + }; + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Partition.cs b/Aaru.CommonTypes/Partition.cs new file mode 100644 index 000000000..2af522758 --- /dev/null +++ b/Aaru.CommonTypes/Partition.cs @@ -0,0 +1,119 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Partition.cs +// Author(s) : Natalia Portillo +// +// Component : Aaru common types. +// +// --[ Description ] ---------------------------------------------------------- +// +// Contains common partition types. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; + +namespace Aaru.CommonTypes +{ + /// Partition structure. + public struct Partition : IEquatable, IComparable + { + /// Partition number, 0-started + public ulong Sequence; + /// Partition type + public string Type; + /// Partition name (if the scheme supports it) + public string Name; + /// Start of the partition, in bytes + public ulong Offset; + /// LBA of partition start + public ulong Start; + /// Length in bytes of the partition + public ulong Size; + /// Length in sectors of the partition + public ulong Length; + /// Information that does not find space in this struct + public string Description; + /// LBA of last partition sector + public readonly ulong End => Start + Length - 1; + /// Name of partition scheme that contains this partition + public string Scheme; + + /// + /// Compares two partitions + /// Partition to compare with + /// 0 if both partitions start and end at the same sector + public bool Equals(Partition other) => Start == other.Start && Length == other.Length; + + /// + public override bool Equals(object obj) => obj is Partition partition && Equals(partition); + + /// + + // ReSharper disable once NonReadonlyMemberInGetHashCode + public override int GetHashCode() => Start.GetHashCode() + End.GetHashCode(); + + /// + /// Compares this partition with another and returns an integer that indicates whether the current partition + /// precedes, follows, or is in the same place as the other partition. + /// + /// Partition to compare with + /// A value that indicates the relative equality of the partitions being compared. + /// + public int CompareTo(Partition other) + { + if(Start == other.Start && + End == other.End) + return 0; + + if(Start > other.Start || + End > other.End) + return 1; + + return -1; + } + + // Define the equality operator. + public static bool operator ==(Partition operand1, Partition operand2) => operand1.Equals(operand2); + + // Define the inequality operator. + public static bool operator !=(Partition operand1, Partition operand2) => !operand1.Equals(operand2); + + // Define the is greater than operator. + public static bool operator >(Partition operand1, Partition operand2) => operand1.CompareTo(operand2) == 1; + + // Define the is less than operator. + public static bool operator <(Partition operand1, Partition operand2) => operand1.CompareTo(operand2) == -1; + + // Define the is greater than or equal to operator. + public static bool operator >=(Partition operand1, Partition operand2) => operand1.CompareTo(operand2) >= 0; + + // Define the is less than or equal to operator. + public static bool operator <=(Partition operand1, Partition operand2) => operand1.CompareTo(operand2) <= 0; + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/PluginBase.cs b/Aaru.CommonTypes/PluginBase.cs new file mode 100644 index 000000000..c09062f57 --- /dev/null +++ b/Aaru.CommonTypes/PluginBase.cs @@ -0,0 +1,140 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : PluginBase.cs +// Author(s) : Natalia Portillo +// +// Component : Core algorithms. +// +// --[ Description ] ---------------------------------------------------------- +// +// Class to hold all installed plugins. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Linq; +using Aaru.CommonTypes.Interfaces; + +namespace Aaru.CommonTypes +{ + /// Contain all plugins (filesystem, partition and image) + public class PluginBase + { + /// List of checksum plugins + public readonly List Checksums; + /// List of filter plugins + public readonly SortedDictionary Filters; + /// List of floppy image plugins + public readonly SortedDictionary FloppyImages; + /// List of all media image plugins + public readonly SortedDictionary ImagePluginsList; + /// List of all partition plugins + public readonly SortedDictionary PartPluginsList; + /// List of all filesystem plugins + public readonly SortedDictionary PluginsList; + /// List of read-only filesystem plugins + public readonly SortedDictionary ReadOnlyFilesystems; + /// List of writable floppy image plugins + public readonly SortedDictionary WritableFloppyImages; + /// List of writable media image plugins + public readonly SortedDictionary WritableImages; + + /// Initializes the plugins lists + public PluginBase() + { + PluginsList = new SortedDictionary(); + ReadOnlyFilesystems = new SortedDictionary(); + PartPluginsList = new SortedDictionary(); + ImagePluginsList = new SortedDictionary(); + WritableImages = new SortedDictionary(); + Checksums = new List(); + Filters = new SortedDictionary(); + FloppyImages = new SortedDictionary(); + WritableFloppyImages = new SortedDictionary(); + } + + /// Adds plugins to the central plugin register + /// Plugin register + public void AddPlugins(IPluginRegister pluginRegister) + { + foreach(Type type in pluginRegister.GetAllChecksumPlugins() ?? Enumerable.Empty()) + if(type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] + {}) is IChecksum plugin) + Checksums.Add(plugin); + + foreach(Type type in pluginRegister.GetAllFilesystemPlugins() ?? Enumerable.Empty()) + if(type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] + {}) is IFilesystem plugin && + !PluginsList.ContainsKey(plugin.Name.ToLower())) + PluginsList.Add(plugin.Name.ToLower(), plugin); + + foreach(Type type in pluginRegister.GetAllFilterPlugins() ?? Enumerable.Empty()) + if(type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] + {}) is IFilter plugin && + !Filters.ContainsKey(plugin.Name.ToLower())) + Filters.Add(plugin.Name.ToLower(), plugin); + + foreach(Type type in pluginRegister.GetAllFloppyImagePlugins() ?? Enumerable.Empty()) + if(type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] + {}) is IFloppyImage plugin && + !FloppyImages.ContainsKey(plugin.Name.ToLower())) + FloppyImages.Add(plugin.Name.ToLower(), plugin); + + foreach(Type type in pluginRegister.GetAllMediaImagePlugins() ?? Enumerable.Empty()) + if(type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] + {}) is IMediaImage plugin && + !ImagePluginsList.ContainsKey(plugin.Name.ToLower())) + ImagePluginsList.Add(plugin.Name.ToLower(), plugin); + + foreach(Type type in pluginRegister.GetAllPartitionPlugins() ?? Enumerable.Empty()) + if(type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] + {}) is IPartition plugin && + !PartPluginsList.ContainsKey(plugin.Name.ToLower())) + PartPluginsList.Add(plugin.Name.ToLower(), plugin); + + foreach(Type type in pluginRegister.GetAllReadOnlyFilesystemPlugins() ?? Enumerable.Empty()) + if(type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] + {}) is IReadOnlyFilesystem plugin && + !ReadOnlyFilesystems.ContainsKey(plugin.Name.ToLower())) + ReadOnlyFilesystems.Add(plugin.Name.ToLower(), plugin); + + foreach(Type type in pluginRegister.GetAllWritableFloppyImagePlugins() ?? Enumerable.Empty()) + if(type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] + {}) is IWritableFloppyImage plugin && + !WritableFloppyImages.ContainsKey(plugin.Name.ToLower())) + WritableFloppyImages.Add(plugin.Name.ToLower(), plugin); + + foreach(Type type in pluginRegister.GetAllWritableImagePlugins() ?? Enumerable.Empty()) + if(type.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] + {}) is IWritableImage plugin && + !WritableImages.ContainsKey(plugin.Name.ToLower())) + WritableImages.Add(plugin.Name.ToLower(), plugin); + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Structs/Devices/ATA/Identify.cs b/Aaru.CommonTypes/Structs/Devices/ATA/Identify.cs new file mode 100644 index 000000000..1b0bf1d74 --- /dev/null +++ b/Aaru.CommonTypes/Structs/Devices/ATA/Identify.cs @@ -0,0 +1,1127 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Identify.cs +// Author(s) : Natalia Portillo +// +// Component : Common structures for ATA devices. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines a high level interpretation of the ATA IDENTIFY response. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using System.Text; +using Aaru.Console; +using Aaru.Helpers; +using Marshal = Aaru.Helpers.Marshal; + +// ReSharper disable UnusedMember.Global + +namespace Aaru.CommonTypes.Structs.Devices.ATA +{ + /// + /// Information from following standards: T10-791D rev. 4c (ATA) T10-948D rev. 4c (ATA-2) T13-1153D rev. 18 + /// (ATA/ATAPI-4) T13-1321D rev. 3 (ATA/ATAPI-5) T13-1410D rev. 3b (ATA/ATAPI-6) T13-1532D rev. 4b (ATA/ATAPI-7) + /// T13-1699D rev. 3f (ATA8-ACS) T13-1699D rev. 4a (ATA8-ACS) T13-2015D rev. 2 (ACS-2) T13-2161D rev. 5 (ACS-3) CF+ + /// & CF Specification rev. 1.4 (CFA) + /// + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class Identify + { + /// Capabilities flag bits. + [Flags] + public enum CapabilitiesBit : ushort + { + /// ATAPI: Interleaved DMA supported + InterleavedDMA = 0x8000, + /// ATAPI: Command queueing supported + CommandQueue = 0x4000, + /// Standby timer values are standard + StandardStandbyTimer = 0x2000, + /// ATAPI: Overlap operation supported + OverlapOperation = 0x2000, + /// ATAPI: ATA software reset required Obsoleted in ATA/ATAPI-4 + RequiresATASoftReset = 0x1000, + /// IORDY is supported + IORDY = 0x0800, + /// IORDY can be disabled + CanDisableIORDY = 0x0400, + /// LBA is supported + LBASupport = 0x0200, + /// DMA is supported + DMASupport = 0x0100, + /// Vendor unique Obsoleted in ATA/ATAPI-4 + VendorBit7 = 0x0080, + /// Vendor unique Obsoleted in ATA/ATAPI-4 + VendorBit6 = 0x0040, + /// Vendor unique Obsoleted in ATA/ATAPI-4 + VendorBit5 = 0x0020, + /// Vendor unique Obsoleted in ATA/ATAPI-4 + VendorBit4 = 0x0010, + /// Vendor unique Obsoleted in ATA/ATAPI-4 + VendorBit3 = 0x0008, + /// Vendor unique Obsoleted in ATA/ATAPI-4 + VendorBit2 = 0x0004, + /// Long Physical Alignment setting bit 1 + PhysicalAlignment1 = 0x0002, + /// Long Physical Alignment setting bit 0 + PhysicalAlignment0 = 0x0001 + } + + /// More capabilities flag bits. + [Flags] + public enum CapabilitiesBit2 : ushort + { + /// MUST NOT be set + MustBeClear = 0x8000, + /// MUST be set + MustBeSet = 0x4000, + #pragma warning disable 1591 + Reserved13 = 0x2000, Reserved12 = 0x1000, Reserved11 = 0x0800, + Reserved10 = 0x0400, Reserved09 = 0x0200, Reserved08 = 0x0100, + Reserved07 = 0x0080, Reserved06 = 0x0040, Reserved05 = 0x0020, + Reserved04 = 0x0010, Reserved03 = 0x0008, Reserved02 = 0x0004, + Reserved01 = 0x0002, + #pragma warning restore 1591 + /// Indicates a device specific minimum standby timer value + SpecificStandbyTimer = 0x0001 + } + + /// Even more capabilities flag bits. + [Flags] + public enum CapabilitiesBit3 : byte + { + /// BLOCK ERASE EXT supported + BlockErase = 0x0080, + /// OVERWRITE EXT supported + Overwrite = 0x0040, + /// CRYPTO SCRAMBLE EXT supported + CryptoScramble = 0x0020, + /// Sanitize feature set is supported + Sanitize = 0x0010, + /// If unset, sanitize commands are specified by ACS-2 + SanitizeCommands = 0x0008, + /// SANITIZE ANTIFREEZE LOCK EXT is supported + SanitizeAntifreeze = 0x0004, + #pragma warning disable 1591 + Reserved01 = 0x0002, + #pragma warning restore 1591 + /// Multiple logical sector setting is valid + MultipleValid = 0x0001 + } + + /// Command set flag bits. + [Flags] + public enum CommandSetBit : ushort + { + /// Already obsolete in ATA/ATAPI-4, reserved in ATA3 + Obsolete15 = 0x8000, + /// NOP is supported + Nop = 0x4000, + /// READ BUFFER is supported + ReadBuffer = 0x2000, + /// WRITE BUFFER is supported + WriteBuffer = 0x1000, + /// Already obsolete in ATA/ATAPI-4, reserved in ATA3 + Obsolete11 = 0x0800, + /// Host Protected Area is supported + HPA = 0x0400, + /// DEVICE RESET is supported + DeviceReset = 0x0200, + /// SERVICE interrupt is supported + Service = 0x0100, + /// Release is supported + Release = 0x0080, + /// Look-ahead is supported + LookAhead = 0x0040, + /// Write cache is supported + WriteCache = 0x0020, + /// PACKET command set is supported + Packet = 0x0010, + /// Power Management feature set is supported + PowerManagement = 0x0008, + /// Removable Media feature set is supported + RemovableMedia = 0x0004, + /// Security Mode feature set is supported + SecurityMode = 0x0002, + /// SMART feature set is supported + SMART = 0x0001 + } + + /// More command set flag bits. + [Flags] + public enum CommandSetBit2 : ushort + { + /// MUST NOT be set + MustBeClear = 0x8000, + /// MUST BE SET + MustBeSet = 0x4000, + /// FLUSH CACHE EXT supported + FlushCacheExt = 0x2000, + /// FLUSH CACHE supported + FlushCache = 0x1000, + /// Device Configuration Overlay feature set supported + DCO = 0x0800, + /// 48-bit LBA supported + LBA48 = 0x0400, + /// Automatic Acoustic Management supported + AAM = 0x0200, + /// SET MAX security extension supported + SetMax = 0x0100, + /// Address Offset Reserved Area Boot NCITS TR27:2001 + AddressOffsetReservedAreaBoot = 0x0080, + /// SET FEATURES required to spin-up + SetFeaturesRequired = 0x0040, + /// Power-Up in standby feature set supported + PowerUpInStandby = 0x0020, + /// Removable Media Status Notification feature set is supported + RemovableNotification = 0x0010, + /// Advanced Power Management feature set is supported + APM = 0x0008, + /// Compact Flash feature set is supported + CompactFlash = 0x0004, + /// READ DMA QUEUED and WRITE DMA QUEUED are supported + RWQueuedDMA = 0x0002, + /// DOWNLOAD MICROCODE is supported + DownloadMicrocode = 0x0001 + } + + /// Even more command set flag bits. + [Flags] + public enum CommandSetBit3 : ushort + { + /// MUST NOT be set + MustBeClear = 0x8000, + /// MUST BE SET + MustBeSet = 0x4000, + /// IDLE IMMEDIATE with UNLOAD FEATURE is supported + IdleImmediate = 0x2000, + /// Reserved for INCITS TR-37/2004 + Reserved12 = 0x1000, + /// Reserved for INCITS TR-37/2004 + Reserved11 = 0x0800, + /// URG bit is supported in WRITE STREAM DMA EXT and WRITE STREAM EXT + WriteURG = 0x0400, + /// URG bit is supported in READ STREAM DMA EXT and READ STREAM EXT + ReadURG = 0x0200, + /// 64-bit World Wide Name is supported + WWN = 0x0100, + /// WRITE DMA QUEUED FUA EXT is supported + FUAWriteQ = 0x0080, + /// WRITE DMA FUA EXT and WRITE MULTIPLE FUA EXT are supported + FUAWrite = 0x0040, + /// General Purpose Logging feature supported + GPL = 0x0020, + /// Streaming feature set is supported + Streaming = 0x0010, + /// Media Card Pass Through command set supported + MCPT = 0x0008, + /// Media serial number supported + MediaSerial = 0x0004, + /// SMART self-test supported + SMARTSelfTest = 0x0002, + /// SMART error logging supported + SMARTLog = 0x0001 + } + + /// Yet more command set flag bits. + [Flags] + public enum CommandSetBit4 : ushort + { + /// MUST NOT be set + MustBeClear = 0x8000, + /// MUST be set + MustBeSet = 0x4000, + #pragma warning disable 1591 + Reserved13 = 0x2000, Reserved12 = 0x1000, Reserved11 = 0x0800, + Reserved10 = 0x0400, + #pragma warning restore 1591 + /// DSN feature set is supported + DSN = 0x0200, + /// Accessible Max Address Configuration is supported + AMAC = 0x0100, + /// Extended Power Conditions is supported + ExtPowerCond = 0x0080, + /// Extended Status Reporting is supported + ExtStatusReport = 0x0040, + /// Free-fall Control feature set is supported + FreeFallControl = 0x0020, + /// Supports segmented feature in DOWNLOAD MICROCODE + SegmentedDownloadMicrocode = 0x0010, + /// READ/WRITE DMA EXT GPL are supported + RWDMAExtGpl = 0x0008, + /// WRITE UNCORRECTABLE is supported + WriteUnc = 0x0004, + /// Write/Read/Verify is supported + WRV = 0x0002, + /// Reserved for DT1825 + DT1825 = 0x0001 + } + + /// Yet again more command set flag bits. + [Flags] + public enum CommandSetBit5 : ushort + { + /// Supports CFast Specification + CFast = 0x8000, + /// Deterministic read after TRIM is supported + DeterministicTrim = 0x4000, + /// Long physical sector alignment error reporting control is supported + LongPhysSectorAligError = 0x2000, + /// DEVICE CONFIGURATION IDENTIFY DMA and DEVICE CONFIGURATION SET DMA are supported + DeviceConfDMA = 0x1000, + /// READ BUFFER DMA is supported + ReadBufferDMA = 0x0800, + /// WRITE BUFFER DMA is supported + WriteBufferDMA = 0x0400, + /// SET PASSWORD DMA and SET UNLOCK DMA are supported + SetMaxDMA = 0x0200, + /// DOWNLOAD MICROCODE DMA is supported + DownloadMicroCodeDMA = 0x0100, + /// Reserved for IEEE-1667 + IEEE1667 = 0x0080, + /// Optional ATA 28-bit commands are supported + Ata28 = 0x0040, + /// Read zero after TRIM is supported + ReadZeroTrim = 0x0020, + /// Device encrypts all user data + Encrypted = 0x0010, + /// Extended number of user addressable sectors is supported + ExtSectors = 0x0008, + /// All write cache is non-volatile + AllCacheNV = 0x0004, + /// Zoned capabilities bit 1 + ZonedBit1 = 0x0002, + /// Zoned capabilities bit 0 + ZonedBit0 = 0x0001 + } + + /// Data set management flag bits. + [Flags] + public enum DataSetMgmtBit : ushort + { + #pragma warning disable 1591 + Reserved15 = 0x8000, Reserved14 = 0x4000, Reserved13 = 0x2000, + Reserved12 = 0x1000, Reserved11 = 0x0800, Reserved10 = 0x0400, + Reserved09 = 0x0200, Reserved08 = 0x0100, Reserved07 = 0x0080, + Reserved06 = 0x0040, Reserved05 = 0x0020, Reserved04 = 0x0010, + Reserved03 = 0x0008, Reserved02 = 0x0004, Reserved01 = 0x0002, + #pragma warning restore 1591 + /// TRIM is supported + Trim = 0x0001 + } + + /// Device form factor + public enum DeviceFormFactorEnum : ushort + { + /// Size not reported + NotReported = 0, + /// 5.25" + FiveAndQuarter = 1, + /// 3.5" + ThreeAndHalf = 2, + /// 2.5" + TwoAndHalf = 3, + /// 1.8" + OnePointEight = 4, + /// Less than 1.8" + LessThanOnePointEight = 5 + } + + /// Extended identify flag bits. + [Flags] + public enum ExtendedIdentifyBit : byte + { + /// Reserved + Reserved07 = 0x80, + /// Reserved + Reserved06 = 0x40, + /// Reserved + Reserved05 = 0x20, + /// Reserved + Reserved04 = 0x10, + /// Reserved + Reserved03 = 0x08, + /// Identify word 88 is valid + Word88Valid = 0x04, + /// Identify words 64 to 70 are valid + Words64to70Valid = 0x02, + /// Identify words 54 to 58 are valid + Words54to58Valid = 0x01 + } + + /// General configuration flag bits. + [Flags] + public enum GeneralConfigurationBit : ushort + { + /// Set on ATAPI + NonMagnetic = 0x8000, + /// Format speed tolerance gap is required Obsoleted in ATA-2 + FormatGapReq = 0x4000, + /// Track offset option is available Obsoleted in ATA-2 + TrackOffset = 0x2000, + /// Data strobe offset option is available Obsoleted in ATA-2 + DataStrobeOffset = 0x1000, + /// Rotational speed tolerance is higher than 0,5% Obsoleted in ATA-2 + RotationalSpeedTolerance = 0x0800, + /// Disk transfer rate is > 10 Mb/s Obsoleted in ATA-2 + UltraFastIDE = 0x0400, + /// Disk transfer rate is > 5 Mb/s but <= 10 Mb/s Obsoleted in ATA-2 + FastIDE = 0x0200, + /// Disk transfer rate is <= 5 Mb/s Obsoleted in ATA-2 + SlowIDE = 0x0100, + /// Drive uses removable media + Removable = 0x0080, + /// Drive is fixed Obsoleted in ATA/ATAPI-6 + Fixed = 0x0040, + /// Spindle motor control is implemented Obsoleted in ATA-2 + SpindleControl = 0x0020, + /// Head switch time is bigger than 15 µsec. Obsoleted in ATA-2 + HighHeadSwitch = 0x0010, + /// Drive is not MFM encoded Obsoleted in ATA-2 + NotMFM = 0x0008, + /// Drive is soft sectored Obsoleted in ATA-2 + SoftSector = 0x0004, + /// Response incomplete Since ATA/ATAPI-5 + IncompleteResponse = 0x0004, + /// Drive is hard sectored Obsoleted in ATA-2 + HardSector = 0x0002, + /// Reserved + Reserved = 0x0001 + } + + /// Word 80 Major version + [Flags] + public enum MajorVersionBit : ushort + { + #pragma warning disable 1591 + Reserved15 = 0x8000, Reserved14 = 0x4000, Reserved13 = 0x2000, + Reserved12 = 0x1000, + #pragma warning restore 1591 + /// ACS-4 + ACS4 = 0x0800, + /// ACS-3 + ACS3 = 0x0400, + /// ACS-2 + ACS2 = 0x0200, + /// ATA8-ACS + Ata8ACS = 0x0100, + /// ATA/ATAPI-7 + AtaAtapi7 = 0x0080, + /// ATA/ATAPI-6 + AtaAtapi6 = 0x0040, + /// ATA/ATAPI-5 + AtaAtapi5 = 0x0020, + /// ATA/ATAPI-4 + AtaAtapi4 = 0x0010, + /// ATA-3 + Ata3 = 0x0008, + /// ATA-2 + Ata2 = 0x0004, + /// ATA-1 + Ata1 = 0x0002, + #pragma warning disable 1591 + Reserved00 = 0x0001 + #pragma warning restore 1591 + } + + /// SATA capabilities flags + [Flags] + public enum SATACapabilitiesBit : ushort + { + /// Supports READ LOG DMA EXT + ReadLogDMAExt = 0x8000, + /// Supports device automatic partial to slumber transitions + DevSlumbTrans = 0x4000, + /// Supports host automatic partial to slumber transitions + HostSlumbTrans = 0x2000, + /// Supports NCQ priority + NCQPriority = 0x1000, + /// Supports unload while NCQ commands are outstanding + UnloadNCQ = 0x0800, + /// Supports PHY Event Counters + PHYEventCounter = 0x0400, + /// Supports receipt of host initiated power management requests + PowerReceipt = 0x0200, + /// Supports NCQ + NCQ = 0x0100, + #pragma warning disable 1591 + Reserved07 = 0x0080, Reserved06 = 0x0040, Reserved05 = 0x0020, + Reserved04 = 0x0010, + #pragma warning restore 1591 + /// Supports SATA Gen. 3 Signaling Speed (6.0Gb/s) + Gen3Speed = 0x0008, + /// Supports SATA Gen. 2 Signaling Speed (3.0Gb/s) + Gen2Speed = 0x0004, + /// Supports SATA Gen. 1 Signaling Speed (1.5Gb/s) + Gen1Speed = 0x0002, + /// MUST NOT be set + Clear = 0x0001 + } + + /// More SATA capabilities flags + [Flags] + public enum SATACapabilitiesBit2 : ushort + { + #pragma warning disable 1591 + Reserved15 = 0x8000, Reserved14 = 0x4000, Reserved13 = 0x2000, + Reserved12 = 0x1000, Reserved11 = 0x0800, Reserved10 = 0x0400, + Reserved09 = 0x0200, Reserved08 = 0x0100, Reserved07 = 0x0080, + #pragma warning restore 1591 + /// Supports RECEIVE FPDMA QUEUED and SEND FPDMA QUEUED + FPDMAQ = 0x0040, + /// Supports NCQ Queue Management + NCQMgmt = 0x0020, + /// ATAPI: Supports host environment detect + HostEnvDetect = 0x0020, + /// Supports NCQ streaming + NCQStream = 0x0010, + /// ATAPI: Supports device attention on slimline connected devices + DevAttSlimline = 0x0010, + /// Coded value indicating current negotiated Serial ATA signal speed + CurrentSpeedBit2 = 0x0008, + /// Coded value indicating current negotiated Serial ATA signal speed + CurrentSpeedBit1 = 0x0004, + /// Coded value indicating current negotiated Serial ATA signal speed + CurrentSpeedBit0 = 0x0002, + /// MUST NOT be set + Clear = 0x0001 + } + + /// SATA features flags + [Flags] + public enum SATAFeaturesBit : ushort + { + #pragma warning disable 1591 + Reserved15 = 0x8000, Reserved14 = 0x4000, Reserved13 = 0x2000, + Reserved12 = 0x1000, Reserved11 = 0x0800, Reserved10 = 0x0400, + Reserved09 = 0x0200, Reserved08 = 0x0100, + #pragma warning restore 1591 + /// Supports NCQ autosense + NCQAutoSense = 0x0080, + /// Automatic Partial to Slumber transitions are enabled + EnabledSlumber = 0x0080, + /// Supports Software Settings Preservation + SettingsPreserve = 0x0040, + /// Supports hardware feature control + HardwareFeatureControl = 0x0020, + /// ATAPI: Asynchronous notification + AsyncNotification = 0x0020, + /// Supports in-order data delivery + InOrderData = 0x0010, + /// Supports initiating power management + InitPowerMgmt = 0x0008, + /// Supports DMA Setup auto-activation + DMASetup = 0x0004, + /// Supports non-zero buffer offsets + NonZeroBufferOffset = 0x0002, + /// MUST NOT be set + Clear = 0x0001 + } + + /// SCT Command Transport flags + [Flags] + public enum SCTCommandTransportBit : ushort + { + #pragma warning disable 1591 + Vendor15 = 0x8000, Vendor14 = 0x4000, Vendor13 = 0x2000, + Vendor12 = 0x1000, Reserved11 = 0x0800, Reserved10 = 0x0400, + Reserved09 = 0x0200, Reserved08 = 0x0100, Reserved07 = 0x0080, + Reserved06 = 0x0040, + #pragma warning restore 1591 + /// SCT Command Transport Data Tables supported + DataTables = 0x0020, + /// SCT Command Transport Features Control supported + FeaturesControl = 0x0010, + /// SCT Command Transport Error Recovery Control supported + ErrorRecoveryControl = 0x0008, + /// SCT Command Transport Write Same supported + WriteSame = 0x0004, + /// SCT Command Transport Long Sector Address supported + LongSectorAccess = 0x0002, + /// SCT Command Transport supported + Supported = 0x0001 + } + + /// Security status flag bits. + [Flags] + public enum SecurityStatusBit : ushort + { + #pragma warning disable 1591 + Reserved15 = 0x8000, Reserved14 = 0x4000, Reserved13 = 0x2000, + Reserved12 = 0x1000, Reserved11 = 0x0800, Reserved10 = 0x0400, + Reserved09 = 0x0200, + #pragma warning restore 1591 + /// Maximum security level + Maximum = 0x0100, + #pragma warning disable 1591 + Reserved07 = 0x0080, Reserved06 = 0x0040, + #pragma warning restore 1591 + /// Supports enhanced security erase + Enhanced = 0x0020, + /// Security count expired + Expired = 0x0010, + /// Security frozen + Frozen = 0x0008, + /// Security locked + Locked = 0x0004, + /// Security enabled + Enabled = 0x0002, + /// Security supported + Supported = 0x0001 + } + + /// Specific configuration flags + public enum SpecificConfigurationEnum : ushort + { + /// Device requires SET FEATURES to spin up and IDENTIFY DEVICE response is incomplete + RequiresSetIncompleteResponse = 0x37C8, + /// Device requires SET FEATURES to spin up and IDENTIFY DEVICE response is complete + RequiresSetCompleteResponse = 0x738C, + /// Device does not requires SET FEATURES to spin up and IDENTIFY DEVICE response is incomplete + NotRequiresSetIncompleteResponse = 0x8C73, + /// Device does not requires SET FEATURES to spin up and IDENTIFY DEVICE response is complete + NotRequiresSetCompleteResponse = 0xC837 + } + + /// Transfer mode flags + [Flags] + public enum TransferMode : byte + { + #pragma warning disable 1591 + Mode7 = 0x80, Mode6 = 0x40, Mode5 = 0x20, + Mode4 = 0x10, Mode3 = 0x08, Mode2 = 0x04, + Mode1 = 0x02, Mode0 = 0x01 + #pragma warning restore 1591 + } + + /// Trusted Computing flags + [Flags] + public enum TrustedComputingBit : ushort + { + /// MUST NOT be set + Clear = 0x8000, + /// MUST be set + Set = 0x4000, + #pragma warning disable 1591 + Reserved13 = 0x2000, Reserved12 = 0x1000, Reserved11 = 0x0800, + Reserved10 = 0x0400, Reserved09 = 0x0200, Reserved08 = 0x0100, + Reserved07 = 0x0080, Reserved06 = 0x0040, Reserved05 = 0x0020, + Reserved04 = 0x0010, Reserved03 = 0x0008, Reserved02 = 0x0004, + Reserved01 = 0x0002, + #pragma warning restore 1591 + /// Trusted Computing feature set is supported + TrustedComputing = 0x0001 + } + + /// IDENTIFY DEVICE decoded response + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 2)] + public struct IdentifyDevice + { + /// + /// Word 0 General device configuration On ATAPI devices: Bits 12 to 8 indicate device type as SCSI defined Bits 6 + /// to 5: 0 = Device shall set DRQ within 3 ms of receiving PACKET 1 = Device shall assert INTRQ when DRQ is set to one + /// 2 = Device shall set DRQ within 50 µs of receiving PACKET Bits 1 to 0: 0 = 12 byte command packet 1 = 16 byte + /// command packet CompactFlash is 0x848A (non magnetic, removable, not MFM, hardsector, and UltraFAST) + /// + public GeneralConfigurationBit GeneralConfiguration; + /// Word 1 Cylinders in default translation mode Obsoleted in ATA/ATAPI-6 + public ushort Cylinders; + /// Word 2 Specific configuration + public SpecificConfigurationEnum SpecificConfiguration; + /// Word 3 Heads in default translation mode Obsoleted in ATA/ATAPI-6 + public ushort Heads; + /// Word 4 Unformatted bytes per track in default translation mode Obsoleted in ATA-2 + public ushort UnformattedBPT; + /// Word 5 Unformatted bytes per sector in default translation mode Obsoleted in ATA-2 + public ushort UnformattedBPS; + /// Word 6 Sectors per track in default translation mode Obsoleted in ATA/ATAPI-6 + public ushort SectorsPerTrack; + /// Words 7 to 8 CFA: Number of sectors per card + public uint SectorsPerCard; + /// Word 9 Vendor unique Obsoleted in ATA/ATAPI-4 + public ushort VendorWord9; + /// Words 10 to 19 Device serial number, right justified, padded with spaces + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] + public string SerialNumber; + /// + /// Word 20 Manufacturer defined Obsoleted in ATA-2 0x0001 = single ported single sector buffer 0x0002 = dual + /// ported multi sector buffer 0x0003 = dual ported multi sector buffer with reading + /// + public ushort BufferType; + /// Word 21 Size of buffer in 512 byte increments Obsoleted in ATA-2 + public ushort BufferSize; + /// Word 22 Bytes of ECC available in READ/WRITE LONG commands Obsoleted in ATA/ATAPI-4 + public ushort EccBytes; + /// Words 23 to 26 Firmware revision, left justified, padded with spaces + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] + public string FirmwareRevision; + /// Words 27 to 46 Model number, left justified, padded with spaces + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)] + public string Model; + /// + /// Word 47 bits 7 to 0 Maximum number of sectors that can be transferred per interrupt on read and write multiple + /// commands + /// + public byte MultipleMaxSectors; + /// Word 47 bits 15 to 8 Vendor unique ATA/ATAPI-4 says it must be 0x80 + public byte VendorWord47; + /// + /// Word 48 ATA-1: Set to 1 if it can perform doubleword I/O ATA-2 to ATA/ATAPI-7: Reserved ATA8-ACS: Trusted + /// Computing feature set + /// + public TrustedComputingBit TrustedComputing; + /// Word 49 Capabilities + public CapabilitiesBit Capabilities; + /// Word 50 Capabilities + public CapabilitiesBit2 Capabilities2; + /// Word 51 bits 7 to 0 Vendor unique Obsoleted in ATA/ATAPI-4 + public byte VendorWord51; + /// Word 51 bits 15 to 8 Transfer timing mode in PIO Obsoleted in ATA/ATAPI-4 + public byte PIOTransferTimingMode; + /// Word 52 bits 7 to 0 Vendor unique Obsoleted in ATA/ATAPI-4 + public byte VendorWord52; + /// Word 52 bits 15 to 8 Transfer timing mode in DMA Obsoleted in ATA/ATAPI-4 + public byte DMATransferTimingMode; + /// Word 53 bits 7 to 0 Reports if words 54 to 58 are valid + public ExtendedIdentifyBit ExtendedIdentify; + /// Word 53 bits 15 to 8 Free-fall Control Sensitivity + public byte FreeFallSensitivity; + /// Word 54 Cylinders in current translation mode Obsoleted in ATA/ATAPI-6 + public ushort CurrentCylinders; + /// Word 55 Heads in current translation mode Obsoleted in ATA/ATAPI-6 + public ushort CurrentHeads; + /// Word 56 Sectors per track in current translation mode Obsoleted in ATA/ATAPI-6 + public ushort CurrentSectorsPerTrack; + /// Words 57 to 58 Total sectors currently user-addressable Obsoleted in ATA/ATAPI-6 + public uint CurrentSectors; + /// Word 59 bits 7 to 0 Number of sectors currently set to transfer on a READ/WRITE MULTIPLE command + public byte MultipleSectorNumber; + /// Word 59 bits 15 to 8 Indicates if is valid + public CapabilitiesBit3 Capabilities3; + /// Words 60 to 61 If drive supports LBA, how many sectors are addressable using LBA + public uint LBASectors; + /// + /// Word 62 bits 7 to 0 Single word DMA modes available Obsoleted in ATA/ATAPI-4 In ATAPI it's not obsolete, + /// indicates UDMA mode (UDMA7 is instead MDMA0) + /// + public TransferMode DMASupported; + /// + /// Word 62 bits 15 to 8 Single word DMA mode currently active Obsoleted in ATA/ATAPI-4 In ATAPI it's not + /// obsolete, bits 0 and 1 indicate MDMA mode+1, bit 10 indicates DMA is supported and bit 15 indicates DMADIR bit in + /// PACKET is required for DMA transfers + /// + public TransferMode DMAActive; + /// Word 63 bits 7 to 0 Multiword DMA modes available + public TransferMode MDMASupported; + /// Word 63 bits 15 to 8 Multiword DMA mode currently active + public TransferMode MDMAActive; + + /// Word 64 bits 7 to 0 Supported Advanced PIO transfer modes + public TransferMode APIOSupported; + /// Word 64 bits 15 to 8 Reserved + public byte ReservedWord64; + /// Word 65 Minimum MDMA transfer cycle time per word in nanoseconds + public ushort MinMDMACycleTime; + /// Word 66 Recommended MDMA transfer cycle time per word in nanoseconds + public ushort RecMDMACycleTime; + /// Word 67 Minimum PIO transfer cycle time without flow control in nanoseconds + public ushort MinPIOCycleTimeNoFlow; + /// Word 68 Minimum PIO transfer cycle time with IORDY flow control in nanoseconds + public ushort MinPIOCycleTimeFlow; + + /// Word 69 Additional supported + public CommandSetBit5 CommandSet5; + /// Word 70 Reserved + public ushort ReservedWord70; + /// Word 71 ATAPI: Typical time in ns from receipt of PACKET to release bus + public ushort PacketBusRelease; + /// Word 72 ATAPI: Typical time in ns from receipt of SERVICE to clear BSY + public ushort ServiceBusyClear; + /// Word 73 Reserved + public ushort ReservedWord73; + /// Word 74 Reserved + public ushort ReservedWord74; + + /// Word 75 Maximum Queue depth + public ushort MaxQueueDepth; + + /// Word 76 Serial ATA Capabilities + public SATACapabilitiesBit SATACapabilities; + /// Word 77 Serial ATA Additional Capabilities + public SATACapabilitiesBit2 SATACapabilities2; + + /// Word 78 Supported Serial ATA features + public SATAFeaturesBit SATAFeatures; + /// Word 79 Enabled Serial ATA features + public SATAFeaturesBit EnabledSATAFeatures; + + /// Word 80 Major version of ATA/ATAPI standard supported + public MajorVersionBit MajorVersion; + /// Word 81 Minimum version of ATA/ATAPI standard supported + public ushort MinorVersion; + + /// Word 82 Supported command/feature sets + public CommandSetBit CommandSet; + /// Word 83 Supported command/feature sets + public CommandSetBit2 CommandSet2; + /// Word 84 Supported command/feature sets + public CommandSetBit3 CommandSet3; + + /// Word 85 Enabled command/feature sets + public CommandSetBit EnabledCommandSet; + /// Word 86 Enabled command/feature sets + public CommandSetBit2 EnabledCommandSet2; + /// Word 87 Enabled command/feature sets + public CommandSetBit3 EnabledCommandSet3; + + /// Word 88 bits 7 to 0 Supported Ultra DMA transfer modes + public TransferMode UDMASupported; + /// Word 88 bits 15 to 8 Selected Ultra DMA transfer modes + public TransferMode UDMAActive; + + /// Word 89 Time required for security erase completion + public ushort SecurityEraseTime; + /// Word 90 Time required for enhanced security erase completion + public ushort EnhancedSecurityEraseTime; + /// Word 91 Current advanced power management value + public ushort CurrentAPM; + + /// Word 92 Master password revision code + public ushort MasterPasswordRevisionCode; + /// Word 93 Hardware reset result + public ushort HardwareResetResult; + + /// Word 94 bits 7 to 0 Current AAM value + public byte CurrentAAM; + /// Word 94 bits 15 to 8 Vendor's recommended AAM value + public byte RecommendedAAM; + + /// Word 95 Stream minimum request size + public ushort StreamMinReqSize; + /// Word 96 Streaming transfer time in DMA + public ushort StreamTransferTimeDMA; + /// Word 97 Streaming access latency in DMA and PIO + public ushort StreamAccessLatency; + /// Words 98 to 99 Streaming performance granularity + public uint StreamPerformanceGranularity; + + /// Words 100 to 103 48-bit LBA addressable sectors + public ulong LBA48Sectors; + + /// Word 104 Streaming transfer time in PIO + public ushort StreamTransferTimePIO; + + /// Word 105 Maximum number of 512-byte block per DATA SET MANAGEMENT command + public ushort DataSetMgmtSize; + + /// + /// Word 106 Bit 15 should be zero Bit 14 should be one Bit 13 set indicates device has multiple logical sectors + /// per physical sector Bit 12 set indicates logical sector has more than 256 words (512 bytes) Bits 11 to 4 are + /// reserved Bits 3 to 0 indicate power of two of logical sectors per physical sector + /// + public ushort PhysLogSectorSize; + + /// Word 107 Interseek delay for ISO-7779 acoustic testing, in microseconds + public ushort InterseekDelay; + + /// Words 108 to 111 World Wide Name + public ulong WWN; + + /// Words 112 to 115 Reserved for WWN extension to 128 bit + public ulong WWNExtension; + + /// Word 116 Reserved for technical report + public ushort ReservedWord116; + + /// Words 117 to 118 Words per logical sector + public uint LogicalSectorWords; + + /// Word 119 Supported command/feature sets + public CommandSetBit4 CommandSet4; + /// Word 120 Supported command/feature sets + public CommandSetBit4 EnabledCommandSet4; + + /// Words 121 to 125 Reserved + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] + public ushort[] ReservedWords121; + + /// Word 126 ATAPI byte count limit + public ushort ATAPIByteCount; + + /// + /// Word 127 Removable Media Status Notification feature set support Bits 15 to 2 are reserved Bits 1 to 0 must be + /// 0 for not supported or 1 for supported. 2 and 3 are reserved. Obsoleted in ATA8-ACS + /// + public ushort RemovableStatusSet; + + /// Word 128 Security status + public SecurityStatusBit SecurityStatus; + + /// Words 129 to 159 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 31)] + public ushort[] ReservedWords129; + + /// + /// Word 160 CFA power mode Bit 15 must be set Bit 13 indicates mode 1 is required for one or more commands Bit 12 + /// indicates mode 1 is disabled Bits 11 to 0 indicates maximum current in mA + /// + public ushort CFAPowerMode; + + /// Words 161 to 167 Reserved for CFA + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] + public ushort[] ReservedCFA; + + /// Word 168 Bits 15 to 4, reserved Bits 3 to 0, device nominal form factor + public DeviceFormFactorEnum DeviceFormFactor; + /// Word 169 DATA SET MANAGEMENT support + public DataSetMgmtBit DataSetMgmt; + /// Words 170 to 173 Additional product identifier + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] + public string AdditionalPID; + + /// Word 174 Reserved + public ushort ReservedWord174; + /// Word 175 Reserved + public ushort ReservedWord175; + + /// Words 176 to 195 Current media serial number + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)] + public string MediaSerial; + /// Words 196 to 205 Current media manufacturer + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] + public string MediaManufacturer; + + /// Word 206 SCT Command Transport features + public SCTCommandTransportBit SCTCommandTransport; + + /// Word 207 Reserved for CE-ATA + public ushort ReservedCEATAWord207; + /// Word 208 Reserved for CE-ATA + public ushort ReservedCEATAWord208; + + /// + /// Word 209 Alignment of logical block within a larger physical block Bit 15 shall be cleared to zero Bit 14 + /// shall be set to one Bits 13 to 0 indicate logical sector offset within the first physical sector + /// + public ushort LogicalAlignment; + + /// Words 210 to 211 Write/Read/Verify sector count mode 3 only + public uint WRVSectorCountMode3; + /// Words 212 to 213 Write/Read/Verify sector count mode 2 only + public uint WRVSectorCountMode2; + + /// + /// Word 214 NV Cache capabilities Bits 15 to 12 feature set version Bits 11 to 18 power mode feature set version + /// Bits 7 to 5 reserved Bit 4 feature set enabled Bits 3 to 2 reserved Bit 1 power mode feature set enabled Bit 0 + /// power mode feature set supported + /// + public ushort NVCacheCaps; + /// Words 215 to 216 NV Cache Size in Logical BLocks + public uint NVCacheSize; + /// Word 217 Nominal media rotation rate In ACS-1 meant NV Cache read speed in MB/s + public ushort NominalRotationRate; + /// Word 218 NV Cache write speed in MB/s Reserved since ACS-2 + public ushort NVCacheWriteSpeed; + /// Word 219 bits 7 to 0 Estimated device spin up in seconds + public byte NVEstimatedSpinUp; + /// Word 219 bits 15 to 8 NV Cache reserved + public byte NVReserved; + + /// Word 220 bits 7 to 0 Write/Read/Verify feature set current mode + public byte WRVMode; + /// Word 220 bits 15 to 8 Reserved + public byte WRVReserved; + + /// Word 221 Reserved + public ushort ReservedWord221; + + /// + /// Word 222 Transport major revision number Bits 15 to 12 indicate transport type. 0 parallel, 1 serial, 0xE + /// PCIe. Bits 11 to 0 indicate revision + /// + public ushort TransportMajorVersion; + /// Word 223 Transport minor revision number + public ushort TransportMinorVersion; + + /// Words 224 to 229 Reserved for CE-ATA + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + public ushort[] ReservedCEATA224; + + /// Words 230 to 233 48-bit LBA if Word 69 bit 3 is set + public ulong ExtendedUserSectors; + + /// Word 234 Minimum number of 512 byte units per DOWNLOAD MICROCODE mode 3 + public ushort MinDownloadMicroMode3; + /// Word 235 Maximum number of 512 byte units per DOWNLOAD MICROCODE mode 3 + public ushort MaxDownloadMicroMode3; + + /// Words 236 to 254 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 19)] + public ushort[] ReservedWords; + + /// Word 255 bits 7 to 0 Should be 0xA5 + public byte Signature; + /// Word 255 bits 15 to 8 Checksum + public byte Checksum; + } + + /// Decodes a raw IDENTIFY DEVICE response + /// Raw IDENTIFY DEVICE response + /// Decoded IDENTIFY DEVICE + public static IdentifyDevice? Decode(byte[] IdentifyDeviceResponse) + { + if(IdentifyDeviceResponse == null) + return null; + + if(IdentifyDeviceResponse.Length != 512) + { + AaruConsole.DebugWriteLine("ATA/ATAPI IDENTIFY decoder", + "IDENTIFY response is different than 512 bytes, not decoding."); + + return null; + } + + IdentifyDevice ATAID = Marshal.ByteArrayToStructureLittleEndian(IdentifyDeviceResponse); + + ATAID.WWN = DescrambleWWN(ATAID.WWN); + ATAID.WWNExtension = DescrambleWWN(ATAID.WWNExtension); + + ATAID.SerialNumber = DescrambleATAString(IdentifyDeviceResponse, 10 * 2, 20); + ATAID.FirmwareRevision = DescrambleATAString(IdentifyDeviceResponse, 23 * 2, 8); + ATAID.Model = DescrambleATAString(IdentifyDeviceResponse, 27 * 2, 40); + ATAID.AdditionalPID = DescrambleATAString(IdentifyDeviceResponse, 170 * 2, 8); + ATAID.MediaSerial = DescrambleATAString(IdentifyDeviceResponse, 176 * 2, 40); + ATAID.MediaManufacturer = DescrambleATAString(IdentifyDeviceResponse, 196 * 2, 20); + + return ATAID; + } + + /// Encodes a raw IDENTIFY DEVICE response + /// Decoded IDENTIFY DEVICE + /// Raw IDENTIFY DEVICE response + public static byte[] Encode(IdentifyDevice? identify) + { + if(identify is null) + return null; + + IdentifyDevice ataId = identify.Value; + + ataId.WWN = DescrambleWWN(ataId.WWN); + ataId.WWNExtension = DescrambleWWN(ataId.WWNExtension); + + byte[] buf = new byte[512]; + IntPtr ptr = System.Runtime.InteropServices.Marshal.AllocHGlobal(512); + System.Runtime.InteropServices.Marshal.StructureToPtr(ataId, ptr, false); + System.Runtime.InteropServices.Marshal.Copy(ptr, buf, 0, 512); + System.Runtime.InteropServices.Marshal.FreeHGlobal(ptr); + + byte[] str = ScrambleATAString(ataId.SerialNumber, 20); + Array.Copy(str, 0, buf, 10 * 2, 20); + str = ScrambleATAString(ataId.FirmwareRevision, 8); + Array.Copy(str, 0, buf, 23 * 2, 8); + str = ScrambleATAString(ataId.Model, 40); + Array.Copy(str, 0, buf, 27 * 2, 40); + str = ScrambleATAString(ataId.AdditionalPID, 8); + Array.Copy(str, 0, buf, 170 * 2, 8); + str = ScrambleATAString(ataId.MediaSerial, 40); + Array.Copy(str, 0, buf, 176 * 2, 40); + str = ScrambleATAString(ataId.MediaManufacturer, 20); + Array.Copy(str, 0, buf, 196 * 2, 20); + + return buf; + } + + static ulong DescrambleWWN(ulong WWN) + { + byte[] qwb = BitConverter.GetBytes(WWN); + byte[] qword = new byte[8]; + + qword[7] = qwb[1]; + qword[6] = qwb[0]; + qword[5] = qwb[3]; + qword[4] = qwb[2]; + qword[3] = qwb[5]; + qword[2] = qwb[4]; + qword[1] = qwb[7]; + qword[0] = qwb[6]; + + return BitConverter.ToUInt64(qword, 0); + } + + static string DescrambleATAString(IList buffer, int offset, int length) + { + byte[] outbuf = buffer[offset + length - 1] != 0x00 ? new byte[length + 1] : new byte[length]; + + for(int i = 0; i < length; i += 2) + { + outbuf[i] = buffer[offset + i + 1]; + outbuf[i + 1] = buffer[offset + i]; + } + + string outStr = StringHandlers.CToString(outbuf); + + return outStr.Trim(); + } + + static byte[] ScrambleATAString(string str, int length) + { + byte[] buf = new byte[length]; + + for(int i = 0; i < length; i++) + buf[i] = 0x20; + + if(str is null) + return buf; + + byte[] bytes = Encoding.ASCII.GetBytes(str); + + if(bytes.Length % 2 != 0) + { + byte[] tmp = new byte[bytes.Length + 1]; + tmp[^1] = 0x20; + Array.Copy(bytes, 0, tmp, 0, bytes.Length); + bytes = tmp; + } + + for(int i = 0; i < bytes.Length; i += 2) + { + buf[i] = bytes[i + 1]; + buf[i + 1] = bytes[i]; + } + + return buf; + } + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Structs/Devices/SCSI/Enums.cs b/Aaru.CommonTypes/Structs/Devices/SCSI/Enums.cs new file mode 100644 index 000000000..5cbf63f8f --- /dev/null +++ b/Aaru.CommonTypes/Structs/Devices/SCSI/Enums.cs @@ -0,0 +1,245 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Enums.cs +// Author(s) : Natalia Portillo +// +// Component : Common structures for SCSI devices. +// +// --[ Description ] ---------------------------------------------------------- +// +// Contains various SCSI enumerations. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.CommonTypes.Structs.Devices.SCSI +{ + /// List of known SCSI peripheral qualifiers + public enum PeripheralQualifiers : byte + { + /// Peripheral qualifier: Device is connected and supported + Supported = 0x00, + /// Peripheral qualifier: Device is supported but not connected + Unconnected = 0x01, + /// Peripheral qualifier: Reserved value + Reserved = 0x02, + /// Peripheral qualifier: Device is connected but unsupported + Unsupported = 0x03, + /// Peripheral qualifier: Vendor values: 0x04, 0x05, 0x06 and 0x07 + VendorMask = 0x04 + } + + /// List of known peripheral device types + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum PeripheralDeviceTypes : byte + { + /// Direct-access device + DirectAccess = 0x00, + /// Sequential-access device + SequentialAccess = 0x01, + /// Printer device + PrinterDevice = 0x02, + /// Processor device + ProcessorDevice = 0x03, + /// Write-once device + WriteOnceDevice = 0x04, + /// CD-ROM/DVD/etc device + MultiMediaDevice = 0x05, + /// Scanner device + ScannerDevice = 0x06, + /// Optical memory device + OpticalDevice = 0x07, + /// Medium change device + MediumChangerDevice = 0x08, + /// Communications device + CommsDevice = 0x09, + /// Graphics arts pre-press device (defined in ASC IT8) + PrePressDevice1 = 0x0A, + /// Graphics arts pre-press device (defined in ASC IT8) + PrePressDevice2 = 0x0B, + /// Array controller device + ArrayControllerDevice = 0x0C, + /// Enclosure services device + EnclosureServiceDevice = 0x0D, + /// Simplified direct-access device + SimplifiedDevice = 0x0E, + /// Optical card reader/writer device + OCRWDevice = 0x0F, + /// Bridging Expanders + BridgingExpander = 0x10, + /// Object-based Storage Device + ObjectDevice = 0x11, + /// Automation/Drive Interface + ADCDevice = 0x12, + /// Security Manager Device + SCSISecurityManagerDevice = 0x13, + /// Host managed zoned block device + SCSIZonedBlockDevice = 0x14, + /// Well known logical unit + WellKnownDevice = 0x1E, + /// Unknown or no device type + UnknownDevice = 0x1F + } + + /// List of known ANSI SCSI standards + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum ANSIVersions : byte + { + /// Device does not claim conformance to any ANSI version + ANSINoVersion = 0x00, + /// Device complies with ANSI X3.131:1986 + ANSI1986Version = 0x01, + /// Device complies with ANSI X3.131:1994 + ANSI1994Version = 0x02, + /// Device complies with ANSI X3.301:1997 + ANSI1997Version = 0x03, + /// Device complies with ANSI X3.351:2001 + ANSI2001Version = 0x04, + /// Device complies with ANSI X3.408:2005. + ANSI2005Version = 0x05, + /// Device complies with SPC-4 + ANSI2008Version = 0x06 + } + + /// List of known ECMA SCSI standards + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum ECMAVersions : byte + { + /// Device does not claim conformance to any ECMA version + ECMANoVersion = 0x00, + /// Device complies with a ECMA-111 standard + ECMA111 = 0x01 + } + + /// List of known ISO SCSI standards + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum ISOVersions : byte + { + /// Device does not claim conformance to any ISO/IEC version + ISONoVersion = 0x00, + /// Device complies with ISO/IEC 9316:1995 + ISO1995Version = 0x02 + } + + /// List of known SCSI Parallel Interface clocking types + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum SPIClocking : byte + { + /// Supports only ST + ST = 0x00, + /// Supports only DT + DT = 0x01, + /// Reserved value + Reserved = 0x02, + /// Supports ST and DT + STandDT = 0x03 + } + + /// List of known TGPS values + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum TGPSValues : byte + { + /// Asymmetrical access not supported + NotSupported = 0x00, + /// Only implicit asymmetrical access is supported + OnlyImplicit = 0x01, + /// Only explicit asymmetrical access is supported + OnlyExplicit = 0x02, + /// Both implicit and explicit asymmetrical access are supported + Both = 0x03 + } + + /// List of known SCSI protocols + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum ProtocolIdentifiers : byte + { + /// Fibre Channel + FibreChannel = 0, + /// Parallel SCSI + SCSI = 1, + /// SSA + SSA = 2, + /// IEEE-1394 + Firewire = 3, + /// SCSI Remote Direct Memory Access Protocol + RDMAP = 4, + /// Internet SCSI + iSCSI = 5, + /// Serial SCSI + SAS = 6, + /// Automation/Drive Interface Transport Protocol + ADT = 7, + /// AT Attachment Interface (ATA/ATAPI) + ATA = 8, + /// USB Attached SCSI + UAS = 9, + /// SCSI over PCI Express + SCSIe = 10, + /// PCI Express + PCIe = 11, + /// No specific protocol + NoProtocol = 15 + } + + /// List of known SCSI definitions + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum ScsiDefinitions : byte + { + /// Unknown + Current = 0, + /// SCSI-1 + SCSI1 = 1, + /// Unknown + CCS = 2, + /// SCSI-2 + SCSI2 = 3, + /// SCSI-3 + SCSI3 = 4 + } + + /// List of known SCSI physical interfaces + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum PhysicalInterfaces : uint + { + /// Unspecified physical interface + Unspecified = 0, + /// SCSI + SCSI = 1, + /// ATAPI + ATAPI = 2, + /// IEEE-1394/1995 + IEEE1394 = 3, + /// IEEE-1394A + IEEE1394A = 4, + /// Fibre Channel + FC = 5, + /// IEEE-1394B + IEEE1394B = 6, + /// Serial ATAPI + SerialATAPI = 7, + /// USB + USB = 8, + /// Vendor unique + Vendor = 0xFFFF + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Structs/Devices/SCSI/Inquiry.cs b/Aaru.CommonTypes/Structs/Devices/SCSI/Inquiry.cs new file mode 100644 index 000000000..b6f602918 --- /dev/null +++ b/Aaru.CommonTypes/Structs/Devices/SCSI/Inquiry.cs @@ -0,0 +1,788 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Inquiry.cs +// Author(s) : Natalia Portillo +// +// Component : Common structures for SCSI devices. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines a high level interpretation of the SCSI INQUIRY response. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Aaru.Console; + +namespace Aaru.CommonTypes.Structs.Devices.SCSI +{ + /// + /// Information from the following standards: T9/375-D revision 10l T10/995-D revision 10 T10/1236-D revision 20 + /// T10/1416-D revision 23 T10/1731-D revision 16 T10/502 revision 05 RFC 7144 ECMA-111 + /// + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public struct Inquiry + { + /// Peripheral qualifier Byte 0, bits 7 to 5 + public byte PeripheralQualifier; + /// Peripheral device type Byte 0, bits 4 to 0 + public byte PeripheralDeviceType; + /// Removable device Byte 1, bit 7 + public bool RMB; + /// SCSI-1 vendor-specific qualification codes Byte 1, bits 6 to 0 + public byte DeviceTypeModifier; + /// ISO/IEC SCSI Standard Version Byte 2, bits 7 to 6, mask = 0xC0, >> 6 + public byte ISOVersion; + /// ECMA SCSI Standard Version Byte 2, bits 5 to 3, mask = 0x38, >> 3 + public byte ECMAVersion; + /// ANSI SCSI Standard Version Byte 2, bits 2 to 0, mask = 0x07 + public byte ANSIVersion; + /// Asynchronous Event Reporting Capability supported Byte 3, bit 7 + public bool AERC; + /// Device supports TERMINATE TASK command Byte 3, bit 6 + public bool TrmTsk; + /// Supports setting Normal ACA Byte 3, bit 5 + public bool NormACA; + /// Supports LUN hierarchical addressing Byte 3, bit 4 + public bool HiSup; + /// Responde data format Byte 3, bit 3 to 0 + public byte ResponseDataFormat; + /// Lenght of total INQUIRY response minus 4 Byte 4 + public byte AdditionalLength; + /// Device contains an embedded storage array controller Byte 5, bit 7 + public bool SCCS; + /// Device contains an Access Control Coordinator Byte 5, bit 6 + public bool ACC; + /// Supports asymetrical logical unit access Byte 5, bits 5 to 4 + public byte TPGS; + /// Supports third-party copy commands Byte 5, bit 3 + public bool ThreePC; + /// Reserved Byte 5, bits 2 to 1 + public byte Reserved2; + /// Supports protection information Byte 5, bit 0 + public bool Protect; + /// Supports basic queueing Byte 6, bit 7 + public bool BQue; + /// Device contains an embedded enclosure services component Byte 6, bit 6 + public bool EncServ; + /// Vendor-specific Byte 6, bit 5 + public bool VS1; + /// Multi-port device Byte 6, bit 4 + public bool MultiP; + /// Device contains or is attached to a medium changer Byte 6, bit 3 + public bool MChngr; + /// Device supports request and acknowledge handshakes Byte 6, bit 2 + public bool ACKREQQ; + /// Supports 32-bit wide SCSI addresses Byte 6, bit 1 + public bool Addr32; + /// Supports 16-bit wide SCSI addresses Byte 6, bit 0 + public bool Addr16; + /// Device supports relative addressing Byte 7, bit 7 + public bool RelAddr; + /// Supports 32-bit wide data transfers Byte 7, bit 6 + public bool WBus32; + /// Supports 16-bit wide data transfers Byte 7, bit 5 + public bool WBus16; + /// Supports synchronous data transfer Byte 7, bit 4 + public bool Sync; + /// Supports linked commands Byte 7, bit 3 + public bool Linked; + /// Supports CONTINUE TASK and TARGET TRANSFER DISABLE commands Byte 7, bit 2 + public bool TranDis; + /// Supports TCQ queue Byte 7, bit 1 + public bool CmdQue; + /// Indicates that the devices responds to RESET with soft reset Byte 7, bit 0 + public bool SftRe; + /// Vendor identification Bytes 8 to 15 + public byte[] VendorIdentification; + /// Product identification Bytes 16 to 31 + public byte[] ProductIdentification; + /// Product revision level Bytes 32 to 35 + public byte[] ProductRevisionLevel; + /// Vendor-specific data Bytes 36 to 55 + public byte[] VendorSpecific; + /// Byte 56, bits 7 to 4 + public byte Reserved3; + /// Supported SPI clocking Byte 56, bits 3 to 2 + public byte Clocking; + /// Device supports Quick Arbitration and Selection Byte 56, bit 1 + public bool QAS; + /// Supports information unit transfers Byte 56, bit 0 + public bool IUS; + /// Reserved Byte 57 + public byte Reserved4; + /// Array of version descriptors Bytes 58 to 73 + public ushort[] VersionDescriptors; + /// Reserved Bytes 74 to 95 + public byte[] Reserved5; + /// Reserved Bytes 96 to end + public byte[] VendorSpecific2; + + // Per DLT4000/DLT4500/DLT4700 Cartridge Tape Subsystem Product Manual + + #region Quantum vendor unique inquiry data structure + /// Means that the INQUIRY response contains 56 bytes or more, so this data has been filled + public bool QuantumPresent; + /// The product family. Byte 36, bits 7 to 5 + public byte Qt_ProductFamily; + /// The released firmware. Byte 36, bits 4 to 0 + public byte Qt_ReleasedFirmware; + /// The firmware major version. Byte 37 + public byte Qt_FirmwareMajorVersion; + /// The firmware minor version. Byte 38 + public byte Qt_FirmwareMinorVersion; + /// The EEPROM format major version. Byte 39 + public byte Qt_EEPROMFormatMajorVersion; + /// The EEPROM format minor version. Byte 40 + public byte Qt_EEPROMFormatMinorVersion; + /// The firmware personality. Byte 41 + public byte Qt_FirmwarePersonality; + /// The firmware sub personality. Byte 42 + public byte Qt_FirmwareSubPersonality; + /// The tape directory format version. Byte 43 + public byte Qt_TapeDirectoryFormatVersion; + /// The controller hardware version. Byte 44 + public byte Qt_ControllerHardwareVersion; + /// The drive EEPROM version. Byte 45 + public byte Qt_DriveEEPROMVersion; + /// The drive hardware version. Byte 46 + public byte Qt_DriveHardwareVersion; + /// The media loader firmware version. Byte 47 + public byte Qt_MediaLoaderFirmwareVersion; + /// The media loader hardware version. Byte 48 + public byte Qt_MediaLoaderHardwareVersion; + /// The media loader mechanical version. Byte 49 + public byte Qt_MediaLoaderMechanicalVersion; + /// Is a media loader present? Byte 50 + public bool Qt_MediaLoaderPresent; + /// Is a library present? Byte 51 + public bool Qt_LibraryPresent; + /// The module revision. Bytes 52 to 55 + public byte[] Qt_ModuleRevision; + #endregion Quantum vendor unique inquiry data structure + + #region IBM vendor unique inquiry data structure + /// Means that the INQUIRY response contains 56 bytes or more, so this data has been filled + public bool IBMPresent; + /// Drive is not capable of automation Byte 36 bit 0 + public bool IBM_AutDis; + /// If not zero, limit in MB/s = Max * (this / 256) Byte 37 + public byte IBM_PerformanceLimit; + /// Byte 41 + public byte IBM_OEMSpecific; + #endregion IBM vendor unique inquiry data structure + + #region HP vendor unique inquiry data structure + /// Means that the INQUIRY response contains 49 bytes or more, so this data has been filled + public bool HPPresent; + /// WORM version Byte 40 bits 7 to 1 + public byte HP_WORMVersion; + /// WORM supported Byte 40 bit 0 + public bool HP_WORM; + /// Bytes 43 to 48 + public byte[] HP_OBDR; + #endregion HP vendor unique inquiry data structure + + #region Seagate vendor unique inquiry data structure + /// Means that bytes 36 to 43 are filled + public bool SeagatePresent; + /// Drive Serial Number Bytes 36 to 43 + public byte[] Seagate_DriveSerialNumber; + /// Means that bytes 96 to 143 are filled + public bool Seagate2Present; + /// Contains Seagate copyright notice Bytes 96 to 143 + public byte[] Seagate_Copyright; + /// Means that bytes 144 to 147 are filled + public bool Seagate3Present; + /// Reserved Seagate field Bytes 144 to 147 + public byte[] Seagate_ServoPROMPartNo; + #endregion Seagate vendor unique inquiry data structure + + #region Kreon vendor unique inquiry data structure + /// Means that firmware is Kreon + public bool KreonPresent; + /// Kreon identifier Bytes 36 to 40 + public byte[] KreonIdentifier; + /// Kreon just a 0x20 Bytes 41 + public byte KreonSpace; + /// Kreon version string Bytes 42 to 46 + public byte[] KreonVersion; + #endregion Kreon vendor unique inquiry data structure + + #region Sony Hi-MD data + /// Set if Hi-MD signature is present + public bool IsHiMD; + /// Hi-MD signature, bytes 36 to 44 + public byte[] HiMDSignature; + /// Unknown data, bytes 44 to 55 + public byte[] HiMDSpecific; + #endregion Sony Hi-MD data + + static readonly byte[] HiMDSignatureContents = + { + 0x48, 0x69, 0x2D, 0x4D, 0x44, 0x20, 0x20, 0x20 + }; + + /// Decodes a SCSI INQUIRY response + /// INQUIRY raw response data + /// Decoded SCSI INQUIRY + #region Public methods + public static Inquiry? Decode(byte[] SCSIInquiryResponse) + { + if(SCSIInquiryResponse == null) + return null; + + if(SCSIInquiryResponse.Length < 36 && + SCSIInquiryResponse.Length != 5) + { + AaruConsole.DebugWriteLine("SCSI INQUIRY decoder", + "INQUIRY response is {0} bytes, less than minimum of 36 bytes, decoded data can be incorrect, not decoding.", + SCSIInquiryResponse.Length); + + return null; + } + + if(SCSIInquiryResponse.Length < SCSIInquiryResponse[4] + 4 && + SCSIInquiryResponse.Length != SCSIInquiryResponse[4]) + { + AaruConsole.DebugWriteLine("SCSI INQUIRY decoder", + "INQUIRY response length ({0} bytes) is different than specified in length field ({1} bytes), decoded data can be incorrect, not decoding.", + SCSIInquiryResponse.Length, SCSIInquiryResponse[4] + 4); + + return null; + } + + var decoded = new Inquiry(); + + if(SCSIInquiryResponse.Length >= 1) + { + decoded.PeripheralQualifier = (byte)((SCSIInquiryResponse[0] & 0xE0) >> 5); + decoded.PeripheralDeviceType = (byte)(SCSIInquiryResponse[0] & 0x1F); + } + + if(SCSIInquiryResponse.Length >= 2) + { + decoded.RMB = Convert.ToBoolean(SCSIInquiryResponse[1] & 0x80); + decoded.DeviceTypeModifier = (byte)(SCSIInquiryResponse[1] & 0x7F); + } + + if(SCSIInquiryResponse.Length >= 3) + { + decoded.ISOVersion = (byte)((SCSIInquiryResponse[2] & 0xC0) >> 6); + decoded.ECMAVersion = (byte)((SCSIInquiryResponse[2] & 0x38) >> 3); + decoded.ANSIVersion = (byte)(SCSIInquiryResponse[2] & 0x07); + } + + if(SCSIInquiryResponse.Length >= 4) + { + decoded.AERC = Convert.ToBoolean(SCSIInquiryResponse[3] & 0x80); + decoded.TrmTsk = Convert.ToBoolean(SCSIInquiryResponse[3] & 0x40); + decoded.NormACA = Convert.ToBoolean(SCSIInquiryResponse[3] & 0x20); + decoded.HiSup = Convert.ToBoolean(SCSIInquiryResponse[3] & 0x10); + decoded.ResponseDataFormat = (byte)(SCSIInquiryResponse[3] & 0x07); + } + + if(SCSIInquiryResponse.Length >= 5) + decoded.AdditionalLength = SCSIInquiryResponse[4]; + + if(SCSIInquiryResponse.Length >= 6) + { + decoded.SCCS = Convert.ToBoolean(SCSIInquiryResponse[5] & 0x80); + decoded.ACC = Convert.ToBoolean(SCSIInquiryResponse[5] & 0x40); + decoded.TPGS = (byte)((SCSIInquiryResponse[5] & 0x30) >> 4); + decoded.ThreePC = Convert.ToBoolean(SCSIInquiryResponse[5] & 0x08); + decoded.Reserved2 = (byte)((SCSIInquiryResponse[5] & 0x06) >> 1); + decoded.Protect = Convert.ToBoolean(SCSIInquiryResponse[5] & 0x01); + } + + if(SCSIInquiryResponse.Length >= 7) + { + decoded.BQue = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x80); + decoded.EncServ = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x40); + decoded.VS1 = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x20); + decoded.MultiP = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x10); + decoded.MChngr = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x08); + decoded.ACKREQQ = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x04); + decoded.Addr32 = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x02); + decoded.Addr16 = Convert.ToBoolean(SCSIInquiryResponse[6] & 0x01); + } + + if(SCSIInquiryResponse.Length >= 8) + { + decoded.RelAddr = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x80); + decoded.WBus32 = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x40); + decoded.WBus16 = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x20); + decoded.Sync = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x10); + decoded.Linked = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x08); + decoded.TranDis = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x04); + decoded.CmdQue = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x02); + decoded.SftRe = Convert.ToBoolean(SCSIInquiryResponse[7] & 0x01); + } + + if(SCSIInquiryResponse.Length >= 16) + { + decoded.VendorIdentification = new byte[8]; + Array.Copy(SCSIInquiryResponse, 8, decoded.VendorIdentification, 0, 8); + } + + if(SCSIInquiryResponse.Length >= 32) + { + decoded.ProductIdentification = new byte[16]; + Array.Copy(SCSIInquiryResponse, 16, decoded.ProductIdentification, 0, 16); + } + + if(SCSIInquiryResponse.Length >= 36) + { + decoded.ProductRevisionLevel = new byte[4]; + Array.Copy(SCSIInquiryResponse, 32, decoded.ProductRevisionLevel, 0, 4); + } + + if(SCSIInquiryResponse.Length >= 44) + { + // Seagate 1 + decoded.SeagatePresent = true; + decoded.Seagate_DriveSerialNumber = new byte[8]; + Array.Copy(SCSIInquiryResponse, 36, decoded.Seagate_DriveSerialNumber, 0, 8); + + // Hi-MD + decoded.HiMDSignature = new byte[8]; + Array.Copy(SCSIInquiryResponse, 36, decoded.HiMDSignature, 0, 8); + decoded.IsHiMD = HiMDSignatureContents.SequenceEqual(decoded.HiMDSignature); + } + + if(SCSIInquiryResponse.Length >= 46) + { + // Kreon + decoded.KreonIdentifier = new byte[5]; + Array.Copy(SCSIInquiryResponse, 36, decoded.KreonIdentifier, 0, 5); + decoded.KreonSpace = SCSIInquiryResponse[41]; + decoded.KreonVersion = new byte[5]; + Array.Copy(SCSIInquiryResponse, 42, decoded.KreonVersion, 0, 5); + + if(decoded.KreonSpace == 0x20 && + decoded.KreonIdentifier.SequenceEqual(new byte[] + { + 0x4B, 0x52, 0x45, 0x4F, 0x4E + })) + decoded.KreonPresent = true; + } + + if(SCSIInquiryResponse.Length >= 49) + { + // HP + decoded.HPPresent = true; + decoded.HP_WORM |= (SCSIInquiryResponse[40] & 0x01) == 0x01; + decoded.HP_WORMVersion = (byte)((SCSIInquiryResponse[40] & 0x7F) >> 1); + decoded.HP_OBDR = new byte[6]; + Array.Copy(SCSIInquiryResponse, 43, decoded.HP_OBDR, 0, 6); + } + + if(SCSIInquiryResponse.Length >= 56) + { + if(decoded.IsHiMD) + { + decoded.HiMDSpecific = new byte[12]; + Array.Copy(SCSIInquiryResponse, 44, decoded.HiMDSpecific, 0, 12); + } + else + { + decoded.VendorSpecific = new byte[20]; + Array.Copy(SCSIInquiryResponse, 36, decoded.VendorSpecific, 0, 20); + } + + // Quantum + decoded.QuantumPresent = true; + decoded.Qt_ProductFamily = (byte)((SCSIInquiryResponse[36] & 0xF0) >> 4); + decoded.Qt_ReleasedFirmware = (byte)(SCSIInquiryResponse[36] & 0x0F); + decoded.Qt_FirmwareMajorVersion = SCSIInquiryResponse[37]; + decoded.Qt_FirmwareMinorVersion = SCSIInquiryResponse[38]; + decoded.Qt_EEPROMFormatMajorVersion = SCSIInquiryResponse[39]; + decoded.Qt_EEPROMFormatMinorVersion = SCSIInquiryResponse[40]; + decoded.Qt_FirmwarePersonality = SCSIInquiryResponse[41]; + decoded.Qt_FirmwareSubPersonality = SCSIInquiryResponse[42]; + decoded.Qt_TapeDirectoryFormatVersion = SCSIInquiryResponse[43]; + decoded.Qt_ControllerHardwareVersion = SCSIInquiryResponse[44]; + decoded.Qt_DriveEEPROMVersion = SCSIInquiryResponse[45]; + decoded.Qt_DriveHardwareVersion = SCSIInquiryResponse[46]; + decoded.Qt_MediaLoaderFirmwareVersion = SCSIInquiryResponse[47]; + decoded.Qt_MediaLoaderHardwareVersion = SCSIInquiryResponse[48]; + decoded.Qt_MediaLoaderMechanicalVersion = SCSIInquiryResponse[49]; + decoded.Qt_MediaLoaderPresent = SCSIInquiryResponse[50] > 0; + decoded.Qt_LibraryPresent = SCSIInquiryResponse[51] > 0; + decoded.Qt_ModuleRevision = new byte[4]; + Array.Copy(SCSIInquiryResponse, 52, decoded.Qt_ModuleRevision, 0, 4); + + // IBM + decoded.IBMPresent = true; + decoded.IBM_AutDis |= (SCSIInquiryResponse[36] & 0x01) == 0x01; + decoded.IBM_PerformanceLimit = SCSIInquiryResponse[37]; + decoded.IBM_OEMSpecific = SCSIInquiryResponse[41]; + } + + if(SCSIInquiryResponse.Length >= 57) + { + decoded.Reserved3 = (byte)((SCSIInquiryResponse[56] & 0xF0) >> 4); + decoded.Clocking = (byte)((SCSIInquiryResponse[56] & 0x0C) >> 2); + decoded.QAS = Convert.ToBoolean(SCSIInquiryResponse[56] & 0x02); + decoded.IUS = Convert.ToBoolean(SCSIInquiryResponse[56] & 0x01); + } + + if(SCSIInquiryResponse.Length >= 58) + decoded.Reserved4 = SCSIInquiryResponse[57]; + + if(SCSIInquiryResponse.Length >= 60) + { + int descriptorsNo; + + if(SCSIInquiryResponse.Length >= 74) + descriptorsNo = 8; + else + descriptorsNo = (SCSIInquiryResponse.Length - 58) / 2; + + decoded.VersionDescriptors = new ushort[descriptorsNo]; + + for(int i = 0; i < descriptorsNo; i++) + decoded.VersionDescriptors[i] = BitConverter.ToUInt16(SCSIInquiryResponse, 58 + (i * 2)); + } + + if(SCSIInquiryResponse.Length >= 75 && + SCSIInquiryResponse.Length < 96) + { + decoded.Reserved5 = new byte[SCSIInquiryResponse.Length - 74]; + Array.Copy(SCSIInquiryResponse, 74, decoded.Reserved5, 0, SCSIInquiryResponse.Length - 74); + } + + if(SCSIInquiryResponse.Length >= 96) + { + decoded.Reserved5 = new byte[22]; + Array.Copy(SCSIInquiryResponse, 74, decoded.Reserved5, 0, 22); + } + + if(SCSIInquiryResponse.Length > 96) + { + decoded.VendorSpecific2 = new byte[SCSIInquiryResponse.Length - 96]; + Array.Copy(SCSIInquiryResponse, 96, decoded.VendorSpecific2, 0, SCSIInquiryResponse.Length - 96); + } + + if(SCSIInquiryResponse.Length >= 144) + { + // Seagate 2 + decoded.Seagate2Present = true; + decoded.Seagate_Copyright = new byte[48]; + Array.Copy(SCSIInquiryResponse, 96, decoded.Seagate_Copyright, 0, 48); + } + + if(SCSIInquiryResponse.Length < 148) + return decoded; + + // Seagate 2 + decoded.Seagate3Present = true; + decoded.Seagate_ServoPROMPartNo = new byte[4]; + Array.Copy(SCSIInquiryResponse, 144, decoded.Seagate_ServoPROMPartNo, 0, 4); + + return decoded; + } + + /// Encodes a SCSI INQUIRY response + /// Decoded SCSI INQUIRY + /// Raw SCSI INQUIRY response + public static byte[] Encode(Inquiry? inq) + { + if(inq is null) + return null; + + Inquiry decoded = inq.Value; + + byte[] buffer = new byte[512]; + byte length = 0; + + buffer[0] = (byte)(decoded.PeripheralQualifier << 5); + buffer[0] += decoded.PeripheralDeviceType; + + if(decoded.RMB) + buffer[1] = 0x80; + + buffer[1] += decoded.DeviceTypeModifier; + + buffer[2] = (byte)(decoded.ISOVersion << 6); + buffer[2] += (byte)(decoded.ECMAVersion << 3); + buffer[2] += decoded.ANSIVersion; + + if(decoded.AERC) + buffer[3] = 0x80; + + if(decoded.TrmTsk) + buffer[3] += 0x40; + + if(decoded.NormACA) + buffer[3] += 0x20; + + if(decoded.HiSup) + buffer[3] += 0x10; + + buffer[3] += decoded.ResponseDataFormat; + + if(decoded.AdditionalLength > 0) + { + length = 5; + buffer[4] = decoded.AdditionalLength; + } + + if(decoded.SCCS || + decoded.ACC || + decoded.TPGS > 0 || + decoded.ThreePC || + decoded.Reserved2 > 0 || + decoded.Protect) + { + length = 6; + + if(decoded.SCCS) + buffer[5] = 0x80; + + if(decoded.ACC) + buffer[5] += 0x40; + + buffer[5] += (byte)(decoded.TPGS << 4); + + if(decoded.ThreePC) + buffer[5] += 0x08; + + buffer[5] += (byte)(decoded.Reserved2 << 1); + + if(decoded.Protect) + buffer[5] += 0x01; + } + + if(decoded.BQue || + decoded.EncServ || + decoded.VS1 || + decoded.MultiP || + decoded.MChngr || + decoded.ACKREQQ || + decoded.Addr32 || + decoded.Addr16) + { + length = 7; + + if(decoded.BQue) + buffer[6] = 0x80; + + if(decoded.EncServ) + buffer[6] += 0x40; + + if(decoded.VS1) + buffer[6] += 0x20; + + if(decoded.MultiP) + buffer[6] += 0x10; + + if(decoded.MChngr) + buffer[6] += 0x08; + + if(decoded.ACKREQQ) + buffer[6] += 0x04; + + if(decoded.Addr32) + buffer[6] += 0x02; + + if(decoded.Addr16) + buffer[6] += 0x01; + } + + if(decoded.RelAddr || + decoded.WBus32 || + decoded.WBus16 || + decoded.Sync || + decoded.Linked || + decoded.TranDis || + decoded.CmdQue || + decoded.SftRe) + + { + length = 8; + + if(decoded.RelAddr) + buffer[7] = 0x80; + + if(decoded.WBus32) + buffer[7] += 0x40; + + if(decoded.WBus16) + buffer[7] += 0x20; + + if(decoded.Sync) + buffer[7] += 0x10; + + if(decoded.Linked) + buffer[7] += 0x08; + + if(decoded.TranDis) + buffer[7] += 0x04; + + if(decoded.CmdQue) + buffer[7] += 0x02; + + if(decoded.SftRe) + buffer[7] += 0x01; + } + + if(decoded.VendorIdentification != null) + { + length = 16; + + Array.Copy(decoded.VendorIdentification, 0, buffer, 8, + decoded.VendorIdentification.Length >= 8 ? 8 : decoded.VendorIdentification.Length); + } + + if(decoded.ProductIdentification != null) + { + length = 32; + + Array.Copy(decoded.ProductIdentification, 0, buffer, 16, + decoded.ProductIdentification.Length >= 16 ? 16 : decoded.ProductIdentification.Length); + } + + if(decoded.ProductRevisionLevel != null) + { + length = 36; + + Array.Copy(decoded.ProductRevisionLevel, 0, buffer, 32, + decoded.ProductRevisionLevel.Length >= 4 ? 4 : decoded.ProductRevisionLevel.Length); + } + + if(decoded.Seagate_DriveSerialNumber != null) + { + length = 44; + Array.Copy(decoded.Seagate_DriveSerialNumber, 0, buffer, 36, 8); + } + + if(decoded.KreonIdentifier != null && + decoded.KreonVersion != null) + { + length = 46; + Array.Copy(decoded.KreonIdentifier, 0, buffer, 36, 5); + buffer[41] = decoded.KreonSpace; + Array.Copy(decoded.KreonVersion, 0, buffer, 42, 5); + } + + if(decoded.HP_WORM || + decoded.HP_WORMVersion > 0 || + decoded.HP_OBDR != null) + { + length = 49; + + if(decoded.HP_WORM) + buffer[40] = 0x01; + + buffer[40] += (byte)(decoded.HP_WORMVersion << 1); + Array.Copy(decoded.HP_OBDR, 0, buffer, 43, 6); + } + + if(decoded.IsHiMD) + { + length = 56; + Array.Copy(HiMDSignatureContents, 0, buffer, 36, 8); + + if(decoded.HiMDSpecific != null) + Array.Copy(decoded.HiMDSpecific, 0, buffer, 44, 12); + } + + if(decoded.VendorSpecific != null && + !decoded.IsHiMD) + { + length = 56; + Array.Copy(decoded.VendorSpecific, 0, buffer, 36, 20); + } + + if(decoded.Reserved3 > 0 || + decoded.Clocking > 0 || + decoded.QAS || + decoded.IUS) + { + length = 57; + buffer[56] = (byte)(decoded.Reserved3 << 4); + buffer[56] += (byte)(decoded.Clocking << 2); + + if(decoded.QAS) + buffer[56] += 0x02; + + if(decoded.IUS) + buffer[56] += 0x01; + } + + if(decoded.Reserved4 != 0) + { + length = 58; + buffer[57] = decoded.Reserved4; + } + + if(decoded.VersionDescriptors != null) + { + length = (byte)(58 + (decoded.VersionDescriptors.Length * 2)); + + for(int i = 0; i < decoded.VersionDescriptors.Length; i++) + Array.Copy(BitConverter.GetBytes(decoded.VersionDescriptors[i]), 0, buffer, 56 + (i * 2), 2); + } + + if(decoded.Reserved5 != null) + { + length = (byte)(74 + decoded.Reserved5.Length); + Array.Copy(decoded.Reserved5, 0, buffer, 74, decoded.Reserved5.Length); + } + + if(decoded.VendorSpecific2 != null) + { + length = (byte)(96 + decoded.VendorSpecific2.Length); + Array.Copy(decoded.VendorSpecific2, 0, buffer, 96, decoded.VendorSpecific2.Length); + } + + if(decoded.Seagate_Copyright != null) + { + length = 144; + Array.Copy(decoded.Seagate_Copyright, 0, buffer, 96, 48); + } + + if(decoded.Seagate_ServoPROMPartNo != null) + { + length = 148; + Array.Copy(decoded.Seagate_ServoPROMPartNo, 0, buffer, 144, 4); + } + + buffer[4] = length; + byte[] dest = new byte[length]; + Array.Copy(buffer, 0, dest, 0, length); + + return dest; + } + #endregion Public methods + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Structs/Devices/SCSI/Modes/2A.cs b/Aaru.CommonTypes/Structs/Devices/SCSI/Modes/2A.cs new file mode 100644 index 000000000..fdbda1ba5 --- /dev/null +++ b/Aaru.CommonTypes/Structs/Devices/SCSI/Modes/2A.cs @@ -0,0 +1,514 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 2A.cs +// Author(s) : Natalia Portillo +// +// Component : Common structures for SCSI devices. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 2Ah: CD-ROM capabilities page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.ComponentModel.DataAnnotations; +using System.Diagnostics.CodeAnalysis; +using Newtonsoft.Json; + +namespace Aaru.CommonTypes.Structs.Devices.SCSI.Modes +{ + #region Mode Page 0x2A: CD-ROM capabilities page + /// + /// CD-ROM capabilities page Page code 0x2A 16 bytes in OB-U0077C 20 bytes in SFF-8020i 22 bytes in MMC-1 26 bytes + /// in MMC-2 Variable bytes in MMC-3 + /// + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public class ModePage_2A + { + /// Write speed performance descriptors + public ModePage_2A_WriteDescriptor[] WriteSpeedPerformanceDescriptors; + /// Parameters can be saved + public bool PS { get; set; } + /// Drive supports multi-session and/or Photo-CD + public bool MultiSession { get; set; } + /// Drive is capable of reading sectors in Mode 2 Form 2 format + public bool Mode2Form2 { get; set; } + /// Drive is capable of reading sectors in Mode 2 Form 1 format + public bool Mode2Form1 { get; set; } + /// Drive is capable of playing audio + public bool AudioPlay { get; set; } + /// Drive can return the ISRC + public bool ISRC { get; set; } + /// Drive can return the media catalogue number + public bool UPC { get; set; } + /// Drive can return C2 pointers + public bool C2Pointer { get; set; } + /// Drive can read, deinterlave and correct R-W subchannels + public bool DeinterlaveSubchannel { get; set; } + /// Drive can read interleaved and uncorrected R-W subchannels + public bool Subchannel { get; set; } + /// Drive can continue from a loss of streaming on audio reading + public bool AccurateCDDA { get; set; } + /// Audio can be read as digital data + public bool CDDACommand { get; set; } + /// Loading Mechanism Type + public byte LoadingMechanism { get; set; } + /// Drive can eject discs + public bool Eject { get; set; } + /// Drive's optional prevent jumper status + public bool PreventJumper { get; set; } + /// Current lock status + public bool LockState { get; set; } + /// Drive can lock media + public bool Lock { get; set; } + /// Each channel can be muted independently + public bool SeparateChannelMute { get; set; } + /// Each channel's volume can be controlled independently + public bool SeparateChannelVolume { get; set; } + /// Maximum drive speed in Kbytes/second + public ushort MaximumSpeed { get; set; } + /// Supported volume levels + public ushort SupportedVolumeLevels { get; set; } + /// Buffer size in Kbytes + public ushort BufferSize { get; set; } + /// Current drive speed in Kbytes/second + public ushort CurrentSpeed { get; set; } + + /// Can read packet media + public bool Method2 { get; set; } + /// Can read CD-RW + public bool ReadCDRW { get; set; } + /// Can read CD-R + public bool ReadCDR { get; set; } + /// Can write CD-RW + public bool WriteCDRW { get; set; } + /// Can write CD-R + public bool WriteCDR { get; set; } + /// Supports IEC-958 digital output on port 2 + public bool DigitalPort2 { get; set; } + /// Supports IEC-958 digital output on port 1 + public bool DigitalPort1 { get; set; } + /// Can deliver a composite audio and video data stream + public bool Composite { get; set; } + /// This bit controls the behavior of the LOAD/UNLOAD command when trying to load a Slot with no Disc present + public bool SSS { get; set; } + /// Contains a changer that can report the exact contents of the slots + public bool SDP { get; set; } + /// Page length + public byte Length { get; set; } + /// Set if LSB comes first + public bool LSBF { get; set; } + /// Set if HIGH on LRCK indicates left channel. Clear if HIGH on LRCK indicates right channel. + public bool RCK { get; set; } + /// + /// Set if data valid on the falling edge of the BCK signal. Clear if data valid on the rising edge of the BCK + /// signal + /// + public bool BCK { get; set; } + + /// Can do a test write + public bool TestWrite { get; set; } + /// Maximum write speed + public ushort MaxWriteSpeed { get; set; } + /// Current write speed + public ushort CurrentWriteSpeed { get; set; } + /// Can read disc's barcode + public bool ReadBarcode { get; set; } + /// Can read DVD-RAM + public bool ReadDVDRAM { get; set; } + /// Can read DVD-R + public bool ReadDVDR { get; set; } + /// Can read DVD-ROM + public bool ReadDVDROM { get; set; } + /// Can write DVD-RAM + public bool WriteDVDRAM { get; set; } + /// Can write DVD-R + public bool WriteDVDR { get; set; } + /// Can read raw R-W subchannel from the Lead-In + public bool LeadInPW { get; set; } + /// Can read both sides of a disc + public bool SCC { get; set; } + /// Support copyright management + public ushort CMRSupported { get; set; } + /// Supports buffer under-run free recording + public bool BUF { get; set; } + /// Selected rotational control + public byte RotationControlSelected { get; set; } + /// Current write speed selected + public ushort CurrentWriteSpeedSelected { get; set; } + + /// Database ID + [JsonIgnore, Key] + public int Id { get; set; } + + /// Decodes the page 2Ah of a MODE SENSE response + /// Raw page 2Ah + /// Decoded page 2Ah + public static ModePage_2A Decode(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x2A) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 16) + return null; + + var decoded = new ModePage_2A(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + + decoded.AudioPlay |= (pageResponse[4] & 0x01) == 0x01; + decoded.Mode2Form1 |= (pageResponse[4] & 0x10) == 0x10; + decoded.Mode2Form2 |= (pageResponse[4] & 0x20) == 0x20; + decoded.MultiSession |= (pageResponse[4] & 0x40) == 0x40; + + decoded.CDDACommand |= (pageResponse[5] & 0x01) == 0x01; + decoded.AccurateCDDA |= (pageResponse[5] & 0x02) == 0x02; + decoded.Subchannel |= (pageResponse[5] & 0x04) == 0x04; + decoded.DeinterlaveSubchannel |= (pageResponse[5] & 0x08) == 0x08; + decoded.C2Pointer |= (pageResponse[5] & 0x10) == 0x10; + decoded.UPC |= (pageResponse[5] & 0x20) == 0x20; + decoded.ISRC |= (pageResponse[5] & 0x40) == 0x40; + + decoded.LoadingMechanism = (byte)((pageResponse[6] & 0xE0) >> 5); + decoded.Lock |= (pageResponse[6] & 0x01) == 0x01; + decoded.LockState |= (pageResponse[6] & 0x02) == 0x02; + decoded.PreventJumper |= (pageResponse[6] & 0x04) == 0x04; + decoded.Eject |= (pageResponse[6] & 0x08) == 0x08; + + decoded.SeparateChannelVolume |= (pageResponse[7] & 0x01) == 0x01; + decoded.SeparateChannelMute |= (pageResponse[7] & 0x02) == 0x02; + + decoded.MaximumSpeed = (ushort)((pageResponse[8] << 8) + pageResponse[9]); + decoded.SupportedVolumeLevels = (ushort)((pageResponse[10] << 8) + pageResponse[11]); + decoded.BufferSize = (ushort)((pageResponse[12] << 8) + pageResponse[13]); + decoded.CurrentSpeed = (ushort)((pageResponse[14] << 8) + pageResponse[15]); + + if(pageResponse.Length < 20) + return decoded; + + decoded.Method2 |= (pageResponse[2] & 0x04) == 0x04; + decoded.ReadCDRW |= (pageResponse[2] & 0x02) == 0x02; + decoded.ReadCDR |= (pageResponse[2] & 0x01) == 0x01; + + decoded.WriteCDRW |= (pageResponse[3] & 0x02) == 0x02; + decoded.WriteCDR |= (pageResponse[3] & 0x01) == 0x01; + + decoded.Composite |= (pageResponse[4] & 0x02) == 0x02; + decoded.DigitalPort1 |= (pageResponse[4] & 0x04) == 0x04; + decoded.DigitalPort2 |= (pageResponse[4] & 0x08) == 0x08; + + decoded.SDP |= (pageResponse[7] & 0x04) == 0x04; + decoded.SSS |= (pageResponse[7] & 0x08) == 0x08; + + decoded.Length = (byte)((pageResponse[17] & 0x30) >> 4); + decoded.LSBF |= (pageResponse[17] & 0x08) == 0x08; + decoded.RCK |= (pageResponse[17] & 0x04) == 0x04; + decoded.BCK |= (pageResponse[17] & 0x02) == 0x02; + + if(pageResponse.Length < 22) + return decoded; + + decoded.TestWrite |= (pageResponse[3] & 0x04) == 0x04; + decoded.MaxWriteSpeed = (ushort)((pageResponse[18] << 8) + pageResponse[19]); + decoded.CurrentWriteSpeed = (ushort)((pageResponse[20] << 8) + pageResponse[21]); + + decoded.ReadBarcode |= (pageResponse[5] & 0x80) == 0x80; + + if(pageResponse.Length < 26) + return decoded; + + decoded.ReadDVDRAM |= (pageResponse[2] & 0x20) == 0x20; + decoded.ReadDVDR |= (pageResponse[2] & 0x10) == 0x10; + decoded.ReadDVDROM |= (pageResponse[2] & 0x08) == 0x08; + + decoded.WriteDVDRAM |= (pageResponse[3] & 0x20) == 0x20; + decoded.WriteDVDR |= (pageResponse[3] & 0x10) == 0x10; + + decoded.LeadInPW |= (pageResponse[3] & 0x20) == 0x20; + decoded.SCC |= (pageResponse[3] & 0x10) == 0x10; + + decoded.CMRSupported = (ushort)((pageResponse[22] << 8) + pageResponse[23]); + + if(pageResponse.Length < 32) + return decoded; + + decoded.BUF |= (pageResponse[4] & 0x80) == 0x80; + decoded.RotationControlSelected = (byte)(pageResponse[27] & 0x03); + decoded.CurrentWriteSpeedSelected = (ushort)((pageResponse[28] << 8) + pageResponse[29]); + + ushort descriptors = (ushort)((pageResponse.Length - 32) / 4); + decoded.WriteSpeedPerformanceDescriptors = new ModePage_2A_WriteDescriptor[descriptors]; + + for(int i = 0; i < descriptors; i++) + decoded.WriteSpeedPerformanceDescriptors[i] = new ModePage_2A_WriteDescriptor + { + RotationControl = (byte)(pageResponse[1 + 32 + (i * 4)] & 0x07), + WriteSpeed = (ushort)((pageResponse[2 + 32 + (i * 4)] << 8) + pageResponse[3 + 32 + (i * 4)]) + }; + + return decoded; + } + + /// Encodes a page 2Ah of a MODE SENSE response + /// Decoded page 2Ah + /// Raw page 2Ah + public static byte[] Encode(ModePage_2A decoded) + { + byte[] pageResponse = new byte[512]; + byte length = 16; + + pageResponse[0] = 0x2A; + + if(decoded.PS) + pageResponse[0] += 0x80; + + if(decoded.AudioPlay) + pageResponse[4] += 0x01; + + if(decoded.Mode2Form1) + pageResponse[4] += 0x10; + + if(decoded.Mode2Form2) + pageResponse[4] += 0x20; + + if(decoded.MultiSession) + pageResponse[4] += 0x40; + + if(decoded.CDDACommand) + pageResponse[5] += 0x01; + + if(decoded.AccurateCDDA) + pageResponse[5] += 0x02; + + if(decoded.Subchannel) + pageResponse[5] += 0x04; + + if(decoded.DeinterlaveSubchannel) + pageResponse[5] += 0x08; + + if(decoded.C2Pointer) + pageResponse[5] += 0x10; + + if(decoded.UPC) + pageResponse[5] += 0x20; + + if(decoded.ISRC) + pageResponse[5] += 0x40; + + decoded.LoadingMechanism = (byte)((pageResponse[6] & 0xE0) >> 5); + + if(decoded.Lock) + pageResponse[6] += 0x01; + + if(decoded.LockState) + pageResponse[6] += 0x02; + + if(decoded.PreventJumper) + pageResponse[6] += 0x04; + + if(decoded.Eject) + pageResponse[6] += 0x08; + + if(decoded.SeparateChannelVolume) + pageResponse[7] += 0x01; + + if(decoded.SeparateChannelMute) + pageResponse[7] += 0x02; + + decoded.MaximumSpeed = (ushort)((pageResponse[8] << 8) + pageResponse[9]); + decoded.SupportedVolumeLevels = (ushort)((pageResponse[10] << 8) + pageResponse[11]); + decoded.BufferSize = (ushort)((pageResponse[12] << 8) + pageResponse[13]); + decoded.CurrentSpeed = (ushort)((pageResponse[14] << 8) + pageResponse[15]); + + if(decoded.Method2 || + decoded.ReadCDRW || + decoded.ReadCDR || + decoded.WriteCDRW || + decoded.WriteCDR || + decoded.Composite || + decoded.DigitalPort1 || + decoded.DigitalPort2 || + decoded.SDP || + decoded.SSS || + decoded.Length > 0 || + decoded.LSBF || + decoded.RCK || + decoded.BCK) + { + length = 20; + + if(decoded.Method2) + pageResponse[2] += 0x04; + + if(decoded.ReadCDRW) + pageResponse[2] += 0x02; + + if(decoded.ReadCDR) + pageResponse[2] += 0x01; + + if(decoded.WriteCDRW) + pageResponse[3] += 0x02; + + if(decoded.WriteCDR) + pageResponse[3] += 0x01; + + if(decoded.Composite) + pageResponse[4] += 0x02; + + if(decoded.DigitalPort1) + pageResponse[4] += 0x04; + + if(decoded.DigitalPort2) + pageResponse[4] += 0x08; + + if(decoded.SDP) + pageResponse[7] += 0x04; + + if(decoded.SSS) + pageResponse[7] += 0x08; + + pageResponse[17] = (byte)(decoded.Length << 4); + + if(decoded.LSBF) + pageResponse[17] += 0x08; + + if(decoded.RCK) + pageResponse[17] += 0x04; + + if(decoded.BCK) + pageResponse[17] += 0x02; + } + + if(decoded.TestWrite || + decoded.MaxWriteSpeed > 0 || + decoded.CurrentWriteSpeed > 0 || + decoded.ReadBarcode) + { + length = 22; + + if(decoded.TestWrite) + pageResponse[3] += 0x04; + + pageResponse[18] = (byte)((decoded.MaxWriteSpeed & 0xFF00) >> 8); + pageResponse[19] = (byte)(decoded.MaxWriteSpeed & 0xFF); + pageResponse[20] = (byte)((decoded.CurrentWriteSpeed & 0xFF00) >> 8); + pageResponse[21] = (byte)(decoded.CurrentWriteSpeed & 0xFF); + + if(decoded.ReadBarcode) + pageResponse[5] += 0x80; + } + + if(decoded.ReadDVDRAM || + decoded.ReadDVDR || + decoded.ReadDVDROM || + decoded.WriteDVDRAM || + decoded.WriteDVDR || + decoded.LeadInPW || + decoded.SCC || + decoded.CMRSupported > 0) + + { + length = 26; + + if(decoded.ReadDVDRAM) + pageResponse[2] += 0x20; + + if(decoded.ReadDVDR) + pageResponse[2] += 0x10; + + if(decoded.ReadDVDROM) + pageResponse[2] += 0x08; + + if(decoded.WriteDVDRAM) + pageResponse[3] += 0x20; + + if(decoded.WriteDVDR) + pageResponse[3] += 0x10; + + if(decoded.LeadInPW) + pageResponse[3] += 0x20; + + if(decoded.SCC) + pageResponse[3] += 0x10; + + pageResponse[22] = (byte)((decoded.CMRSupported & 0xFF00) >> 8); + pageResponse[23] = (byte)(decoded.CMRSupported & 0xFF); + } + + if(decoded.BUF || + decoded.RotationControlSelected > 0 || + decoded.CurrentWriteSpeedSelected > 0) + { + length = 32; + + if(decoded.BUF) + pageResponse[4] += 0x80; + + pageResponse[27] += decoded.RotationControlSelected; + pageResponse[28] = (byte)((decoded.CurrentWriteSpeedSelected & 0xFF00) >> 8); + pageResponse[29] = (byte)(decoded.CurrentWriteSpeedSelected & 0xFF); + } + + if(decoded.WriteSpeedPerformanceDescriptors != null) + { + length = 32; + + for(int i = 0; i < decoded.WriteSpeedPerformanceDescriptors.Length; i++) + { + length += 4; + pageResponse[1 + 32 + (i * 4)] = decoded.WriteSpeedPerformanceDescriptors[i].RotationControl; + + pageResponse[2 + 32 + (i * 4)] = + (byte)((decoded.WriteSpeedPerformanceDescriptors[i].WriteSpeed & 0xFF00) >> 8); + + pageResponse[3 + 32 + (i * 4)] = + (byte)(decoded.WriteSpeedPerformanceDescriptors[i].WriteSpeed & 0xFF); + } + } + + pageResponse[1] = (byte)(length - 2); + byte[] buf = new byte[length]; + Array.Copy(pageResponse, 0, buf, 0, length); + + return buf; + } + } + + /// Page 2Ah write descriptor + [SuppressMessage("ReSharper", "InconsistentNaming")] + public struct ModePage_2A_WriteDescriptor + { + /// Rotational control + public byte RotationControl; + /// Write speed + public ushort WriteSpeed; + } + #endregion Mode Page 0x2A: CD-ROM capabilities page +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Structs/Filesystems.cs b/Aaru.CommonTypes/Structs/Filesystems.cs new file mode 100644 index 000000000..ec188a858 --- /dev/null +++ b/Aaru.CommonTypes/Structs/Filesystems.cs @@ -0,0 +1,350 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Structs.cs +// Author(s) : Natalia Portillo +// +// Component : Common structures. +// +// --[ Description ] ---------------------------------------------------------- +// +// Contains enumerations and structures of common usage by filesystem +// plugins. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using Newtonsoft.Json; + +namespace Aaru.CommonTypes.Structs +{ + /// File attributes. + [Flags] + public enum FileAttributes : ulong + { + /// File has no attributes + None = 0, + /// File is an alias (Mac OS) + Alias = 0x01, + /// Indicates that the file can only be writable appended + AppendOnly = 0x02, + /// File is candidate for archival/backup + Archive = 0x04, + /// File is a block device + BlockDevice = 0x08, + /// File is stored on filesystem block units instead of device sectors + BlockUnits = 0x10, + /// Directory is a bundle or file contains a BNDL resource + Bundle = 0x20, + /// File is a char device + CharDevice = 0x40, + /// File is compressed + Compressed = 0x80, + /// File is compressed and should not be uncompressed on read + CompressedRaw = 0x100, + /// File has compression errors + CompressionError = 0x200, + /// Compressed file is dirty + CompressionDirty = 0x400, + /// File is a device + Device = 0x800, + /// File is a directory + Directory = 0x1000, + /// File is encrypted + Encrypted = 0x2000, + /// File is stored on disk using extents + Extents = 0x4000, + /// File is a FIFO + FIFO = 0x8000, + /// File is a normal file + File = 0x10000, + /// File is a Mac OS file containing desktop databases that has already been added to the desktop database + HasBeenInited = 0x20000, + /// File contains an icon resource / EA + HasCustomIcon = 0x40000, + /// File is a Mac OS extension or control panel lacking INIT resources + HasNoINITs = 0x80000, + /// File is hidden/invisible + Hidden = 0x100000, + /// File cannot be written, deleted, modified or linked to + Immutable = 0x200000, + /// Directory is indexed using hashed trees + IndexedDirectory = 0x400000, + /// File contents are stored alongside its inode (or equivalent) + Inline = 0x800000, + /// File contains integrity checks + IntegrityStream = 0x1000000, + /// File is on desktop + IsOnDesk = 0x2000000, + /// File changes are written to filesystem journal before being written to file itself + Journaled = 0x4000000, + /// Access time will not be modified + NoAccessTime = 0x8000000, + /// File will not be subject to copy-on-write + NoCopyOnWrite = 0x10000000, + /// File will not be backed up + NoDump = 0x20000000, + /// File contents should not be scrubbed + NoScrub = 0x40000000, + /// File contents should not be indexed + NotIndexed = 0x80000000, + /// File is offline + Offline = 0x100000000, + /// File is password protected, but contents are not encrypted on disk + Password = 0x200000000, + /// File is read-only + ReadOnly = 0x400000000, + /// File is a reparse point + ReparsePoint = 0x800000000, + /// When file is removed its content will be overwritten with zeroes + Secured = 0x1000000000, + /// File contents are sparse + Sparse = 0x2000000000, + /// File is a shadow (OS/2) + Shadow = 0x4000000000, + /// File is shared + Shared = 0x8000000000, + /// File is a stationery + Stationery = 0x10000000000, + /// File is a symbolic link + Symlink = 0x20000000000, + /// File writes are synchronously written to disk + Sync = 0x40000000000, + /// File belongs to the operating system + System = 0x80000000000, + /// If file end is a partial block its content will be merged with other files + TailMerged = 0x100000000000, + /// File is temporary + Temporary = 0x200000000000, + /// Subdirectories inside of this directory are not related and should be allocated elsewhere + TopDirectory = 0x400000000000, + /// If file is deleted, contents should be stored, for a possible future undeletion + Undeletable = 0x800000000000, + /// File is a pipe + Pipe = 0x1000000000000, + /// File is a socket + Socket = 0x2000000000000 + } + + /// Information about a file entry + public class FileEntryInfo + { + /// File attributes + public FileAttributes Attributes { get; set; } + /// File length in blocks + public long Blocks { get; set; } + /// File block size in bytes + public long BlockSize { get; set; } + /// If file points to a device, device number. Null if the underlying filesystem does not support them. + public ulong? DeviceNo { get; set; } + /// POSIX group ID. Null if the underlying filesystem does not support them. + public ulong? GID { get; set; } + /// inode number for this file (or other unique identifier for the volume) + public ulong Inode { get; set; } + /// File length in bytes + public long Length { get; set; } + /// Number of hard links pointing to this file (. and .. entries count as hard links) + public ulong Links { get; set; } + /// POSIX permissions/mode for this file. Null if the underlying filesystem does not support them. + public uint? Mode { get; set; } + /// POSIX owner ID. Null if the underlying filesystem does not support them. + public ulong? UID { get; set; } + /// File creation date in UTC. Null if the underlying filesystem does not support them. + public DateTime? CreationTimeUtc { get; set; } + /// File last access date in UTC. Null if the underlying filesystem does not support them. + public DateTime? AccessTimeUtc { get; set; } + /// File attributes change date in UTC. Null if the underlying filesystem does not support them. + public DateTime? StatusChangeTimeUtc { get; set; } + /// File last backup date in UTC. Null if the underlying filesystem does not support them. + public DateTime? BackupTimeUtc { get; set; } + /// File last modification date in UTC. Null if the underlying filesystem does not support them. + public DateTime? LastWriteTimeUtc { get; set; } + + /// File creation date. Null if the underlying filesystem does not support them. + [JsonIgnore] + public DateTime? CreationTime + { + get => CreationTimeUtc?.ToLocalTime(); + set => CreationTimeUtc = value?.ToUniversalTime(); + } + + /// File last access date. Null if the underlying filesystem does not support them. + [JsonIgnore] + public DateTime? AccessTime + { + get => AccessTimeUtc?.ToLocalTime(); + set => AccessTimeUtc = value?.ToUniversalTime(); + } + + /// File attributes change date. Null if the underlying filesystem does not support them. + [JsonIgnore] + public DateTime? StatusChangeTime + { + get => StatusChangeTimeUtc?.ToLocalTime(); + set => StatusChangeTimeUtc = value?.ToUniversalTime(); + } + + /// File last backup date. Null if the underlying filesystem does not support them. + [JsonIgnore] + public DateTime? BackupTime + { + get => BackupTimeUtc?.ToLocalTime(); + set => BackupTimeUtc = value?.ToUniversalTime(); + } + + /// File last modification date. Null if the underlying filesystem does not support them. + [JsonIgnore] + public DateTime? LastWriteTime + { + get => LastWriteTimeUtc?.ToLocalTime(); + set => LastWriteTimeUtc = value?.ToUniversalTime(); + } + } + + /// Information about a volume + public class FileSystemInfo + { + /// Blocks for this filesystem + public ulong Blocks; + /// Maximum length of filenames on this filesystem + public ushort FilenameLength; + /// Files on this filesystem + public ulong Files; + /// Blocks free on this filesystem + public ulong FreeBlocks; + /// Free inodes on this filesystem + public ulong FreeFiles; + /// Filesystem ID + public FileSystemId Id; + /// ID of plugin for this file + public Guid PluginId; + /// Filesystem type + public string Type; + + /// Initializes an empty instance of this structure + public FileSystemInfo() => Id = new FileSystemId(); + + /// Gets a clone of this structure + /// Clone of this structure + public FileSystemInfo ShallowCopy() => (FileSystemInfo)MemberwiseClone(); + } + + /// Stores a filesystem volume unique identifier or serial number + [StructLayout(LayoutKind.Explicit)] + public struct FileSystemId + { + /// Set to true if the identifier is a 32-bit integer + [FieldOffset(0)] + public bool IsInt; + /// Set to true if the identifier is a 64-bit integer + [FieldOffset(1)] + public bool IsLong; + /// Set to true if the identifier is a GUID + [FieldOffset(2)] + public bool IsGuid; + + /// Identifier as a 32-bit integer + [FieldOffset(3)] + public uint Serial32; + /// Identifier as a 64-bit integer + [FieldOffset(3)] + public ulong Serial64; + /// Identifier as a GUID + [FieldOffset(3)] + public Guid uuid; + } + + /// Errors + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum Errno + { + /// No error happened + NoError = 0, + /// Access denied + AccessDenied = -13, + /// Busy, cannot complete + Busy = -16, + /// File is too large + FileTooLarge = -27, + /// Invalid argument + InvalidArgument = -22, + /// I/O error + InOutError = -5, + /// Is a directory (e.g.: trying to Read() a dir) + IsDirectory = -21, + /// Name is too long + NameTooLong = -36, + /// There is no data available + NoData = 61, + /// There is no such attribute + NoSuchExtendedAttribute = NoData, + /// No such device + NoSuchDevice = -19, + /// No such file or directory + NoSuchFile = -2, + /// Is not a directory (e.g.: trying to ReadDir() a file) + NotDirectory = -20, + /// Not implemented + NotImplemented = -38, + /// Not supported + NotSupported = -252, + /// Link is severed + SeveredLink = -67, + /// Access denied + EACCES = AccessDenied, + /// Busy, cannot complete + EBUSY = Busy, + /// File is too large + EFBIG = FileTooLarge, + /// Invalid argument + EINVAL = InvalidArgument, + /// I/O error + EIO = InOutError, + /// Is a directory (e.g.: trying to Read() a dir) + EISDIR = IsDirectory, + /// Name is too long + ENAMETOOLONG = NameTooLong, + /// There is no such attribute + ENOATTR = NoSuchExtendedAttribute, + /// There is no data available + ENODATA = NoData, + /// No such device + ENODEV = NoSuchDevice, + /// No such file or directory + ENOENT = NoSuchFile, + /// Link is severed + ENOLINK = SeveredLink, + /// Not implemented + ENOSYS = NotImplemented, + /// Is not a directory (e.g.: trying to ReadDir() a file) + ENOTDIR = NotDirectory, + /// Not supported + ENOTSUP = NotSupported + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Structs/Images.cs b/Aaru.CommonTypes/Structs/Images.cs new file mode 100644 index 000000000..791a12ce6 --- /dev/null +++ b/Aaru.CommonTypes/Structs/Images.cs @@ -0,0 +1,190 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : IMediaImage.cs +// Author(s) : Natalia Portillo +// +// Component : Common structures. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines structures to be used by media image plugins. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Interfaces; + +namespace Aaru.CommonTypes.Structs +{ + /// Contains information about a dump image and its contents + public struct ImageInfo + { + /// Image contains partitions (or tracks for optical media) + public bool HasPartitions; + /// Image contains sessions (optical media only) + public bool HasSessions; + /// Size of the image without headers + public ulong ImageSize; + /// Sectors contained in the image + public ulong Sectors; + /// Size of sectors contained in the image + public uint SectorSize; + /// Media tags contained by the image + public List ReadableMediaTags; + /// Sector tags contained by the image + public List ReadableSectorTags; + /// Image version + public string Version; + /// Application that created the image + public string Application; + /// Version of the application that created the image + public string ApplicationVersion; + /// Who (person) created the image? + public string Creator; + /// Image creation time + public DateTime CreationTime; + /// Image last modification time + public DateTime LastModificationTime; + /// Title of the media represented by the image + public string MediaTitle; + /// Image comments + public string Comments; + /// Manufacturer of the media represented by the image + public string MediaManufacturer; + /// Model of the media represented by the image + public string MediaModel; + /// Serial number of the media represented by the image + public string MediaSerialNumber; + /// Barcode of the media represented by the image + public string MediaBarcode; + /// Part number of the media represented by the image + public string MediaPartNumber; + /// Media type represented by the image + public MediaType MediaType; + /// Number in sequence for the media represented by the image + public int MediaSequence; + /// Last media of the sequence the media represented by the image corresponds to + public int LastMediaSequence; + /// Manufacturer of the drive used to read the media represented by the image + public string DriveManufacturer; + /// Model of the drive used to read the media represented by the image + public string DriveModel; + /// Serial number of the drive used to read the media represented by the image + public string DriveSerialNumber; + /// Firmware revision of the drive used to read the media represented by the image + public string DriveFirmwareRevision; + /// Type of the media represented by the image to use in XML sidecars + public XmlMediaType XmlMediaType; + + // CHS geometry... + /// Cylinders of the media represented by the image + public uint Cylinders; + /// Heads of the media represented by the image + public uint Heads; + /// Sectors per track of the media represented by the image (for variable image, the smallest) + public uint SectorsPerTrack; + } + + /// Session defining structure. + public struct Session + { + /// Session number, 1-started + public ushort SessionSequence; + /// First track present on this session + public uint StartTrack; + /// Last track present on this session + public uint EndTrack; + /// First sector present on this session + public ulong StartSector; + /// Last sector present on this session + public ulong EndSector; + } + + /// Track defining structure. + public class Track + { + /// Indexes, 00 to 99 and sector offset + public Dictionary Indexes; + /// How many main channel / user data bytes are per sector in this track + public int TrackBytesPerSector; + /// Information that does not find space in this struct + public string TrackDescription; + /// Track ending sector + public ulong TrackEndSector; + /// Which file stores this track + public string TrackFile; + /// Starting at which byte is this track stored + public ulong TrackFileOffset; + /// What kind of file is storing this track + public string TrackFileType; + /// Which filter stores this track + public IFilter TrackFilter; + /// Track pre-gap + public ulong TrackPregap; + /// How many main channel bytes per sector are in the file with this track + public int TrackRawBytesPerSector; + /// Track number, 1-started + public uint TrackSequence; + /// Session this track belongs to + public ushort TrackSession; + /// Track starting sector + public ulong TrackStartSector; + /// Which file stores this track's subchannel + public string TrackSubchannelFile; + /// Which filter stores this track's subchannel + public IFilter TrackSubchannelFilter; + /// Starting at which byte are this track's subchannel stored + public ulong TrackSubchannelOffset; + /// Type of subchannel stored for this track + public TrackSubchannelType TrackSubchannelType; + /// Partition type + public TrackType TrackType; + + /// Initializes an empty instance of this structure + public Track() => Indexes = new Dictionary(); + } + + /// Floppy physical characteristics structure. + public struct FloppyInfo + { + /// Physical floppy type. + public FloppyTypes Type; + /// Bitrate in bits per second used to write the floppy, 0 if unknown or track-variable. + public uint Bitrate; + /// Physical magnetic density (coercivity) of floppy medium. + public FloppyDensities Coercivity; + /// How many physical tracks are actually written in the floppy image. + public ushort Tracks; + /// How many physical heads are actually written in the floppy image. + public byte Heads; + /// How many tracks per inch are actually written in the floppy image. + public ushort TrackDensity; + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Structs/TapeFile.cs b/Aaru.CommonTypes/Structs/TapeFile.cs new file mode 100644 index 000000000..b146e597e --- /dev/null +++ b/Aaru.CommonTypes/Structs/TapeFile.cs @@ -0,0 +1,53 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : TapeFile.cs +// Author(s) : Natalia Portillo +// +// Component : Common structures. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines a structure to hold information about a tape file object. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.CommonTypes.Structs +{ + /// Describes a tape file + public struct TapeFile + { + /// File number + public uint File; + /// Partition number + public byte Partition; + /// First block, inclusive, of the file + public ulong FirstBlock; + /// Last block, inclusive, of the file + public ulong LastBlock; + } +} \ No newline at end of file diff --git a/Aaru.CommonTypes/Structs/TapePartition.cs b/Aaru.CommonTypes/Structs/TapePartition.cs new file mode 100644 index 000000000..35bd3efc7 --- /dev/null +++ b/Aaru.CommonTypes/Structs/TapePartition.cs @@ -0,0 +1,51 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : TapeFile.cs +// Author(s) : Natalia Portillo +// +// Component : Common structures. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines a structure to hold information about a tape partition. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.CommonTypes.Structs +{ + /// Describes a tape partition + public struct TapePartition + { + /// Partition number + public byte Number; + /// First block, inclusive, of the partition + public ulong FirstBlock; + /// Last block, inclusive, of the partition + public ulong LastBlock; + } +} \ No newline at end of file diff --git a/Aaru.Console b/Aaru.Console deleted file mode 160000 index 429f84a69..000000000 --- a/Aaru.Console +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 429f84a69f7e62f684782ca11a6bb27632a6b7ac diff --git a/Aaru.Console/.editorconfig b/Aaru.Console/.editorconfig new file mode 100644 index 000000000..9181fe501 --- /dev/null +++ b/Aaru.Console/.editorconfig @@ -0,0 +1,632 @@ +root = true + +[*] +charset = utf-8 +next_line = crlf +insert_final_newline = false +indent_style = space +indent_size = 4 + +# Generic non-language specific ones for Resharper and friends +brace_style = next_line +int_align = true +keep_existing_arrangement = false +place_simple_blocks_on_single_line = true +place_simple_declaration_blocks_on_single_line = true +place_attribute_on_same_line = false +space_after_unary_operator = false +space_after_comma = true +space_around_ternary_operator = true +space_around_binary_operator = true +space_around_member_access_operator = false +space_before_open_square_brackets = false +space_after_keywords_in_control_flow_statements = true +space_before_comma = false +space_between_method_call_name_and_opening_parenthesis = false +space_between_method_declaration_name_and_open_parenthesis = false +space_between_square_brackets = false +space_between_parentheses_of_control_flow_statements = false +accessor_owner_declaration_braces = next_line +accessor_declaration_braces = next_line +case_block_braces = next_line +initializer_braces = next_line +other_braces = next_line +allow_comment_after_lbrace = false +empty_block_style = together_same_line +braces_for_ifelse = not_required +braces_for_for = not_required +braces_for_foreach = not_required +braces_for_while = not_required +braces_for_dowhile = not_required +braces_for_using = not_required +braces_for_lock = not_required +braces_for_fixed = not_required +method_or_operator_body = expression_body +local_function_body = expression_body +constructor_or_destructor_body = expression_body +accessor_owner_body = expression_body +force_attribute_style = join +function_braces = next_line +force_control_statements_braces = always_remove +space_in_singleline_accessorholder = true +type_declaration_braces = next_line +invocable_declaration_braces = next_line +anonymous_method_declaration_braces = next_line +space_between_accessors_in_singleline_property = true +indent_nested_usings_stmt = true +space_within_empty_braces = false +indent_nested_fixed_stmt = true +indent_nested_lock_stmt = true +indent_nested_for_stmt = true +indent_nested_foreach_stmt = true +indent_nested_while_stmt = true +use_continuous_indent_inside_parens = true +indent_method_decl_pars = inside +indent_invocation_pars = inside +indent_statement_pars = inside +indent_typeparam_angles = inside +indent_typearg_angles = inside +indent_pars = inside +indent_preprocessor_if = outdent +indent_preprocessor_region = usual_indent +indent_preprocessor_other = usual_indent +indent_switch_labels = true +indent_type_constraints = true +stick_comment = false +alignment_tab_fill_style = use_spaces +align_multiline_parameter = true +align_multiline_extends_list = true +align_linq_query = true +align_multiline_binary_expressions_chain = true +outdent_binary_ops = true +align_multiline_calls_chain = true +outdent_dots = true +align_multiline_array_and_object_initializer = false +indent_anonymous_method_block = false +align_first_arg_by_paren = true +align_multiline_argument = true +align_tuple_components = true +align_multiline_expression = true +align_multiline_for_stmt = true +align_multiple_declaration = true +align_multline_type_parameter_list = true +align_multline_type_parameter_constrains = true +int_align_fields = true +int_align_properties = true +int_align_methods = true +int_align_parameters = false +int_align_variables = true +int_align_assignments = true +int_align_nested_ternary = true +int_align_invocations = false +int_align_binary_expressions = true +int_align_comments = true +int_align_switch_sections = true +keep_user_linebreaks = false +keep_existing_arrangement = false +keep_existing_linebreaks = false +max_line_length = 120 +wrap_before_comma = false +special_else_if_treatment = true +place_type_attribute_on_same_line = never +place_method_attribute_on_same_line = never +place_accessorholder_attribute_on_same_line = never +place_attribute_on_same_line = never +place_accessor_attribute_on_same_line = never +place_attribute_on_same_line = never +place_field_attribute_on_same_line = never +place_attribute_on_same_line = never +wrap_parameters_style = wrap_if_long +keep_existing_declaration_parens_arrangement = false +wrap_before_declaration_lpar = false +wrap_after_declaration_lpar = false +wrap_before_declaration_rpar = false +place_constructor_initializer_on_same_line = true +keep_existing_expr_member_arrangement = false +place_expr_method_on_single_line = true +place_expr_property_on_single_line = true +place_expr_accessor_on_single_line = true +wrap_before_arrow_with_expressions = false +place_type_constraints_on_same_line = true +wrap_before_first_type_parameter_constraint = true +wrap_multiple_type_parameter_constraints_style = wrap_if_long +wrap_before_type_parameter_langle = true +wrap_before_extends_colon = false +wrap_extends_list_style = wrap_if_long +keep_existing_declaration_block_arrangement = false +place_abstract_accessorholder_on_single_line = true +place_simple_accessorholder_on_single_line = false +place_accessor_with_attrs_holder_on_single_line = false +place_simple_accessor_on_single_line = true +place_simple_method_on_single_line = false +keep_existing_enum_arrangement = false +place_simple_enum_on_single_line = false +wrap_enum_declaration = wrap_if_long +new_line_before_else = true +new_line_before_while = false +wrap_for_stmt_header_style = wrap_if_long +wrap_multiple_declaration_style = wrap_if_long +keep_existing_embedded_arrangement = false +place_simple_embedded_statement_on_same_line = false +place_simple_case_statement_on_same_line = true +keep_existing_embedded_block_arrangement = false +place_simple_embedded_block_on_same_line = false +place_simple_anonymousmethod_on_single_line = false +keep_existing_initializer_arrangement = false +place_simple_initializer_on_single_line = false +wrap_object_and_collection_initializer_style = chop_always +wrap_array_initializer_style = wrap_if_long +wrap_arguments_style = wrap_if_long +keep_existing_invocation_parens_arrangement = false +wrap_after_invocation_lpar = false +wrap_before_invocation_rpar = false +wrap_after_dot_in_method_calls = true +wrap_chained_method_calls = wrap_if_long +wrap_before_binary_opsign = false +wrap_chained_binary_expressions = wrap_if_long +force_chop_compound_if_expression = true +force_chop_compound_while_expression = true +force_chop_compound_do_expression = true +wrap_before_ternary_opsigns = true +wrap_ternary_expr_style = wrap_if_long +nested_ternary_style = expanded +wrap_linq_expressions = wrap_if_long +wrap_before_linq_expression = false +place_linq_into_on_new_line = false +wrap_verbatim_interpolated_strings = wrap_if_long +extra_spaces = remove_all +space_after_keywords_in_control_flow_statements = false +space_between_method_call_name_and_opening_parenthesis = false +space_between_method_declaration_name_and_open_parenthesis = false +space_before_typeof_parentheses = false +space_before_checked_parentheses = false +space_before_sizeof_parentheses = false +space_before_nameof_parentheses = false +space_between_keyword_and_expression = true +space_between_keyword_and_type = true +space_around_assignment_op = true +space_around_logical_op = true +space_around_binary_operator = true +space_around_equality_op = true +space_around_relational_op = true +space_around_bitwise_op = true +space_around_additive_op = true +space_around_multiplicative_op = true +space_around_shift_op = true +space_around_nullcoalescing_op = true +space_around_arrow_op = false +space_after_logical_not_op = false +space_after_unary_operator = false +space_after_cast = false +space_around_dot = false +space_around_lambda_arrow = true +space_before_pointer_asterik_declaration = false +space_before_nullable_mark = false +blank_lines_around_class_definition = 1 +namespace_indentation = all +space_within_template_argument = false +align_union_type_usage = true +space_in_singleline_method = true +space_in_singleline_anonymous_method = true +space_within_single_line_array_initializer_braces = true +space_around_arrow_op = false + +# These are for markup languages (HTML, XML, etc) +spaces_around_eq_in_pi_attribute = false +space_after_last_pi_attribute = true +pi_attributes_indent = align_by_first_attribute +blank_line_after_pi = true +spaces_around_eq_in_attribute = false +space_after_last_attribute = false +space_before_self_closing = true +attribute_style = on_single_line +attribute_indent = align_by_first_attribute +sort_attributes = true +sort_class_selectors = true +max_blank_lines_between_tags = 0 +linebreak_before_all_elements = true +linebreak_before_multiline_elements = true +quote_style = doublequoted +delete_quotes_from_solid_values = false +normalize_tag_names = true + + +[{.babelrc,.stylelintrc,jest.config,.eslintrc,.prettierrc,*.json,*.jsb3,*.jsb2,*.bowerrc}] +indent_size = 2 + +[*.js.map] +indent_size = 2 + +[*.{css,scss}] +indent_size = 2 +declarations_style = separate_lines_for_nonsingle +media_query_style = separate_lines +selector_style = same_line +properties_style = separate_lines_for_nonsingle +brace_style = next_line + +[{.analysis_options,*.yml,*.yaml}] +indent_size = 2 + +# Xml project files +[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] +indent_size = 2 + +# Xml files +[*.{xml,stylecop,resx,ruleset}] +indent_size = 2 + +# Xml config files +[*.{props,targets,config,nuspec}] +indent_size = 2 + +# .net files +[*.{cs,vb}] +# These set the this. / Me. +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning + +# These make it suggest Int32 instead of int, etc. +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# This controls implicit access modifiers +dotnet_style_require_accessibility_modifiers = never:suggestion + +# Prefer non modified fields to be marked readonly +dotnet_style_readonly_field = true:warning + +# Parenthesis settings +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_operators = always_for_clarity:warning + +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:error +dotnet_style_prefer_inferred_tuple_names = true:warning +dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning +dotnet_style_prefer_conditional_expression_over_return = true:warning +dotnet_style_coalesce_expression = true:warning +dotnet_style_null_propagation = true:error + +dotnet_sort_system_directives_first = true + +# Constants in C style, all-caps +dotnet_naming_rule.constant_fields_caps.symbols = constant_fields +dotnet_naming_rule.constant_fields_caps.severity = warning +dotnet_naming_rule.constant_fields_caps.style = caps_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.required_modifiers = const +dotnet_naming_style.caps_style.capitalization = all_upper + +# interfaces should be prefixed with I +dotnet_naming_rule.pascal_case_for_interface.severity = error +dotnet_naming_rule.pascal_case_for_interface.symbols = interfaces_fields +dotnet_naming_rule.pascal_case_for_interface.style = pascal_case_interface_style +dotnet_naming_symbols.interfaces_fields.applicable_kinds = interface +dotnet_naming_style.pascal_case_interface_style.required_prefix = I +dotnet_naming_style.pascal_case_interface_style.capitalization = pascal_case + +## internal and private fields should be _camelCase +dotnet_naming_rule.camel_case_for_private_internal_fields.severity = warning +dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields +dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style +dotnet_naming_symbols.private_internal_fields.applicable_kinds = field +dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal +dotnet_naming_style.camel_case_underscore_style.required_prefix = _ +dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case + +# 2018-12-07 NP: This is not yet working in VS2017 +# local variables should be camelCase +#dotnet_naming_rule.camel_case_for_locals.severity = suggestion +#dotnet_naming_rule.camel_case_for_locals.symbols = local_fields +#dotnet_naming_rule.camel_case_for_locals.style = camel_case_style +#dotnet_naming_symbols.local_fields.applicable_kinds = local +#dotnet_naming_style.camel_case_style.capitalization = camel_case + +[*.cs] +# var var var +csharp_style_var_for_built_in_types = false:warning +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = false:warning + +csharp_style_expression_bodied_methods = when_on_single_line:suggestion +csharp_style_expression_bodied_constructors = when_on_single_line:suggestion +csharp_style_expression_bodied_operators = when_on_single_line:suggestion +csharp_style_expression_bodied_properties = when_on_single_line:suggestion +csharp_style_expression_bodied_indexers = when_on_single_line:suggestion +csharp_style_expression_bodied_accessors = when_on_single_line:suggestion + +csharp_style_pattern_matching_over_is_with_cast_check = true:warning +csharp_style_pattern_matching_over_as_with_null_check = when_on_single_line:warning + +csharp_style_inlined_variable_declaration = true:warning + +csharp_prefer_simple_default_expression = true:warning +csharp_style_deconstructed_variable_declaration = false:warning + +csharp_style_throw_expression = true:warning +csharp_style_conditional_delegate_call = true:warning + +csharp_prefer_braces = false + +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true + +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = flush_left + +csharp_space_after_cast = false +csharp_space_after_keywords_in_control_flow_statements = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = none +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false + +csharp_preserve_single_line_statements = false +csharp_preserve_single_line_blocks = true + +csharp_blank_lines_around_region = 0 +csharp_blank_lines_inside_region = 0 +csharp_blank_lines_before_single_line_comment = 1 +csharp_keep_blank_lines_in_declarations = 1 +csharp_remove_blank_lines_near_braces_in_declarations = true +csharp_blank_lines_after_start_comment = false +csharp_blank_lines_between_using_groups = 0 +csharp_blank_lines_after_using_list = 1 +csharp_blank_lines_around_namespace = 1 +csharp_blank_lines_inside_namespace = 0 +csharp_blank_lines_around_type = 1 +csharp_blank_lines_inside_type = 0 +csharp_blank_lines_around_field = 0 +csharp_blank_lines_around_single_line_field = 0 +csharp_blank_lines_around_property = 1 +csharp_blank_lines_around_single_line_property = 0 +csharp_blank_lines_around_auto_property = 0 +csharp_blank_lines_around_single_line_auto_property = 0 +csharp_blank_lines_around_invocable = 1 +csharp_blank_lines_around_single_line_invocable = 1 +csharp_keep_blank_lines_in_code = 1 +csharp_remove_blank_lines_near_braces_in_code = true +csharp_blank_lines_around_local_method = 1 +csharp_blank_lines_around_single_line_local_method = 1 +csharp_blank_lines_before_control_transfer_statements = 1 +csharp_blank_lines_after_control_transfer_statements = 1 +csharp_blank_lines_before_block_statements = 1 +csharp_blank_lines_after_block_statements = 1 +csharp_blank_lines_before_multiline_statements = 1 +csharp_blank_lines_after_multiline_statements = 1 + +csharp_type_declaration_braces = next_line +csharp_brace_style = next_line +csharp_indent_inside_namespace = true +csharp_invocable_declaration_braces = next_line +csharp_anonymous_method_declaration_braces = next_line +csharp_accessor_owner_declaration_braces = next_line +csharp_accessor_declaration_braces = next_line +csharp_case_block_braces = next_line +csharp_initializer_braces = next_line +csharp_other_braces = next_line +csharp_allow_comment_after_lbrace = false +csharp_empty_block_style = together_same_line + +csharp_for_built_in_types = use_explicit_type +csharp_for_simple_types = use_var_when_evident +csharp_for_other_types = use_explicit_type +csharp_prefer_separate_deconstructed_variables_declaration = true +csharp_prefer_explicit_discard_declaration = false + +csharp_instance_members_qualify_members = none +csharp_builtin_type_reference_style = use_keyword +csharp_prefer_qualified_reference = false +csharp_add_imports_to_deepest_scope = false +csharp_allow_alias = true +csharp_default_private_modifier = implicit +csharp_default_internal_modifier = explicit +csharp_arguments_literal = positional +csharp_arguments_string_literal = positional +csharp_arguments_named = positional +csharp_arguments_anonymous_function = positional +csharp_arguments_other = positional +csharp_braces_for_ifelse = not_required +csharp_braces_for_for = not_required +csharp_braces_for_foreach = not_required +csharp_braces_for_while = not_required +csharp_braces_for_dowhile = not_required +csharp_braces_for_using = not_required +csharp_braces_for_lock = not_required +csharp_braces_for_fixed = not_required +csharp_method_or_operator_body = expression_body +csharp_local_function_body = expression_body +csharp_constructor_or_destructor_body = expression_body +csharp_accessor_owner_body = expression_body +csharp_force_attribute_style = join +csharp_indent_nested_usings_stmt = true + +csharp_builtin_type_reference_for_member_access_style = use_keyword +csharp_indent_nested_fixed_stmt = true +csharp_indent_nested_lock_stmt = true +csharp_indent_nested_for_stmt = true +csharp_indent_nested_foreach_stmt = true +csharp_indent_nested_while_stmt = true +csharp_use_continuous_indent_inside_parens = true +csharp_indent_method_decl_pars = inside +csharp_indent_invocation_pars = inside +csharp_indent_statement_pars = inside +csharp_indent_typeparam_angles = inside +csharp_indent_typearg_angles = inside +csharp_indent_pars = inside +csharp_indent_preprocessor_if = outdent +csharp_indent_preprocessor_region = usual_indent +csharp_indent_preprocessor_other = usual_indent +csharp_indent_switch_labels = true +csharp_indent_type_constraints = true +csharp_stick_comment = false +csharp_alignment_tab_fill_style = use_spaces +csharp_align_multiline_parameter = true +csharp_align_multiline_extends_list = true +csharp_align_linq_query = true +csharp_align_multiline_binary_expressions_chain = true +csharp_outdent_binary_ops = true +csharp_align_multiline_calls_chain = true +csharp_outdent_dots = true +csharp_align_multiline_array_and_object_initializer = false +csharp_indent_anonymous_method_block = false +csharp_align_first_arg_by_paren = true +csharp_align_multiline_argument = true +csharp_align_tuple_components = true +csharp_align_multiline_expression = true +csharp_align_multiline_for_stmt = true +csharp_align_multiple_declaration = true +csharp_align_multline_type_parameter_list = true +csharp_align_multline_type_parameter_constrains = true +csharp_int_align_fields = true +csharp_int_align_properties = true +csharp_int_align_methods = true +csharp_int_align_parameters = false +csharp_int_align_variables = true +csharp_int_align_assignments = true +csharp_int_align_nested_ternary = true +csharp_int_align_invocations = false +csharp_int_align_binary_expressions = true +csharp_int_align_comments = true +csharp_int_align_switch_sections = true +csharp_int_align = true +csharp_keep_user_linebreaks = false +csharp_keep_existing_arrangement = false +csharp_keep_existing_linebreaks = false +csharp_max_line_length = 120 +csharp_wrap_before_comma = false +csharp_special_else_if_treatment = true +csharp_insert_final_newline = false +csharp_place_type_attribute_on_same_line = never +csharp_place_method_attribute_on_same_line = never +csharp_place_accessorholder_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_place_accessor_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_place_field_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_wrap_parameters_style = wrap_if_long +csharp_keep_existing_declaration_parens_arrangement = false +csharp_wrap_before_declaration_lpar = false +csharp_wrap_after_declaration_lpar = false +csharp_wrap_before_declaration_rpar = false +csharp_place_constructor_initializer_on_same_line = true +csharp_keep_existing_expr_member_arrangement = false +csharp_place_expr_method_on_single_line = true +csharp_place_expr_property_on_single_line = true +csharp_place_expr_accessor_on_single_line = true +csharp_wrap_before_arrow_with_expressions = false +csharp_place_type_constraints_on_same_line = true +csharp_wrap_before_first_type_parameter_constraint = true +csharp_wrap_multiple_type_parameter_constraints_style = wrap_if_long +csharp_wrap_before_type_parameter_langle = true +csharp_wrap_before_extends_colon = false +csharp_wrap_extends_list_style = wrap_if_long +csharp_keep_existing_declaration_block_arrangement = false +csharp_place_abstract_accessorholder_on_single_line = true +csharp_place_simple_accessorholder_on_single_line = false +csharp_place_accessor_with_attrs_holder_on_single_line = false +csharp_place_simple_accessor_on_single_line = true +csharp_place_simple_method_on_single_line = false +csharp_keep_existing_enum_arrangement = false +csharp_place_simple_enum_on_single_line = false +csharp_wrap_enum_declaration = wrap_if_long +csharp_new_line_before_else = true +csharp_new_line_before_while = false +csharp_wrap_for_stmt_header_style = wrap_if_long +csharp_wrap_multiple_declaration_style = wrap_if_long +csharp_keep_existing_embedded_arrangement = false +csharp_place_simple_embedded_statement_on_same_line = false +csharp_place_simple_case_statement_on_same_line = true +csharp_keep_existing_embedded_block_arrangement = false +csharp_place_simple_embedded_block_on_same_line = false +csharp_place_simple_anonymousmethod_on_single_line = false +csharp_keep_existing_initializer_arrangement = false +csharp_place_simple_initializer_on_single_line = false +csharp_wrap_object_and_collection_initializer_style = chop_always +csharp_wrap_array_initializer_style = wrap_if_long +csharp_wrap_arguments_style = wrap_if_long +csharp_keep_existing_invocation_parens_arrangement = false +csharp_wrap_after_invocation_lpar = false +csharp_wrap_before_invocation_rpar = false +csharp_wrap_after_dot_in_method_calls = true +csharp_wrap_chained_method_calls = wrap_if_long +csharp_wrap_before_binary_opsign = false +csharp_wrap_chained_binary_expressions = wrap_if_long +csharp_force_chop_compound_if_expression = true +csharp_force_chop_compound_while_expression = true +csharp_force_chop_compound_do_expression = true +csharp_wrap_before_ternary_opsigns = true +csharp_wrap_ternary_expr_style = wrap_if_long +csharp_nested_ternary_style = expanded +csharp_wrap_linq_expressions = wrap_if_long +csharp_wrap_before_linq_expression = false +csharp_place_linq_into_on_new_line = false +csharp_wrap_verbatim_interpolated_strings = wrap_if_long +csharp_extra_spaces = remove_all +csharp_space_after_keywords_in_control_flow_statements = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_before_typeof_parentheses = false +csharp_space_before_checked_parentheses = false +csharp_space_before_sizeof_parentheses = false +csharp_space_before_nameof_parentheses = false +csharp_space_between_keyword_and_expression = true +csharp_space_between_keyword_and_type = true +csharp_space_around_assignment_op = true +csharp_space_around_logical_op = true +csharp_space_around_binary_operator = true +csharp_space_around_equality_op = true +csharp_space_around_relational_op = true +csharp_space_around_bitwise_op = true +csharp_space_around_additive_op = true +csharp_space_around_multiplicative_op = true +csharp_space_around_shift_op = true +csharp_space_around_nullcoalescing_op = true +csharp_space_around_arrow_op = false +csharp_space_after_logical_not_op = false +csharp_space_after_unary_operator = false +csharp_space_after_cast = false +csharp_space_around_dot = false +csharp_space_around_lambda_arrow = true +csharp_space_before_pointer_asterik_declaration = false +csharp_space_before_nullable_mark = false + +[*.cshtml] +linebreaks_around_razor_statements = true +blank_lines_around_razor_functions = true +blank_lines_around_razor_helpers = true +blank_lines_around_razor_sections = true + +# C++ +[*.{cc,cpp,cxx,h,hpp,hxx}] +cpp_indent_access_specifiers_from_class = true +cpp_indent_wrapped_function_names = false +cpp_align_multiline_type_argument = true + +# C, C++ and ObjectiveC +[*.{c,h,cc,cpp,cxx,m,hpp,hxx}] +indent_preprocessor_directives = normal +indent_type_constraints = true + +# Javascript and Typescript +[*.{js,js.map,ts}] +quote_style = doublequoted +termination_style = ensure_semicolon \ No newline at end of file diff --git a/Aaru.Console/.gitignore b/Aaru.Console/.gitignore new file mode 100644 index 000000000..05c540d38 --- /dev/null +++ b/Aaru.Console/.gitignore @@ -0,0 +1,595 @@ +### VisualStudio template +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ +### Linux template + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* +### Xcode template +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +### VisualStudioCode template +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +### C++ template +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o + +# Precompiled Headers +*.gch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +### MonoDevelop template +#User Specific +*.usertasks + +#Mono Project Files +*.resources +test-results/ +### GPG template +secring.* + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests +### CMake template +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +### C template +# Object files +*.ko +*.elf + +# Linker output +*.map +*.exp + +*.so.* + +# Executables +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf +### Windows template +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# NuGet Packages Directory +packages/ +## TODO: If the tool you use requires repositories.config uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +# This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented) +!packages/build/ + + +# Others +sql/ +*.Cache + +# Visual Studio 2017 +.vs + +workspace.xml +cmake-build-debug +### macOS template +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +pkg/**/pkg +pkg/**/src +pkg/**/*.asc +pkg/**/*.sig +pkg/**/*.tar.xz +pkg/**/*.zip +pkg/**/aaru + +.sonarqube \ No newline at end of file diff --git a/Aaru.Console/Aaru.Console.csproj b/Aaru.Console/Aaru.Console.csproj new file mode 100644 index 000000000..f2f4a6069 --- /dev/null +++ b/Aaru.Console/Aaru.Console.csproj @@ -0,0 +1,50 @@ + + + + 2.0 + {CCAA7AFE-C094-4D82-A66D-630DE8A3F545} + Library + Aaru.Console + Aaru.Console + $(Version) + false + true + 5.3.2 + Claunia.com + Copyright © 2011-2023 Natalia Portillo + Aaru Data Preservation Suite + Aaru.Console + $(Version) + netcoreapp3.1 + 8 + Contains console implementation used by the Aaru Data Preservation Suite. + https://github.com/aaru-dps/ + LGPL-2.1-only + https://github.com/aaru-dps/Aaru.Console + true + en-US + true + true + snupkg + Natalia Portillo <claunia@claunia.com> + + + $(Version)+{chash:8} + true + true + + + + + + + + + + LICENSE.LGPL + + + + + + \ No newline at end of file diff --git a/Aaru.Console/AaruConsole.cs b/Aaru.Console/AaruConsole.cs new file mode 100644 index 000000000..7da07835a --- /dev/null +++ b/Aaru.Console/AaruConsole.cs @@ -0,0 +1,236 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : AaruConsole.cs +// Author(s) : Natalia Portillo +// +// Component : Console. +// +// --[ Description ] ---------------------------------------------------------- +// +// Handlers for normal, verbose and debug consoles. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.Console +{ + /// + /// Writes the text representation of the specified array of objects, followed by the current line terminator, to + /// the standard output console using the specified format information. + /// + /// A composite format string. + /// An array of objects to write using . + public delegate void WriteLineHandler(string format, params object[] arg); + + /// + /// Writes the text representation of the specified array of objects, followed by the current line terminator, to + /// the error output console using the specified format information. + /// + /// A composite format string. + /// An array of objects to write using . + public delegate void ErrorWriteLineHandler(string format, params object[] arg); + + /// + /// Writes the text representation of the specified array of objects, followed by the current line terminator, to + /// the verbose output console using the specified format information. + /// + /// A composite format string. + /// An array of objects to write using . + public delegate void VerboseWriteLineHandler(string format, params object[] arg); + + /// + /// Writes the text representation of the specified array of objects, followed by the current line terminator, to + /// the debug output console using the specified format information. + /// + /// A composite format string. + /// An array of objects to write using . + public delegate void DebugWriteLineHandler(string format, params object[] arg); + + /// + /// Writes the text representation of the specified array of objects, to the standard output console using the + /// specified format information. + /// + /// A composite format string. + /// An array of objects to write using . + public delegate void WriteHandler(string format, params object[] arg); + + /// + /// Writes the text representation of the specified array of objects, to the error output console using the + /// specified format information. + /// + /// A composite format string. + /// An array of objects to write using . + public delegate void ErrorWriteHandler(string format, params object[] arg); + + /// + /// Writes the text representation of the specified array of objects, to the verbose output console using the + /// specified format information. + /// + /// A composite format string. + /// An array of objects to write using . + public delegate void VerboseWriteHandler(string format, params object[] arg); + + /// + /// Writes the text representation of the specified array of objects, to the debug output console using the + /// specified format information. + /// + /// A composite format string. + /// An array of objects to write using . + public delegate void DebugWriteHandler(string format, params object[] arg); + + /// + /// Writes the text representation of the specified array of objects, followed by the current line terminator, to + /// the debug output console using the specified format information. + /// + /// Description of the module writing to the debug console + /// A composite format string. + /// An array of objects to write using . + public delegate void DebugWithModuleWriteLineHandler(string module, string format, params object[] arg); + + /// + /// Implements a console abstraction that defines four level of messages that can be routed to different consoles: + /// standard, error, verbose and debug. + /// + public static class AaruConsole + { + /// Event to receive writings to the standard output console that should be followed by a line termination. + public static event WriteLineHandler WriteLineEvent; + /// Event to receive writings to the error output console that should be followed by a line termination. + public static event ErrorWriteLineHandler ErrorWriteLineEvent; + /// Event to receive writings to the verbose output console that should be followed by a line termination. + public static event VerboseWriteLineHandler VerboseWriteLineEvent; + /// Event to receive line terminations to the debug output console. + public static event DebugWriteLineHandler DebugWriteLineEvent; + /// Event to receive writings to the debug output console that should be followed by a line termination. + public static event DebugWithModuleWriteLineHandler DebugWithModuleWriteLineEvent; + /// Event to receive writings to the standard output console. + public static event WriteHandler WriteEvent; + /// Event to receive writings to the error output console. + public static event ErrorWriteHandler ErrorWriteEvent; + /// Event to receive writings to the verbose output console. + public static event VerboseWriteHandler VerboseWriteEvent; + /// Event to receive writings to the debug output console. + public static event DebugWriteHandler DebugWriteEvent; + + /// + /// Writes the text representation of the specified array of objects, followed by the current line terminator, to + /// the standard output console using the specified format information. + /// + /// A composite format string. + /// An array of objects to write using . + public static void WriteLine(string format, params object[] arg) => WriteLineEvent?.Invoke(format, arg); + + /// + /// Writes the text representation of the specified array of objects, followed by the current line terminator, to + /// the error output console using the specified format information. + /// + /// A composite format string. + /// An array of objects to write using . + public static void ErrorWriteLine(string format, params object[] arg) => + ErrorWriteLineEvent?.Invoke(format, arg); + + /// + /// Writes the text representation of the specified array of objects, followed by the current line terminator, to + /// the verbose output console using the specified format information. + /// + /// A composite format string. + /// An array of objects to write using . + public static void VerboseWriteLine(string format, params object[] arg) => + VerboseWriteLineEvent?.Invoke(format, arg); + + /// + /// Writes the text representation of the specified array of objects, followed by the current line terminator, to + /// the debug output console using the specified format information. + /// + /// Description of the module writing to the debug console + /// A composite format string. + /// An array of objects to write using . + public static void DebugWriteLine(string module, string format, params object[] arg) + { + DebugWriteLineEvent?.Invoke("DEBUG (" + module + "): " + format, arg); + DebugWithModuleWriteLineEvent?.Invoke(module, format, arg); + } + + /// Writes the current line terminator to the standard output console. + public static void WriteLine() => WriteLineEvent?.Invoke("", null); + + /// Writes the current line terminator to the error output console. + public static void ErrorWriteLine() => ErrorWriteLineEvent?.Invoke("", null); + + /// Writes the current line terminator to the verbose output console. + public static void VerboseWriteLine() => VerboseWriteLineEvent?.Invoke("", null); + + /// Writes the current line terminator to the debug output console. + public static void DebugWriteLine() => DebugWriteLineEvent?.Invoke("", null); + + /// + /// Writes the text representation of the specified array of objects to the standard output console using the + /// specified format information. + /// + /// A composite format string. + /// An array of objects to write using . + public static void Write(string format, params object[] arg) => WriteEvent?.Invoke(format, arg); + + /// + /// Writes the text representation of the specified array of objects to the error output console using the + /// specified format information. + /// + /// A composite format string. + /// An array of objects to write using . + public static void ErrorWrite(string format, params object[] arg) => ErrorWriteEvent?.Invoke(format, arg); + + /// + /// Writes the text representation of the specified array of objects to the verbose output console using the + /// specified format information. + /// + /// A composite format string. + /// An array of objects to write using . + public static void VerboseWrite(string format, params object[] arg) => VerboseWriteEvent?.Invoke(format, arg); + + /// + /// Writes the text representation of the specified array of objects to the debug output console using the + /// specified format information. + /// + /// Description of the module writing to the debug console + /// A composite format string. + /// An array of objects to write using . + public static void DebugWrite(string module, string format, params object[] arg) => + DebugWriteEvent?.Invoke("DEBUG (" + module + "): " + format, arg); + + /// Writes the specified string value, followed by the current line terminator, to the standard output console. + /// The value to write. + public static void WriteLine(string value) => WriteLineEvent?.Invoke("{0}", value); + + /// Writes the specified string value, followed by the current line terminator, to the error output console. + /// The value to write. + public static void ErrorWriteLine(string value) => ErrorWriteLineEvent?.Invoke("{0}", value); + + /// Writes the specified string value, followed by the current line terminator, to the verbose output console. + /// The value to write. + public static void VerboseWriteLine(string value) => VerboseWriteLineEvent?.Invoke("{0}", value); + + /// Writes the specified string value, followed by the current line terminator, to the debug output console. + /// Description of the module writing to the debug console + /// The value to write. + public static void DebugWriteLine(string module, string value) => + DebugWriteLineEvent?.Invoke("{0}", "DEBUG (" + module + "): " + value); + } +} \ No newline at end of file diff --git a/Aaru.Decoders b/Aaru.Decoders deleted file mode 160000 index b3531e3e0..000000000 --- a/Aaru.Decoders +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b3531e3e05e7e4ae8fec65f19a30e335842279c5 diff --git a/Aaru.Decoders/.editorconfig b/Aaru.Decoders/.editorconfig new file mode 100644 index 000000000..9181fe501 --- /dev/null +++ b/Aaru.Decoders/.editorconfig @@ -0,0 +1,632 @@ +root = true + +[*] +charset = utf-8 +next_line = crlf +insert_final_newline = false +indent_style = space +indent_size = 4 + +# Generic non-language specific ones for Resharper and friends +brace_style = next_line +int_align = true +keep_existing_arrangement = false +place_simple_blocks_on_single_line = true +place_simple_declaration_blocks_on_single_line = true +place_attribute_on_same_line = false +space_after_unary_operator = false +space_after_comma = true +space_around_ternary_operator = true +space_around_binary_operator = true +space_around_member_access_operator = false +space_before_open_square_brackets = false +space_after_keywords_in_control_flow_statements = true +space_before_comma = false +space_between_method_call_name_and_opening_parenthesis = false +space_between_method_declaration_name_and_open_parenthesis = false +space_between_square_brackets = false +space_between_parentheses_of_control_flow_statements = false +accessor_owner_declaration_braces = next_line +accessor_declaration_braces = next_line +case_block_braces = next_line +initializer_braces = next_line +other_braces = next_line +allow_comment_after_lbrace = false +empty_block_style = together_same_line +braces_for_ifelse = not_required +braces_for_for = not_required +braces_for_foreach = not_required +braces_for_while = not_required +braces_for_dowhile = not_required +braces_for_using = not_required +braces_for_lock = not_required +braces_for_fixed = not_required +method_or_operator_body = expression_body +local_function_body = expression_body +constructor_or_destructor_body = expression_body +accessor_owner_body = expression_body +force_attribute_style = join +function_braces = next_line +force_control_statements_braces = always_remove +space_in_singleline_accessorholder = true +type_declaration_braces = next_line +invocable_declaration_braces = next_line +anonymous_method_declaration_braces = next_line +space_between_accessors_in_singleline_property = true +indent_nested_usings_stmt = true +space_within_empty_braces = false +indent_nested_fixed_stmt = true +indent_nested_lock_stmt = true +indent_nested_for_stmt = true +indent_nested_foreach_stmt = true +indent_nested_while_stmt = true +use_continuous_indent_inside_parens = true +indent_method_decl_pars = inside +indent_invocation_pars = inside +indent_statement_pars = inside +indent_typeparam_angles = inside +indent_typearg_angles = inside +indent_pars = inside +indent_preprocessor_if = outdent +indent_preprocessor_region = usual_indent +indent_preprocessor_other = usual_indent +indent_switch_labels = true +indent_type_constraints = true +stick_comment = false +alignment_tab_fill_style = use_spaces +align_multiline_parameter = true +align_multiline_extends_list = true +align_linq_query = true +align_multiline_binary_expressions_chain = true +outdent_binary_ops = true +align_multiline_calls_chain = true +outdent_dots = true +align_multiline_array_and_object_initializer = false +indent_anonymous_method_block = false +align_first_arg_by_paren = true +align_multiline_argument = true +align_tuple_components = true +align_multiline_expression = true +align_multiline_for_stmt = true +align_multiple_declaration = true +align_multline_type_parameter_list = true +align_multline_type_parameter_constrains = true +int_align_fields = true +int_align_properties = true +int_align_methods = true +int_align_parameters = false +int_align_variables = true +int_align_assignments = true +int_align_nested_ternary = true +int_align_invocations = false +int_align_binary_expressions = true +int_align_comments = true +int_align_switch_sections = true +keep_user_linebreaks = false +keep_existing_arrangement = false +keep_existing_linebreaks = false +max_line_length = 120 +wrap_before_comma = false +special_else_if_treatment = true +place_type_attribute_on_same_line = never +place_method_attribute_on_same_line = never +place_accessorholder_attribute_on_same_line = never +place_attribute_on_same_line = never +place_accessor_attribute_on_same_line = never +place_attribute_on_same_line = never +place_field_attribute_on_same_line = never +place_attribute_on_same_line = never +wrap_parameters_style = wrap_if_long +keep_existing_declaration_parens_arrangement = false +wrap_before_declaration_lpar = false +wrap_after_declaration_lpar = false +wrap_before_declaration_rpar = false +place_constructor_initializer_on_same_line = true +keep_existing_expr_member_arrangement = false +place_expr_method_on_single_line = true +place_expr_property_on_single_line = true +place_expr_accessor_on_single_line = true +wrap_before_arrow_with_expressions = false +place_type_constraints_on_same_line = true +wrap_before_first_type_parameter_constraint = true +wrap_multiple_type_parameter_constraints_style = wrap_if_long +wrap_before_type_parameter_langle = true +wrap_before_extends_colon = false +wrap_extends_list_style = wrap_if_long +keep_existing_declaration_block_arrangement = false +place_abstract_accessorholder_on_single_line = true +place_simple_accessorholder_on_single_line = false +place_accessor_with_attrs_holder_on_single_line = false +place_simple_accessor_on_single_line = true +place_simple_method_on_single_line = false +keep_existing_enum_arrangement = false +place_simple_enum_on_single_line = false +wrap_enum_declaration = wrap_if_long +new_line_before_else = true +new_line_before_while = false +wrap_for_stmt_header_style = wrap_if_long +wrap_multiple_declaration_style = wrap_if_long +keep_existing_embedded_arrangement = false +place_simple_embedded_statement_on_same_line = false +place_simple_case_statement_on_same_line = true +keep_existing_embedded_block_arrangement = false +place_simple_embedded_block_on_same_line = false +place_simple_anonymousmethod_on_single_line = false +keep_existing_initializer_arrangement = false +place_simple_initializer_on_single_line = false +wrap_object_and_collection_initializer_style = chop_always +wrap_array_initializer_style = wrap_if_long +wrap_arguments_style = wrap_if_long +keep_existing_invocation_parens_arrangement = false +wrap_after_invocation_lpar = false +wrap_before_invocation_rpar = false +wrap_after_dot_in_method_calls = true +wrap_chained_method_calls = wrap_if_long +wrap_before_binary_opsign = false +wrap_chained_binary_expressions = wrap_if_long +force_chop_compound_if_expression = true +force_chop_compound_while_expression = true +force_chop_compound_do_expression = true +wrap_before_ternary_opsigns = true +wrap_ternary_expr_style = wrap_if_long +nested_ternary_style = expanded +wrap_linq_expressions = wrap_if_long +wrap_before_linq_expression = false +place_linq_into_on_new_line = false +wrap_verbatim_interpolated_strings = wrap_if_long +extra_spaces = remove_all +space_after_keywords_in_control_flow_statements = false +space_between_method_call_name_and_opening_parenthesis = false +space_between_method_declaration_name_and_open_parenthesis = false +space_before_typeof_parentheses = false +space_before_checked_parentheses = false +space_before_sizeof_parentheses = false +space_before_nameof_parentheses = false +space_between_keyword_and_expression = true +space_between_keyword_and_type = true +space_around_assignment_op = true +space_around_logical_op = true +space_around_binary_operator = true +space_around_equality_op = true +space_around_relational_op = true +space_around_bitwise_op = true +space_around_additive_op = true +space_around_multiplicative_op = true +space_around_shift_op = true +space_around_nullcoalescing_op = true +space_around_arrow_op = false +space_after_logical_not_op = false +space_after_unary_operator = false +space_after_cast = false +space_around_dot = false +space_around_lambda_arrow = true +space_before_pointer_asterik_declaration = false +space_before_nullable_mark = false +blank_lines_around_class_definition = 1 +namespace_indentation = all +space_within_template_argument = false +align_union_type_usage = true +space_in_singleline_method = true +space_in_singleline_anonymous_method = true +space_within_single_line_array_initializer_braces = true +space_around_arrow_op = false + +# These are for markup languages (HTML, XML, etc) +spaces_around_eq_in_pi_attribute = false +space_after_last_pi_attribute = true +pi_attributes_indent = align_by_first_attribute +blank_line_after_pi = true +spaces_around_eq_in_attribute = false +space_after_last_attribute = false +space_before_self_closing = true +attribute_style = on_single_line +attribute_indent = align_by_first_attribute +sort_attributes = true +sort_class_selectors = true +max_blank_lines_between_tags = 0 +linebreak_before_all_elements = true +linebreak_before_multiline_elements = true +quote_style = doublequoted +delete_quotes_from_solid_values = false +normalize_tag_names = true + + +[{.babelrc,.stylelintrc,jest.config,.eslintrc,.prettierrc,*.json,*.jsb3,*.jsb2,*.bowerrc}] +indent_size = 2 + +[*.js.map] +indent_size = 2 + +[*.{css,scss}] +indent_size = 2 +declarations_style = separate_lines_for_nonsingle +media_query_style = separate_lines +selector_style = same_line +properties_style = separate_lines_for_nonsingle +brace_style = next_line + +[{.analysis_options,*.yml,*.yaml}] +indent_size = 2 + +# Xml project files +[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] +indent_size = 2 + +# Xml files +[*.{xml,stylecop,resx,ruleset}] +indent_size = 2 + +# Xml config files +[*.{props,targets,config,nuspec}] +indent_size = 2 + +# .net files +[*.{cs,vb}] +# These set the this. / Me. +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning + +# These make it suggest Int32 instead of int, etc. +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# This controls implicit access modifiers +dotnet_style_require_accessibility_modifiers = never:suggestion + +# Prefer non modified fields to be marked readonly +dotnet_style_readonly_field = true:warning + +# Parenthesis settings +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_operators = always_for_clarity:warning + +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:error +dotnet_style_prefer_inferred_tuple_names = true:warning +dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning +dotnet_style_prefer_conditional_expression_over_return = true:warning +dotnet_style_coalesce_expression = true:warning +dotnet_style_null_propagation = true:error + +dotnet_sort_system_directives_first = true + +# Constants in C style, all-caps +dotnet_naming_rule.constant_fields_caps.symbols = constant_fields +dotnet_naming_rule.constant_fields_caps.severity = warning +dotnet_naming_rule.constant_fields_caps.style = caps_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.required_modifiers = const +dotnet_naming_style.caps_style.capitalization = all_upper + +# interfaces should be prefixed with I +dotnet_naming_rule.pascal_case_for_interface.severity = error +dotnet_naming_rule.pascal_case_for_interface.symbols = interfaces_fields +dotnet_naming_rule.pascal_case_for_interface.style = pascal_case_interface_style +dotnet_naming_symbols.interfaces_fields.applicable_kinds = interface +dotnet_naming_style.pascal_case_interface_style.required_prefix = I +dotnet_naming_style.pascal_case_interface_style.capitalization = pascal_case + +## internal and private fields should be _camelCase +dotnet_naming_rule.camel_case_for_private_internal_fields.severity = warning +dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields +dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style +dotnet_naming_symbols.private_internal_fields.applicable_kinds = field +dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal +dotnet_naming_style.camel_case_underscore_style.required_prefix = _ +dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case + +# 2018-12-07 NP: This is not yet working in VS2017 +# local variables should be camelCase +#dotnet_naming_rule.camel_case_for_locals.severity = suggestion +#dotnet_naming_rule.camel_case_for_locals.symbols = local_fields +#dotnet_naming_rule.camel_case_for_locals.style = camel_case_style +#dotnet_naming_symbols.local_fields.applicable_kinds = local +#dotnet_naming_style.camel_case_style.capitalization = camel_case + +[*.cs] +# var var var +csharp_style_var_for_built_in_types = false:warning +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = false:warning + +csharp_style_expression_bodied_methods = when_on_single_line:suggestion +csharp_style_expression_bodied_constructors = when_on_single_line:suggestion +csharp_style_expression_bodied_operators = when_on_single_line:suggestion +csharp_style_expression_bodied_properties = when_on_single_line:suggestion +csharp_style_expression_bodied_indexers = when_on_single_line:suggestion +csharp_style_expression_bodied_accessors = when_on_single_line:suggestion + +csharp_style_pattern_matching_over_is_with_cast_check = true:warning +csharp_style_pattern_matching_over_as_with_null_check = when_on_single_line:warning + +csharp_style_inlined_variable_declaration = true:warning + +csharp_prefer_simple_default_expression = true:warning +csharp_style_deconstructed_variable_declaration = false:warning + +csharp_style_throw_expression = true:warning +csharp_style_conditional_delegate_call = true:warning + +csharp_prefer_braces = false + +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true + +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = flush_left + +csharp_space_after_cast = false +csharp_space_after_keywords_in_control_flow_statements = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = none +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false + +csharp_preserve_single_line_statements = false +csharp_preserve_single_line_blocks = true + +csharp_blank_lines_around_region = 0 +csharp_blank_lines_inside_region = 0 +csharp_blank_lines_before_single_line_comment = 1 +csharp_keep_blank_lines_in_declarations = 1 +csharp_remove_blank_lines_near_braces_in_declarations = true +csharp_blank_lines_after_start_comment = false +csharp_blank_lines_between_using_groups = 0 +csharp_blank_lines_after_using_list = 1 +csharp_blank_lines_around_namespace = 1 +csharp_blank_lines_inside_namespace = 0 +csharp_blank_lines_around_type = 1 +csharp_blank_lines_inside_type = 0 +csharp_blank_lines_around_field = 0 +csharp_blank_lines_around_single_line_field = 0 +csharp_blank_lines_around_property = 1 +csharp_blank_lines_around_single_line_property = 0 +csharp_blank_lines_around_auto_property = 0 +csharp_blank_lines_around_single_line_auto_property = 0 +csharp_blank_lines_around_invocable = 1 +csharp_blank_lines_around_single_line_invocable = 1 +csharp_keep_blank_lines_in_code = 1 +csharp_remove_blank_lines_near_braces_in_code = true +csharp_blank_lines_around_local_method = 1 +csharp_blank_lines_around_single_line_local_method = 1 +csharp_blank_lines_before_control_transfer_statements = 1 +csharp_blank_lines_after_control_transfer_statements = 1 +csharp_blank_lines_before_block_statements = 1 +csharp_blank_lines_after_block_statements = 1 +csharp_blank_lines_before_multiline_statements = 1 +csharp_blank_lines_after_multiline_statements = 1 + +csharp_type_declaration_braces = next_line +csharp_brace_style = next_line +csharp_indent_inside_namespace = true +csharp_invocable_declaration_braces = next_line +csharp_anonymous_method_declaration_braces = next_line +csharp_accessor_owner_declaration_braces = next_line +csharp_accessor_declaration_braces = next_line +csharp_case_block_braces = next_line +csharp_initializer_braces = next_line +csharp_other_braces = next_line +csharp_allow_comment_after_lbrace = false +csharp_empty_block_style = together_same_line + +csharp_for_built_in_types = use_explicit_type +csharp_for_simple_types = use_var_when_evident +csharp_for_other_types = use_explicit_type +csharp_prefer_separate_deconstructed_variables_declaration = true +csharp_prefer_explicit_discard_declaration = false + +csharp_instance_members_qualify_members = none +csharp_builtin_type_reference_style = use_keyword +csharp_prefer_qualified_reference = false +csharp_add_imports_to_deepest_scope = false +csharp_allow_alias = true +csharp_default_private_modifier = implicit +csharp_default_internal_modifier = explicit +csharp_arguments_literal = positional +csharp_arguments_string_literal = positional +csharp_arguments_named = positional +csharp_arguments_anonymous_function = positional +csharp_arguments_other = positional +csharp_braces_for_ifelse = not_required +csharp_braces_for_for = not_required +csharp_braces_for_foreach = not_required +csharp_braces_for_while = not_required +csharp_braces_for_dowhile = not_required +csharp_braces_for_using = not_required +csharp_braces_for_lock = not_required +csharp_braces_for_fixed = not_required +csharp_method_or_operator_body = expression_body +csharp_local_function_body = expression_body +csharp_constructor_or_destructor_body = expression_body +csharp_accessor_owner_body = expression_body +csharp_force_attribute_style = join +csharp_indent_nested_usings_stmt = true + +csharp_builtin_type_reference_for_member_access_style = use_keyword +csharp_indent_nested_fixed_stmt = true +csharp_indent_nested_lock_stmt = true +csharp_indent_nested_for_stmt = true +csharp_indent_nested_foreach_stmt = true +csharp_indent_nested_while_stmt = true +csharp_use_continuous_indent_inside_parens = true +csharp_indent_method_decl_pars = inside +csharp_indent_invocation_pars = inside +csharp_indent_statement_pars = inside +csharp_indent_typeparam_angles = inside +csharp_indent_typearg_angles = inside +csharp_indent_pars = inside +csharp_indent_preprocessor_if = outdent +csharp_indent_preprocessor_region = usual_indent +csharp_indent_preprocessor_other = usual_indent +csharp_indent_switch_labels = true +csharp_indent_type_constraints = true +csharp_stick_comment = false +csharp_alignment_tab_fill_style = use_spaces +csharp_align_multiline_parameter = true +csharp_align_multiline_extends_list = true +csharp_align_linq_query = true +csharp_align_multiline_binary_expressions_chain = true +csharp_outdent_binary_ops = true +csharp_align_multiline_calls_chain = true +csharp_outdent_dots = true +csharp_align_multiline_array_and_object_initializer = false +csharp_indent_anonymous_method_block = false +csharp_align_first_arg_by_paren = true +csharp_align_multiline_argument = true +csharp_align_tuple_components = true +csharp_align_multiline_expression = true +csharp_align_multiline_for_stmt = true +csharp_align_multiple_declaration = true +csharp_align_multline_type_parameter_list = true +csharp_align_multline_type_parameter_constrains = true +csharp_int_align_fields = true +csharp_int_align_properties = true +csharp_int_align_methods = true +csharp_int_align_parameters = false +csharp_int_align_variables = true +csharp_int_align_assignments = true +csharp_int_align_nested_ternary = true +csharp_int_align_invocations = false +csharp_int_align_binary_expressions = true +csharp_int_align_comments = true +csharp_int_align_switch_sections = true +csharp_int_align = true +csharp_keep_user_linebreaks = false +csharp_keep_existing_arrangement = false +csharp_keep_existing_linebreaks = false +csharp_max_line_length = 120 +csharp_wrap_before_comma = false +csharp_special_else_if_treatment = true +csharp_insert_final_newline = false +csharp_place_type_attribute_on_same_line = never +csharp_place_method_attribute_on_same_line = never +csharp_place_accessorholder_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_place_accessor_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_place_field_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_wrap_parameters_style = wrap_if_long +csharp_keep_existing_declaration_parens_arrangement = false +csharp_wrap_before_declaration_lpar = false +csharp_wrap_after_declaration_lpar = false +csharp_wrap_before_declaration_rpar = false +csharp_place_constructor_initializer_on_same_line = true +csharp_keep_existing_expr_member_arrangement = false +csharp_place_expr_method_on_single_line = true +csharp_place_expr_property_on_single_line = true +csharp_place_expr_accessor_on_single_line = true +csharp_wrap_before_arrow_with_expressions = false +csharp_place_type_constraints_on_same_line = true +csharp_wrap_before_first_type_parameter_constraint = true +csharp_wrap_multiple_type_parameter_constraints_style = wrap_if_long +csharp_wrap_before_type_parameter_langle = true +csharp_wrap_before_extends_colon = false +csharp_wrap_extends_list_style = wrap_if_long +csharp_keep_existing_declaration_block_arrangement = false +csharp_place_abstract_accessorholder_on_single_line = true +csharp_place_simple_accessorholder_on_single_line = false +csharp_place_accessor_with_attrs_holder_on_single_line = false +csharp_place_simple_accessor_on_single_line = true +csharp_place_simple_method_on_single_line = false +csharp_keep_existing_enum_arrangement = false +csharp_place_simple_enum_on_single_line = false +csharp_wrap_enum_declaration = wrap_if_long +csharp_new_line_before_else = true +csharp_new_line_before_while = false +csharp_wrap_for_stmt_header_style = wrap_if_long +csharp_wrap_multiple_declaration_style = wrap_if_long +csharp_keep_existing_embedded_arrangement = false +csharp_place_simple_embedded_statement_on_same_line = false +csharp_place_simple_case_statement_on_same_line = true +csharp_keep_existing_embedded_block_arrangement = false +csharp_place_simple_embedded_block_on_same_line = false +csharp_place_simple_anonymousmethod_on_single_line = false +csharp_keep_existing_initializer_arrangement = false +csharp_place_simple_initializer_on_single_line = false +csharp_wrap_object_and_collection_initializer_style = chop_always +csharp_wrap_array_initializer_style = wrap_if_long +csharp_wrap_arguments_style = wrap_if_long +csharp_keep_existing_invocation_parens_arrangement = false +csharp_wrap_after_invocation_lpar = false +csharp_wrap_before_invocation_rpar = false +csharp_wrap_after_dot_in_method_calls = true +csharp_wrap_chained_method_calls = wrap_if_long +csharp_wrap_before_binary_opsign = false +csharp_wrap_chained_binary_expressions = wrap_if_long +csharp_force_chop_compound_if_expression = true +csharp_force_chop_compound_while_expression = true +csharp_force_chop_compound_do_expression = true +csharp_wrap_before_ternary_opsigns = true +csharp_wrap_ternary_expr_style = wrap_if_long +csharp_nested_ternary_style = expanded +csharp_wrap_linq_expressions = wrap_if_long +csharp_wrap_before_linq_expression = false +csharp_place_linq_into_on_new_line = false +csharp_wrap_verbatim_interpolated_strings = wrap_if_long +csharp_extra_spaces = remove_all +csharp_space_after_keywords_in_control_flow_statements = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_before_typeof_parentheses = false +csharp_space_before_checked_parentheses = false +csharp_space_before_sizeof_parentheses = false +csharp_space_before_nameof_parentheses = false +csharp_space_between_keyword_and_expression = true +csharp_space_between_keyword_and_type = true +csharp_space_around_assignment_op = true +csharp_space_around_logical_op = true +csharp_space_around_binary_operator = true +csharp_space_around_equality_op = true +csharp_space_around_relational_op = true +csharp_space_around_bitwise_op = true +csharp_space_around_additive_op = true +csharp_space_around_multiplicative_op = true +csharp_space_around_shift_op = true +csharp_space_around_nullcoalescing_op = true +csharp_space_around_arrow_op = false +csharp_space_after_logical_not_op = false +csharp_space_after_unary_operator = false +csharp_space_after_cast = false +csharp_space_around_dot = false +csharp_space_around_lambda_arrow = true +csharp_space_before_pointer_asterik_declaration = false +csharp_space_before_nullable_mark = false + +[*.cshtml] +linebreaks_around_razor_statements = true +blank_lines_around_razor_functions = true +blank_lines_around_razor_helpers = true +blank_lines_around_razor_sections = true + +# C++ +[*.{cc,cpp,cxx,h,hpp,hxx}] +cpp_indent_access_specifiers_from_class = true +cpp_indent_wrapped_function_names = false +cpp_align_multiline_type_argument = true + +# C, C++ and ObjectiveC +[*.{c,h,cc,cpp,cxx,m,hpp,hxx}] +indent_preprocessor_directives = normal +indent_type_constraints = true + +# Javascript and Typescript +[*.{js,js.map,ts}] +quote_style = doublequoted +termination_style = ensure_semicolon \ No newline at end of file diff --git a/Aaru.Decoders/.gitignore b/Aaru.Decoders/.gitignore new file mode 100644 index 000000000..05c540d38 --- /dev/null +++ b/Aaru.Decoders/.gitignore @@ -0,0 +1,595 @@ +### VisualStudio template +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ +### Linux template + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* +### Xcode template +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +### VisualStudioCode template +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +### C++ template +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o + +# Precompiled Headers +*.gch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +### MonoDevelop template +#User Specific +*.usertasks + +#Mono Project Files +*.resources +test-results/ +### GPG template +secring.* + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests +### CMake template +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +### C template +# Object files +*.ko +*.elf + +# Linker output +*.map +*.exp + +*.so.* + +# Executables +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf +### Windows template +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# NuGet Packages Directory +packages/ +## TODO: If the tool you use requires repositories.config uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +# This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented) +!packages/build/ + + +# Others +sql/ +*.Cache + +# Visual Studio 2017 +.vs + +workspace.xml +cmake-build-debug +### macOS template +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +pkg/**/pkg +pkg/**/src +pkg/**/*.asc +pkg/**/*.sig +pkg/**/*.tar.xz +pkg/**/*.zip +pkg/**/aaru + +.sonarqube \ No newline at end of file diff --git a/Aaru.Decoders/ATA/Identify.cs b/Aaru.Decoders/ATA/Identify.cs new file mode 100644 index 000000000..0061756b1 --- /dev/null +++ b/Aaru.Decoders/ATA/Identify.cs @@ -0,0 +1,2243 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Identify.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes ATA IDENTIFY DEVICE response. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.CommonTypes.Structs.Devices.SCSI; + +namespace Aaru.Decoders.ATA +{ + // Information from following standards: + // T10-791D rev. 4c (ATA) + // T10-948D rev. 4c (ATA-2) + // T13-1153D rev. 18 (ATA/ATAPI-4) + // T13-1321D rev. 3 (ATA/ATAPI-5) + // T13-1410D rev. 3b (ATA/ATAPI-6) + // T13-1532D rev. 4b (ATA/ATAPI-7) + // T13-1699D rev. 3f (ATA8-ACS) + // T13-1699D rev. 4a (ATA8-ACS) + // T13-2015D rev. 2 (ACS-2) + // T13-2161D rev. 5 (ACS-3) + // CF+ & CF Specification rev. 1.4 (CFA) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class Identify + { + public static string Prettify(byte[] IdentifyDeviceResponse) + { + if(IdentifyDeviceResponse.Length != 512) + return null; + + CommonTypes.Structs.Devices.ATA.Identify.IdentifyDevice? decoded = + CommonTypes.Structs.Devices.ATA.Identify.Decode(IdentifyDeviceResponse); + + return Prettify(decoded); + } + + public static string Prettify(CommonTypes.Structs.Devices.ATA.Identify.IdentifyDevice? IdentifyDeviceResponse) + { + if(IdentifyDeviceResponse == null) + return null; + + var sb = new StringBuilder(); + + bool atapi = false; + bool cfa = false; + + CommonTypes.Structs.Devices.ATA.Identify.IdentifyDevice ATAID = IdentifyDeviceResponse.Value; + + if(ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.GeneralConfigurationBit. + NonMagnetic)) + if((ushort)ATAID.GeneralConfiguration != 0x848A) + atapi = true; + else + cfa = true; + + if(atapi) + sb.AppendLine("ATAPI device"); + else if(cfa) + sb.AppendLine("CompactFlash device"); + else + sb.AppendLine("ATA device"); + + if(ATAID.Model != "") + sb.AppendFormat("Model: {0}", ATAID.Model).AppendLine(); + + if(ATAID.FirmwareRevision != "") + sb.AppendFormat("Firmware revision: {0}", ATAID.FirmwareRevision).AppendLine(); + + if(ATAID.SerialNumber != "") + sb.AppendFormat("Serial #: {0}", ATAID.SerialNumber).AppendLine(); + + if(ATAID.AdditionalPID != "") + sb.AppendFormat("Additional product ID: {0}", ATAID.AdditionalPID).AppendLine(); + + if(ATAID.CommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.MustBeSet) && + !ATAID.CommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.MustBeClear)) + { + if(ATAID.EnabledCommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3. + MediaSerial)) + { + if(ATAID.MediaManufacturer != "") + sb.AppendFormat("Media manufacturer: {0}", ATAID.MediaManufacturer).AppendLine(); + + if(ATAID.MediaSerial != "") + sb.AppendFormat("Media serial #: {0}", ATAID.MediaSerial).AppendLine(); + } + + if(ATAID.EnabledCommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.WWN)) + sb.AppendFormat("World Wide Name: {0:X16}", ATAID.WWN).AppendLine(); + } + + bool ata1 = false, ata2 = false, ata3 = false, ata4 = false, ata5 = false, ata6 = false, ata7 = false, + acs = false, acs2 = false, acs3 = false, acs4 = false; + + if((ushort)ATAID.MajorVersion == 0x0000 || + (ushort)ATAID.MajorVersion == 0xFFFF) + { + // Obsolete in ATA-2, if present, device supports ATA-1 + ata1 |= + ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.GeneralConfigurationBit. + FastIDE) || + ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.GeneralConfigurationBit. + SlowIDE) || + ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.GeneralConfigurationBit. + UltraFastIDE); + + ata2 |= ATAID.ExtendedIdentify.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.ExtendedIdentifyBit. + Words64to70Valid); + + if(!ata1 && + !ata2 && + !atapi && + !cfa) + ata2 = true; + + ata4 |= atapi; + ata3 |= cfa; + + if(cfa && ata1) + ata1 = false; + + if(cfa && ata2) + ata2 = false; + + ata5 |= ATAID.Signature == 0xA5; + } + else + { + ata1 |= ATAID.MajorVersion.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.MajorVersionBit.Ata1); + ata2 |= ATAID.MajorVersion.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.MajorVersionBit.Ata2); + ata3 |= ATAID.MajorVersion.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.MajorVersionBit.Ata3); + ata4 |= ATAID.MajorVersion.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.MajorVersionBit.AtaAtapi4); + ata5 |= ATAID.MajorVersion.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.MajorVersionBit.AtaAtapi5); + ata6 |= ATAID.MajorVersion.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.MajorVersionBit.AtaAtapi6); + ata7 |= ATAID.MajorVersion.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.MajorVersionBit.AtaAtapi7); + acs |= ATAID.MajorVersion.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.MajorVersionBit.Ata8ACS); + acs2 |= ATAID.MajorVersion.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.MajorVersionBit.ACS2); + acs3 |= ATAID.MajorVersion.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.MajorVersionBit.ACS3); + acs4 |= ATAID.MajorVersion.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.MajorVersionBit.ACS4); + } + + int maxatalevel = 0; + int minatalevel = 255; + sb.Append("Supported ATA versions: "); + + if(ata1) + { + sb.Append("ATA-1 "); + maxatalevel = 1; + minatalevel = 1; + } + + if(ata2) + { + sb.Append("ATA-2 "); + maxatalevel = 2; + + if(minatalevel > 2) + minatalevel = 2; + } + + if(ata3) + { + sb.Append("ATA-3 "); + maxatalevel = 3; + + if(minatalevel > 3) + minatalevel = 3; + } + + if(ata4) + { + sb.Append("ATA/ATAPI-4 "); + maxatalevel = 4; + + if(minatalevel > 4) + minatalevel = 4; + } + + if(ata5) + { + sb.Append("ATA/ATAPI-5 "); + maxatalevel = 5; + + if(minatalevel > 5) + minatalevel = 5; + } + + if(ata6) + { + sb.Append("ATA/ATAPI-6 "); + maxatalevel = 6; + + if(minatalevel > 6) + minatalevel = 6; + } + + if(ata7) + { + sb.Append("ATA/ATAPI-7 "); + maxatalevel = 7; + + if(minatalevel > 7) + minatalevel = 7; + } + + if(acs) + { + sb.Append("ATA8-ACS "); + maxatalevel = 8; + + if(minatalevel > 8) + minatalevel = 8; + } + + if(acs2) + { + sb.Append("ATA8-ACS2 "); + maxatalevel = 9; + + if(minatalevel > 9) + minatalevel = 9; + } + + if(acs3) + { + sb.Append("ATA8-ACS3 "); + maxatalevel = 10; + + if(minatalevel > 10) + minatalevel = 10; + } + + if(acs4) + { + sb.Append("ATA8-ACS4 "); + maxatalevel = 11; + + if(minatalevel > 11) + minatalevel = 11; + } + + sb.AppendLine(); + + sb.Append("Maximum ATA revision supported: "); + + if(maxatalevel >= 3) + switch(ATAID.MinorVersion) + { + case 0x0000: + case 0xFFFF: + sb.AppendLine("Minor ATA version not specified"); + + break; + case 0x0001: + sb.AppendLine("ATA (ATA-1) X3T9.2 781D prior to revision 4"); + + break; + case 0x0002: + sb.AppendLine("ATA-1 published, ANSI X3.221-1994"); + + break; + case 0x0003: + sb.AppendLine("ATA (ATA-1) X3T9.2 781D revision 4"); + + break; + case 0x0004: + sb.AppendLine("ATA-2 published, ANSI X3.279-1996"); + + break; + case 0x0005: + sb.AppendLine("ATA-2 X3T10 948D prior to revision 2k"); + + break; + case 0x0006: + sb.AppendLine("ATA-3 X3T10 2008D revision 1"); + + break; + case 0x0007: + sb.AppendLine("ATA-2 X3T10 948D revision 2k"); + + break; + case 0x0008: + sb.AppendLine("ATA-3 X3T10 2008D revision 0"); + + break; + case 0x0009: + sb.AppendLine("ATA-2 X3T10 948D revision 3"); + + break; + case 0x000A: + sb.AppendLine("ATA-3 published, ANSI X3.298-1997"); + + break; + case 0x000B: + sb.AppendLine("ATA-3 X3T10 2008D revision 6"); + + break; + case 0x000C: + sb.AppendLine("ATA-3 X3T13 2008D revision 7"); + + break; + case 0x000D: + sb.AppendLine("ATA/ATAPI-4 X3T13 1153D revision 6"); + + break; + case 0x000E: + sb.AppendLine("ATA/ATAPI-4 T13 1153D revision 13"); + + break; + case 0x000F: + sb.AppendLine("ATA/ATAPI-4 X3T13 1153D revision 7"); + + break; + case 0x0010: + sb.AppendLine("ATA/ATAPI-4 T13 1153D revision 18"); + + break; + case 0x0011: + sb.AppendLine("ATA/ATAPI-4 T13 1153D revision 15"); + + break; + case 0x0012: + sb.AppendLine("ATA/ATAPI-4 published, ANSI INCITS 317-1998"); + + break; + case 0x0013: + sb.AppendLine("ATA/ATAPI-5 T13 1321D revision 3"); + + break; + case 0x0014: + sb.AppendLine("ATA/ATAPI-4 T13 1153D revision 14"); + + break; + case 0x0015: + sb.AppendLine("ATA/ATAPI-5 T13 1321D revision 1"); + + break; + case 0x0016: + sb.AppendLine("ATA/ATAPI-5 published, ANSI INCITS 340-2000"); + + break; + case 0x0017: + sb.AppendLine("ATA/ATAPI-4 T13 1153D revision 17"); + + break; + case 0x0018: + sb.AppendLine("ATA/ATAPI-6 T13 1410D revision 0"); + + break; + case 0x0019: + sb.AppendLine("ATA/ATAPI-6 T13 1410D revision 3a"); + + break; + case 0x001A: + sb.AppendLine("ATA/ATAPI-7 T13 1532D revision 1"); + + break; + case 0x001B: + sb.AppendLine("ATA/ATAPI-6 T13 1410D revision 2"); + + break; + case 0x001C: + sb.AppendLine("ATA/ATAPI-6 T13 1410D revision 1"); + + break; + case 0x001D: + sb.AppendLine("ATA/ATAPI-7 published ANSI INCITS 397-2005"); + + break; + case 0x001E: + sb.AppendLine("ATA/ATAPI-7 T13 1532D revision 0"); + + break; + case 0x001F: + sb.AppendLine("ACS-3 Revision 3b"); + + break; + case 0x0021: + sb.AppendLine("ATA/ATAPI-7 T13 1532D revision 4a"); + + break; + case 0x0022: + sb.AppendLine("ATA/ATAPI-6 published, ANSI INCITS 361-2002"); + + break; + case 0x0027: + sb.AppendLine("ATA8-ACS revision 3c"); + + break; + case 0x0028: + sb.AppendLine("ATA8-ACS revision 6"); + + break; + case 0x0029: + sb.AppendLine("ATA8-ACS revision 4"); + + break; + case 0x0031: + sb.AppendLine("ACS-2 Revision 2"); + + break; + case 0x0033: + sb.AppendLine("ATA8-ACS Revision 3e"); + + break; + case 0x0039: + sb.AppendLine("ATA8-ACS Revision 4c"); + + break; + case 0x0042: + sb.AppendLine("ATA8-ACS Revision 3f"); + + break; + case 0x0052: + sb.AppendLine("ATA8-ACS revision 3b"); + + break; + case 0x006D: + sb.AppendLine("ACS-3 Revision 5"); + + break; + case 0x0082: + sb.AppendLine("ACS-2 published, ANSI INCITS 482-2012"); + + break; + case 0x0107: + sb.AppendLine("ATA8-ACS revision 2d"); + + break; + case 0x0110: + sb.AppendLine("ACS-2 Revision 3"); + + break; + case 0x011B: + sb.AppendLine("ACS-3 Revision 4"); + + break; + default: + sb.AppendFormat("Unknown ATA revision 0x{0:X4}", ATAID.MinorVersion).AppendLine(); + + break; + } + + switch((ATAID.TransportMajorVersion & 0xF000) >> 12) + { + case 0x0: + sb.Append("Parallel ATA device: "); + + if((ATAID.TransportMajorVersion & 0x0002) == 0x0002) + sb.Append("ATA/ATAPI-7 "); + + if((ATAID.TransportMajorVersion & 0x0001) == 0x0001) + sb.Append("ATA8-APT "); + + sb.AppendLine(); + + break; + case 0x1: + sb.Append("Serial ATA device: "); + + if((ATAID.TransportMajorVersion & 0x0001) == 0x0001) + sb.Append("ATA8-AST "); + + if((ATAID.TransportMajorVersion & 0x0002) == 0x0002) + sb.Append("SATA 1.0a "); + + if((ATAID.TransportMajorVersion & 0x0004) == 0x0004) + sb.Append("SATA II Extensions "); + + if((ATAID.TransportMajorVersion & 0x0008) == 0x0008) + sb.Append("SATA 2.5 "); + + if((ATAID.TransportMajorVersion & 0x0010) == 0x0010) + sb.Append("SATA 2.6 "); + + if((ATAID.TransportMajorVersion & 0x0020) == 0x0020) + sb.Append("SATA 3.0 "); + + if((ATAID.TransportMajorVersion & 0x0040) == 0x0040) + sb.Append("SATA 3.1 "); + + sb.AppendLine(); + + break; + case 0xE: + sb.AppendLine("SATA Express device"); + + break; + default: + sb.AppendFormat("Unknown transport type 0x{0:X1}", (ATAID.TransportMajorVersion & 0xF000) >> 12). + AppendLine(); + + break; + } + + if(atapi) + { + // Bits 12 to 8, SCSI Peripheral Device Type + switch((PeripheralDeviceTypes)(((ushort)ATAID.GeneralConfiguration & 0x1F00) >> 8)) + { + case PeripheralDeviceTypes.DirectAccess: //0x00, + sb.AppendLine("ATAPI Direct-access device"); + + break; + case PeripheralDeviceTypes.SequentialAccess: //0x01, + sb.AppendLine("ATAPI Sequential-access device"); + + break; + case PeripheralDeviceTypes.PrinterDevice: //0x02, + sb.AppendLine("ATAPI Printer device"); + + break; + case PeripheralDeviceTypes.ProcessorDevice: //0x03, + sb.AppendLine("ATAPI Processor device"); + + break; + case PeripheralDeviceTypes.WriteOnceDevice: //0x04, + sb.AppendLine("ATAPI Write-once device"); + + break; + case PeripheralDeviceTypes.MultiMediaDevice: //0x05, + sb.AppendLine("ATAPI CD-ROM/DVD/etc device"); + + break; + case PeripheralDeviceTypes.ScannerDevice: //0x06, + sb.AppendLine("ATAPI Scanner device"); + + break; + case PeripheralDeviceTypes.OpticalDevice: //0x07, + sb.AppendLine("ATAPI Optical memory device"); + + break; + case PeripheralDeviceTypes.MediumChangerDevice: //0x08, + sb.AppendLine("ATAPI Medium change device"); + + break; + case PeripheralDeviceTypes.CommsDevice: //0x09, + sb.AppendLine("ATAPI Communications device"); + + break; + case PeripheralDeviceTypes.PrePressDevice1: //0x0A, + sb.AppendLine("ATAPI Graphics arts pre-press device (defined in ASC IT8)"); + + break; + case PeripheralDeviceTypes.PrePressDevice2: //0x0B, + sb.AppendLine("ATAPI Graphics arts pre-press device (defined in ASC IT8)"); + + break; + case PeripheralDeviceTypes.ArrayControllerDevice: //0x0C, + sb.AppendLine("ATAPI Array controller device"); + + break; + case PeripheralDeviceTypes.EnclosureServiceDevice: //0x0D, + sb.AppendLine("ATAPI Enclosure services device"); + + break; + case PeripheralDeviceTypes.SimplifiedDevice: //0x0E, + sb.AppendLine("ATAPI Simplified direct-access device"); + + break; + case PeripheralDeviceTypes.OCRWDevice: //0x0F, + sb.AppendLine("ATAPI Optical card reader/writer device"); + + break; + case PeripheralDeviceTypes.BridgingExpander: //0x10, + sb.AppendLine("ATAPI Bridging Expanders"); + + break; + case PeripheralDeviceTypes.ObjectDevice: //0x11, + sb.AppendLine("ATAPI Object-based Storage Device"); + + break; + case PeripheralDeviceTypes.ADCDevice: //0x12, + sb.AppendLine("ATAPI Automation/Drive Interface"); + + break; + case PeripheralDeviceTypes.WellKnownDevice: //0x1E, + sb.AppendLine("ATAPI Well known logical unit"); + + break; + case PeripheralDeviceTypes.UnknownDevice: //0x1F + sb.AppendLine("ATAPI Unknown or no device type"); + + break; + default: + sb.AppendFormat("ATAPI Unknown device type field value 0x{0:X2}", + ((ushort)ATAID.GeneralConfiguration & 0x1F00) >> 8).AppendLine(); + + break; + } + + // ATAPI DRQ behaviour + switch(((ushort)ATAID.GeneralConfiguration & 0x60) >> 5) + { + case 0: + sb.AppendLine("Device shall set DRQ within 3 ms of receiving PACKET"); + + break; + case 1: + sb.AppendLine("Device shall assert INTRQ when DRQ is set to one"); + + break; + case 2: + sb.AppendLine("Device shall set DRQ within 50 µs of receiving PACKET"); + + break; + default: + sb.AppendFormat("Unknown ATAPI DRQ behaviour code {0}", + ((ushort)ATAID.GeneralConfiguration & 0x60) >> 5).AppendLine(); + + break; + } + + // ATAPI PACKET size + switch((ushort)ATAID.GeneralConfiguration & 0x03) + { + case 0: + sb.AppendLine("ATAPI device uses 12 byte command packet"); + + break; + case 1: + sb.AppendLine("ATAPI device uses 16 byte command packet"); + + break; + default: + sb.AppendFormat("Unknown ATAPI packet size code {0}", + (ushort)ATAID.GeneralConfiguration & 0x03).AppendLine(); + + break; + } + } + else if(!cfa) + { + if(minatalevel >= 5) + if(ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + GeneralConfigurationBit.IncompleteResponse)) + sb.AppendLine("Incomplete identify response"); + + if(ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.GeneralConfigurationBit. + NonMagnetic)) + sb.AppendLine("Device uses non-magnetic media"); + + if(ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.GeneralConfigurationBit. + Removable)) + sb.AppendLine("Device is removable"); + + if(minatalevel <= 5) + if(ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + GeneralConfigurationBit.Fixed)) + sb.AppendLine("Device is fixed"); + + if(ata1) + { + if(ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + GeneralConfigurationBit.SlowIDE)) + sb.AppendLine("Device transfer rate is <= 5 Mb/s"); + + if(ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + GeneralConfigurationBit.FastIDE)) + sb.AppendLine("Device transfer rate is > 5 Mb/s but <= 10 Mb/s"); + + if(ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + GeneralConfigurationBit.UltraFastIDE)) + sb.AppendLine("Device transfer rate is > 10 Mb/s"); + + if(ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + GeneralConfigurationBit.SoftSector)) + sb.AppendLine("Device is soft sectored"); + + if(ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + GeneralConfigurationBit.HardSector)) + sb.AppendLine("Device is hard sectored"); + + if(ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + GeneralConfigurationBit.NotMFM)) + sb.AppendLine("Device is not MFM encoded"); + + if(ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + GeneralConfigurationBit.FormatGapReq)) + sb.AppendLine("Format speed tolerance gap is required"); + + if(ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + GeneralConfigurationBit.TrackOffset)) + sb.AppendLine("Track offset option is available"); + + if(ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + GeneralConfigurationBit.DataStrobeOffset)) + sb.AppendLine("Data strobe offset option is available"); + + if(ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + GeneralConfigurationBit.RotationalSpeedTolerance)) + sb.AppendLine("Rotational speed tolerance is higher than 0,5%"); + + if(ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + GeneralConfigurationBit.SpindleControl)) + sb.AppendLine("Spindle motor control is implemented"); + + if(ATAID.GeneralConfiguration.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + GeneralConfigurationBit.HighHeadSwitch)) + sb.AppendLine("Head switch time is bigger than 15 µs."); + } + } + + if(ATAID.NominalRotationRate != 0x0000 && + ATAID.NominalRotationRate != 0xFFFF) + if(ATAID.NominalRotationRate == 0x0001) + sb.AppendLine("Device does not rotate."); + else + sb.AppendFormat("Device rotate at {0} rpm", ATAID.NominalRotationRate).AppendLine(); + + uint logicalSectorSize = 0; + + if(!atapi) + { + uint physicalSectorSize; + + if((ATAID.PhysLogSectorSize & 0x8000) == 0x0000 && + (ATAID.PhysLogSectorSize & 0x4000) == 0x4000) + { + if((ATAID.PhysLogSectorSize & 0x1000) == 0x1000) + if(ATAID.LogicalSectorWords <= 255 || + ATAID.LogicalAlignment == 0xFFFF) + logicalSectorSize = 512; + else + logicalSectorSize = ATAID.LogicalSectorWords * 2; + else + logicalSectorSize = 512; + + if((ATAID.PhysLogSectorSize & 0x2000) == 0x2000) + physicalSectorSize = logicalSectorSize * (uint)Math.Pow(2, ATAID.PhysLogSectorSize & 0xF); + else + physicalSectorSize = logicalSectorSize; + } + else + { + logicalSectorSize = 512; + physicalSectorSize = 512; + } + + sb.AppendFormat("Physical sector size: {0} bytes", physicalSectorSize).AppendLine(); + sb.AppendFormat("Logical sector size: {0} bytes", logicalSectorSize).AppendLine(); + + if(logicalSectorSize != physicalSectorSize && + (ATAID.LogicalAlignment & 0x8000) == 0x0000 && + (ATAID.LogicalAlignment & 0x4000) == 0x4000) + sb.AppendFormat("Logical sector starts at offset {0} from physical sector", + ATAID.LogicalAlignment & 0x3FFF).AppendLine(); + + if(minatalevel <= 5) + if(ATAID.CurrentCylinders > 0 && + ATAID.CurrentHeads > 0 && + ATAID.CurrentSectorsPerTrack > 0) + { + sb.AppendFormat("Cylinders: {0} max., {1} current", ATAID.Cylinders, ATAID.CurrentCylinders). + AppendLine(); + + sb.AppendFormat("Heads: {0} max., {1} current", ATAID.Heads, ATAID.CurrentHeads).AppendLine(); + + sb.AppendFormat("Sectors per track: {0} max., {1} current", ATAID.SectorsPerTrack, + ATAID.CurrentSectorsPerTrack).AppendLine(); + + sb.AppendFormat("Sectors addressable in CHS mode: {0} max., {1} current", + ATAID.Cylinders * ATAID.Heads * ATAID.SectorsPerTrack, ATAID.CurrentSectors). + AppendLine(); + } + else + { + sb.AppendFormat("Cylinders: {0}", ATAID.Cylinders).AppendLine(); + sb.AppendFormat("Heads: {0}", ATAID.Heads).AppendLine(); + sb.AppendFormat("Sectors per track: {0}", ATAID.SectorsPerTrack).AppendLine(); + + sb.AppendFormat("Sectors addressable in CHS mode: {0}", + ATAID.Cylinders * ATAID.Heads * ATAID.SectorsPerTrack).AppendLine(); + } + + if(ATAID.Capabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit.LBASupport)) + sb.AppendFormat("{0} sectors in 28-bit LBA mode", ATAID.LBASectors).AppendLine(); + + if(ATAID.CommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.LBA48)) + sb.AppendFormat("{0} sectors in 48-bit LBA mode", ATAID.LBA48Sectors).AppendLine(); + + if(minatalevel <= 5) + if(ATAID.CurrentSectors > 0) + sb.AppendFormat("Device size in CHS mode: {0} bytes, {1} Mb, {2} MiB", + (ulong)ATAID.CurrentSectors * logicalSectorSize, + (ulong)ATAID.CurrentSectors * logicalSectorSize / 1000 / 1000, + (ulong)ATAID.CurrentSectors * 512 / 1024 / 1024).AppendLine(); + else + { + ulong currentSectors = (ulong)(ATAID.Cylinders * ATAID.Heads * ATAID.SectorsPerTrack); + + sb.AppendFormat("Device size in CHS mode: {0} bytes, {1} Mb, {2} MiB", + currentSectors * logicalSectorSize, + currentSectors * logicalSectorSize / 1000 / 1000, + currentSectors * 512 / 1024 / 1024).AppendLine(); + } + + if(ATAID.Capabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit.LBASupport)) + if((ulong)ATAID.LBASectors * logicalSectorSize / 1024 / 1024 > 1000000) + sb.AppendFormat("Device size in 28-bit LBA mode: {0} bytes, {1} Tb, {2} TiB", + (ulong)ATAID.LBASectors * logicalSectorSize, + (ulong)ATAID.LBASectors * logicalSectorSize / 1000 / 1000 / 1000 / 1000, + (ulong)ATAID.LBASectors * 512 / 1024 / 1024 / 1024 / 1024).AppendLine(); + else if((ulong)ATAID.LBASectors * logicalSectorSize / 1024 / 1024 > 1000) + sb.AppendFormat("Device size in 28-bit LBA mode: {0} bytes, {1} Gb, {2} GiB", + (ulong)ATAID.LBASectors * logicalSectorSize, + (ulong)ATAID.LBASectors * logicalSectorSize / 1000 / 1000 / 1000, + (ulong)ATAID.LBASectors * 512 / 1024 / 1024 / 1024).AppendLine(); + else + sb.AppendFormat("Device size in 28-bit LBA mode: {0} bytes, {1} Mb, {2} MiB", + (ulong)ATAID.LBASectors * logicalSectorSize, + (ulong)ATAID.LBASectors * logicalSectorSize / 1000 / 1000, + (ulong)ATAID.LBASectors * 512 / 1024 / 1024).AppendLine(); + + if(ATAID.CommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.LBA48)) + if(ATAID.CommandSet5.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit5.ExtSectors)) + if(ATAID.ExtendedUserSectors * logicalSectorSize / 1024 / 1024 > 1000000) + sb.AppendFormat("Device size in 48-bit LBA mode: {0} bytes, {1} Tb, {2} TiB", + ATAID.ExtendedUserSectors * logicalSectorSize, + ATAID.ExtendedUserSectors * logicalSectorSize / 1000 / 1000 / 1000 / 1000, + ATAID.ExtendedUserSectors * logicalSectorSize / 1024 / 1024 / 1024 / 1024). + AppendLine(); + else if(ATAID.ExtendedUserSectors * logicalSectorSize / 1024 / 1024 > 1000) + sb.AppendFormat("Device size in 48-bit LBA mode: {0} bytes, {1} Gb, {2} GiB", + ATAID.ExtendedUserSectors * logicalSectorSize, + ATAID.ExtendedUserSectors * logicalSectorSize / 1000 / 1000 / 1000, + ATAID.ExtendedUserSectors * logicalSectorSize / 1024 / 1024 / 1024). + AppendLine(); + else + sb.AppendFormat("Device size in 48-bit LBA mode: {0} bytes, {1} Mb, {2} MiB", + ATAID.ExtendedUserSectors * logicalSectorSize, + ATAID.ExtendedUserSectors * logicalSectorSize / 1000 / 1000, + ATAID.ExtendedUserSectors * logicalSectorSize / 1024 / 1024).AppendLine(); + else + { + if(ATAID.LBA48Sectors * logicalSectorSize / 1024 / 1024 > 1000000) + sb.AppendFormat("Device size in 48-bit LBA mode: {0} bytes, {1} Tb, {2} TiB", + ATAID.LBA48Sectors * logicalSectorSize, + ATAID.LBA48Sectors * logicalSectorSize / 1000 / 1000 / 1000 / 1000, + ATAID.LBA48Sectors * logicalSectorSize / 1024 / 1024 / 1024 / 1024). + AppendLine(); + else if(ATAID.LBA48Sectors * logicalSectorSize / 1024 / 1024 > 1000) + sb.AppendFormat("Device size in 48-bit LBA mode: {0} bytes, {1} Gb, {2} GiB", + ATAID.LBA48Sectors * logicalSectorSize, + ATAID.LBA48Sectors * logicalSectorSize / 1000 / 1000 / 1000, + ATAID.LBA48Sectors * logicalSectorSize / 1024 / 1024 / 1024).AppendLine(); + else + sb.AppendFormat("Device size in 48-bit LBA mode: {0} bytes, {1} Mb, {2} MiB", + ATAID.LBA48Sectors * logicalSectorSize, + ATAID.LBA48Sectors * logicalSectorSize / 1000 / 1000, + ATAID.LBA48Sectors * logicalSectorSize / 1024 / 1024).AppendLine(); + } + + if(ata1 || cfa) + { + if(cfa) + sb.AppendFormat("{0} sectors in card", ATAID.SectorsPerCard).AppendLine(); + + if(ATAID.UnformattedBPT > 0) + sb.AppendFormat("{0} bytes per unformatted track", ATAID.UnformattedBPT).AppendLine(); + + if(ATAID.UnformattedBPS > 0) + sb.AppendFormat("{0} bytes per unformatted sector", ATAID.UnformattedBPS).AppendLine(); + } + } + + if((ushort)ATAID.SpecificConfiguration != 0x0000 && + (ushort)ATAID.SpecificConfiguration != 0xFFFF) + switch(ATAID.SpecificConfiguration) + { + case CommonTypes.Structs.Devices.ATA.Identify.SpecificConfigurationEnum. + RequiresSetIncompleteResponse: + sb.AppendLine("Device requires SET FEATURES to spin up and IDENTIFY DEVICE response is incomplete."); + + break; + case CommonTypes.Structs.Devices.ATA.Identify.SpecificConfigurationEnum.RequiresSetCompleteResponse: + sb.AppendLine("Device requires SET FEATURES to spin up and IDENTIFY DEVICE response is complete."); + + break; + case CommonTypes.Structs.Devices.ATA.Identify.SpecificConfigurationEnum. + NotRequiresSetIncompleteResponse: + sb.AppendLine("Device does not require SET FEATURES to spin up and IDENTIFY DEVICE response is incomplete."); + + break; + case CommonTypes.Structs.Devices.ATA.Identify.SpecificConfigurationEnum. + NotRequiresSetCompleteResponse: + sb.AppendLine("Device does not require SET FEATURES to spin up and IDENTIFY DEVICE response is complete."); + + break; + default: + sb.AppendFormat("Unknown device specific configuration 0x{0:X4}", + (ushort)ATAID.SpecificConfiguration).AppendLine(); + + break; + } + + // Obsolete since ATA-2, however, it is yet used in ATA-8 devices + if(ATAID.BufferSize != 0x0000 && + ATAID.BufferSize != 0xFFFF && + ATAID.BufferType != 0x0000 && + ATAID.BufferType != 0xFFFF) + switch(ATAID.BufferType) + { + case 1: + sb.AppendFormat("{0} KiB of single ported single sector buffer", ATAID.BufferSize * 512 / 1024). + AppendLine(); + + break; + case 2: + sb.AppendFormat("{0} KiB of dual ported multi sector buffer", ATAID.BufferSize * 512 / 1024). + AppendLine(); + + break; + case 3: + sb.AppendFormat("{0} KiB of dual ported multi sector buffer with read caching", + ATAID.BufferSize * 512 / 1024).AppendLine(); + + break; + default: + sb.AppendFormat("{0} KiB of unknown type {1} buffer", ATAID.BufferSize * 512 / 1024, + ATAID.BufferType).AppendLine(); + + break; + } + + if(ATAID.EccBytes != 0x0000 && + ATAID.EccBytes != 0xFFFF) + sb.AppendFormat("READ/WRITE LONG has {0} extra bytes", ATAID.EccBytes).AppendLine(); + + sb.AppendLine(); + + sb.Append("Device capabilities:"); + + if(ATAID.Capabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit. + StandardStandbyTimer)) + sb.AppendLine().Append("Standby time values are standard"); + + if(ATAID.Capabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit.IORDY)) + { + sb.AppendLine().Append("IORDY is supported"); + + if(ATAID.Capabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit.CanDisableIORDY)) + sb.Append(" and can be disabled"); + } + + if(ATAID.Capabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit.DMASupport)) + sb.AppendLine().Append("DMA is supported"); + + if(ATAID.Capabilities2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit2.MustBeSet) && + !ATAID.Capabilities2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit2.MustBeClear)) + if(ATAID.Capabilities2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit2. + SpecificStandbyTimer)) + sb.AppendLine().Append("Device indicates a specific minimum standby timer value"); + + if(ATAID.Capabilities3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit3.MultipleValid)) + { + sb.AppendLine(). + AppendFormat("A maximum of {0} sectors can be transferred per interrupt on READ/WRITE MULTIPLE", + ATAID.MultipleSectorNumber); + + sb.AppendLine().AppendFormat("Device supports setting a maximum of {0} sectors", + ATAID.MultipleMaxSectors); + } + + if(ATAID.Capabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit. + PhysicalAlignment1) || + ATAID.Capabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit.PhysicalAlignment0)) + sb.AppendLine().AppendFormat("Long Physical Alignment setting is {0}", + (ushort)ATAID.Capabilities & 0x03); + + if(ata1) + if(ATAID.TrustedComputing.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TrustedComputingBit. + TrustedComputing)) + sb.AppendLine().Append("Device supports doubleword I/O"); + + if(atapi) + { + if(ATAID.Capabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit.InterleavedDMA)) + sb.AppendLine().Append("ATAPI device supports interleaved DMA"); + + if(ATAID.Capabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit.CommandQueue)) + sb.AppendLine().Append("ATAPI device supports command queueing"); + + if(ATAID.Capabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit. + OverlapOperation)) + sb.AppendLine().Append("ATAPI device supports overlapped operations"); + + if(ATAID.Capabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit. + RequiresATASoftReset)) + sb.AppendLine().Append("ATAPI device requires ATA software reset"); + } + + if(minatalevel <= 3) + { + sb.AppendLine().AppendFormat("PIO timing mode: {0}", ATAID.PIOTransferTimingMode); + sb.AppendLine().AppendFormat("DMA timing mode: {0}", ATAID.DMATransferTimingMode); + } + + sb.AppendLine().Append("Advanced PIO: "); + + if(ATAID.APIOSupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode0)) + sb.Append("PIO0 "); + + if(ATAID.APIOSupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode1)) + sb.Append("PIO1 "); + + if(ATAID.APIOSupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode2)) + sb.Append("PIO2 "); + + if(ATAID.APIOSupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode3)) + sb.Append("PIO3 "); + + if(ATAID.APIOSupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode4)) + sb.Append("PIO4 "); + + if(ATAID.APIOSupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode5)) + sb.Append("PIO5 "); + + if(ATAID.APIOSupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode6)) + sb.Append("PIO6 "); + + if(ATAID.APIOSupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode7)) + sb.Append("PIO7 "); + + if(minatalevel <= 3 && + !atapi) + { + sb.AppendLine().Append("Single-word DMA: "); + + if(ATAID.DMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode0)) + { + sb.Append("DMA0 "); + + if(ATAID.DMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode0)) + sb.Append("(active) "); + } + + if(ATAID.DMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode1)) + { + sb.Append("DMA1 "); + + if(ATAID.DMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode1)) + sb.Append("(active) "); + } + + if(ATAID.DMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode2)) + { + sb.Append("DMA2 "); + + if(ATAID.DMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode2)) + sb.Append("(active) "); + } + + if(ATAID.DMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode3)) + { + sb.Append("DMA3 "); + + if(ATAID.DMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode3)) + sb.Append("(active) "); + } + + if(ATAID.DMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode4)) + { + sb.Append("DMA4 "); + + if(ATAID.DMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode4)) + sb.Append("(active) "); + } + + if(ATAID.DMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode5)) + { + sb.Append("DMA5 "); + + if(ATAID.DMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode5)) + sb.Append("(active) "); + } + + if(ATAID.DMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode6)) + { + sb.Append("DMA6 "); + + if(ATAID.DMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode6)) + sb.Append("(active) "); + } + + if(ATAID.DMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode7)) + { + sb.Append("DMA7 "); + + if(ATAID.DMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode7)) + sb.Append("(active) "); + } + } + + sb.AppendLine().Append("Multi-word DMA: "); + + if(ATAID.MDMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode0)) + { + sb.Append("MDMA0 "); + + if(ATAID.MDMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode0)) + sb.Append("(active) "); + } + + if(ATAID.MDMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode1)) + { + sb.Append("MDMA1 "); + + if(ATAID.MDMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode1)) + sb.Append("(active) "); + } + + if(ATAID.MDMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode2)) + { + sb.Append("MDMA2 "); + + if(ATAID.MDMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode2)) + sb.Append("(active) "); + } + + if(ATAID.MDMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode3)) + { + sb.Append("MDMA3 "); + + if(ATAID.MDMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode3)) + sb.Append("(active) "); + } + + if(ATAID.MDMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode4)) + { + sb.Append("MDMA4 "); + + if(ATAID.MDMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode4)) + sb.Append("(active) "); + } + + if(ATAID.MDMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode5)) + { + sb.Append("MDMA5 "); + + if(ATAID.MDMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode5)) + sb.Append("(active) "); + } + + if(ATAID.MDMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode6)) + { + sb.Append("MDMA6 "); + + if(ATAID.MDMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode6)) + sb.Append("(active) "); + } + + if(ATAID.MDMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode7)) + { + sb.Append("MDMA7 "); + + if(ATAID.MDMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode7)) + sb.Append("(active) "); + } + + sb.AppendLine().Append("Ultra DMA: "); + + if(ATAID.UDMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode0)) + { + sb.Append("UDMA0 "); + + if(ATAID.UDMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode0)) + sb.Append("(active) "); + } + + if(ATAID.UDMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode1)) + { + sb.Append("UDMA1 "); + + if(ATAID.UDMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode1)) + sb.Append("(active) "); + } + + if(ATAID.UDMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode2)) + { + sb.Append("UDMA2 "); + + if(ATAID.UDMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode2)) + sb.Append("(active) "); + } + + if(ATAID.UDMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode3)) + { + sb.Append("UDMA3 "); + + if(ATAID.UDMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode3)) + sb.Append("(active) "); + } + + if(ATAID.UDMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode4)) + { + sb.Append("UDMA4 "); + + if(ATAID.UDMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode4)) + sb.Append("(active) "); + } + + if(ATAID.UDMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode5)) + { + sb.Append("UDMA5 "); + + if(ATAID.UDMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode5)) + sb.Append("(active) "); + } + + if(ATAID.UDMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode6)) + { + sb.Append("UDMA6 "); + + if(ATAID.UDMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode6)) + sb.Append("(active) "); + } + + if(ATAID.UDMASupported.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode7)) + { + sb.Append("UDMA7 "); + + if(ATAID.UDMAActive.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TransferMode.Mode7)) + sb.Append("(active) "); + } + + if(ATAID.MinMDMACycleTime != 0 && + ATAID.RecMDMACycleTime != 0) + sb.AppendLine(). + AppendFormat("At minimum {0} ns. transfer cycle time per word in MDMA, " + "{1} ns. recommended", + ATAID.MinMDMACycleTime, ATAID.RecMDMACycleTime); + + if(ATAID.MinPIOCycleTimeNoFlow != 0) + sb.AppendLine(). + AppendFormat("At minimum {0} ns. transfer cycle time per word in PIO, " + "without flow control", + ATAID.MinPIOCycleTimeNoFlow); + + if(ATAID.MinPIOCycleTimeFlow != 0) + sb.AppendLine(). + AppendFormat("At minimum {0} ns. transfer cycle time per word in PIO, " + "with IORDY flow control", + ATAID.MinPIOCycleTimeFlow); + + if(ATAID.MaxQueueDepth != 0) + sb.AppendLine().AppendFormat("{0} depth of queue maximum", ATAID.MaxQueueDepth + 1); + + if(atapi) + { + if(ATAID.PacketBusRelease != 0) + sb.AppendLine().AppendFormat("{0} ns. typical to release bus from receipt of PACKET", + ATAID.PacketBusRelease); + + if(ATAID.ServiceBusyClear != 0) + sb.AppendLine().AppendFormat("{0} ns. typical to clear BSY bit from receipt of SERVICE", + ATAID.ServiceBusyClear); + } + + if((ATAID.TransportMajorVersion & 0xF000) >> 12 == 0x1 || + (ATAID.TransportMajorVersion & 0xF000) >> 12 == 0xE) + { + if(!ATAID.SATACapabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATACapabilitiesBit.Clear)) + { + if(ATAID.SATACapabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATACapabilitiesBit. + Gen1Speed)) + sb.AppendLine().Append("SATA 1.5Gb/s is supported"); + + if(ATAID.SATACapabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATACapabilitiesBit. + Gen2Speed)) + sb.AppendLine().Append("SATA 3.0Gb/s is supported"); + + if(ATAID.SATACapabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATACapabilitiesBit. + Gen3Speed)) + sb.AppendLine().Append("SATA 6.0Gb/s is supported"); + + if(ATAID.SATACapabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATACapabilitiesBit. + PowerReceipt)) + sb.AppendLine().Append("Receipt of host initiated power management requests is supported"); + + if(ATAID.SATACapabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATACapabilitiesBit. + PHYEventCounter)) + sb.AppendLine().Append("PHY Event counters are supported"); + + if(ATAID.SATACapabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATACapabilitiesBit. + HostSlumbTrans)) + sb.AppendLine().Append("Supports host automatic partial to slumber transitions is supported"); + + if(ATAID.SATACapabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATACapabilitiesBit. + DevSlumbTrans)) + sb.AppendLine().Append("Supports device automatic partial to slumber transitions is supported"); + + if(ATAID.SATACapabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATACapabilitiesBit.NCQ)) + { + sb.AppendLine().Append("NCQ is supported"); + + if(ATAID.SATACapabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATACapabilitiesBit. + NCQPriority)) + sb.AppendLine().Append("NCQ priority is supported"); + + if(ATAID.SATACapabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATACapabilitiesBit. + UnloadNCQ)) + sb.AppendLine().Append("Unload is supported with outstanding NCQ commands"); + } + } + + if(!ATAID.SATACapabilities2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATACapabilitiesBit2. + Clear)) + { + if(!ATAID.SATACapabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATACapabilitiesBit. + Clear) && + ATAID.SATACapabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATACapabilitiesBit.NCQ)) + { + if(ATAID.SATACapabilities2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + SATACapabilitiesBit2.NCQMgmt)) + sb.AppendLine().Append("NCQ queue management is supported"); + + if(ATAID.SATACapabilities2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + SATACapabilitiesBit2.NCQStream)) + sb.AppendLine().Append("NCQ streaming is supported"); + } + + if(atapi) + { + if(ATAID.SATACapabilities2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + SATACapabilitiesBit2.HostEnvDetect)) + sb.AppendLine().Append("ATAPI device supports host environment detection"); + + if(ATAID.SATACapabilities2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + SATACapabilitiesBit2.DevAttSlimline)) + sb.AppendLine().Append("ATAPI device supports attention on slimline connected devices"); + } + + //sb.AppendFormat("Negotiated speed = {0}", ((ushort)ATAID.SATACapabilities2 & 0x000E) >> 1); + } + } + + if(ATAID.InterseekDelay != 0x0000 && + ATAID.InterseekDelay != 0xFFFF) + sb.AppendLine().AppendFormat("{0} microseconds of interseek delay for ISO-7779 acoustic testing", + ATAID.InterseekDelay); + + if((ushort)ATAID.DeviceFormFactor != 0x0000 && + (ushort)ATAID.DeviceFormFactor != 0xFFFF) + switch(ATAID.DeviceFormFactor) + { + case CommonTypes.Structs.Devices.ATA.Identify.DeviceFormFactorEnum.FiveAndQuarter: + sb.AppendLine().Append("Device nominal size is 5.25\""); + + break; + case CommonTypes.Structs.Devices.ATA.Identify.DeviceFormFactorEnum.ThreeAndHalf: + sb.AppendLine().Append("Device nominal size is 3.5\""); + + break; + case CommonTypes.Structs.Devices.ATA.Identify.DeviceFormFactorEnum.TwoAndHalf: + sb.AppendLine().Append("Device nominal size is 2.5\""); + + break; + case CommonTypes.Structs.Devices.ATA.Identify.DeviceFormFactorEnum.OnePointEight: + sb.AppendLine().Append("Device nominal size is 1.8\""); + + break; + case CommonTypes.Structs.Devices.ATA.Identify.DeviceFormFactorEnum.LessThanOnePointEight: + sb.AppendLine().Append("Device nominal size is smaller than 1.8\""); + + break; + default: + sb.AppendLine().AppendFormat("Device nominal size field value {0} is unknown", + ATAID.DeviceFormFactor); + + break; + } + + if(atapi) + if(ATAID.ATAPIByteCount > 0) + sb.AppendLine().AppendFormat("{0} bytes count limit for ATAPI", ATAID.ATAPIByteCount); + + if(cfa) + if((ATAID.CFAPowerMode & 0x8000) == 0x8000) + { + sb.AppendLine().Append("CompactFlash device supports power mode 1"); + + if((ATAID.CFAPowerMode & 0x2000) == 0x2000) + sb.AppendLine().Append("CompactFlash power mode 1 required for one or more commands"); + + if((ATAID.CFAPowerMode & 0x1000) == 0x1000) + sb.AppendLine().Append("CompactFlash power mode 1 is disabled"); + + sb.AppendLine().AppendFormat("CompactFlash device uses a maximum of {0} mA", + ATAID.CFAPowerMode & 0x0FFF); + } + + sb.AppendLine(); + + sb.AppendLine().Append("Command set and features:"); + + if(ATAID.CommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.Nop)) + { + sb.AppendLine().Append("NOP is supported"); + + if(ATAID.EnabledCommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.Nop)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.ReadBuffer)) + { + sb.AppendLine().Append("READ BUFFER is supported"); + + if(ATAID.EnabledCommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.ReadBuffer)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.WriteBuffer)) + { + sb.AppendLine().Append("WRITE BUFFER is supported"); + + if(ATAID.EnabledCommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.WriteBuffer)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.HPA)) + { + sb.AppendLine().Append("Host Protected Area is supported"); + + if(ATAID.EnabledCommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.HPA)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.DeviceReset)) + { + sb.AppendLine().Append("DEVICE RESET is supported"); + + if(ATAID.EnabledCommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.DeviceReset)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.Service)) + { + sb.AppendLine().Append("SERVICE interrupt is supported"); + + if(ATAID.EnabledCommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.Service)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.Release)) + { + sb.AppendLine().Append("Release is supported"); + + if(ATAID.EnabledCommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.Release)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.LookAhead)) + { + sb.AppendLine().Append("Look-ahead read is supported"); + + if(ATAID.EnabledCommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.LookAhead)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.WriteCache)) + { + sb.AppendLine().Append("Write cache is supported"); + + if(ATAID.EnabledCommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.WriteCache)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.Packet)) + { + sb.AppendLine().Append("PACKET is supported"); + + if(ATAID.EnabledCommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.Packet)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.PowerManagement)) + { + sb.AppendLine().Append("Power management is supported"); + + if(ATAID.EnabledCommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit. + PowerManagement)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.RemovableMedia)) + { + sb.AppendLine().Append("Removable media feature set is supported"); + + if(ATAID.EnabledCommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit. + RemovableMedia)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.SecurityMode)) + { + sb.AppendLine().Append("Security mode is supported"); + + if(ATAID.EnabledCommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.SecurityMode)) + sb.Append(" and enabled"); + } + + if(ATAID.Capabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit.LBASupport)) + sb.AppendLine().Append("28-bit LBA is supported"); + + if(ATAID.CommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.MustBeSet) && + !ATAID.CommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.MustBeClear)) + { + if(ATAID.CommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.LBA48)) + { + sb.AppendLine().Append("48-bit LBA is supported"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.LBA48)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.FlushCache)) + { + sb.AppendLine().Append("FLUSH CACHE is supported"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2. + FlushCache)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.FlushCacheExt)) + { + sb.AppendLine().Append("FLUSH CACHE EXT is supported"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2. + FlushCacheExt)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.DCO)) + { + sb.AppendLine().Append("Device Configuration Overlay feature set is supported"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.DCO)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.AAM)) + { + sb.AppendLine().Append("Automatic Acoustic Management is supported"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.AAM)) + sb.AppendFormat(" and enabled with value {0} (vendor recommends {1}", ATAID.CurrentAAM, + ATAID.RecommendedAAM); + } + + if(ATAID.CommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.SetMax)) + { + sb.AppendLine().Append("SET MAX security extension is supported"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.SetMax)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2. + AddressOffsetReservedAreaBoot)) + { + sb.AppendLine().Append("Address Offset Reserved Area Boot is supported"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2. + AddressOffsetReservedAreaBoot)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2. + SetFeaturesRequired)) + sb.AppendLine().Append("SET FEATURES is required before spin-up"); + + if(ATAID.CommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.PowerUpInStandby)) + { + sb.AppendLine().Append("Power-up in standby is supported"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2. + PowerUpInStandby)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2. + RemovableNotification)) + { + sb.AppendLine().Append("Removable Media Status Notification is supported"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2. + RemovableNotification)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.APM)) + { + sb.AppendLine().Append("Advanced Power Management is supported"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.APM)) + sb.AppendFormat(" and enabled with value {0}", ATAID.CurrentAPM); + } + + if(ATAID.CommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.CompactFlash)) + { + sb.AppendLine().Append("CompactFlash feature set is supported"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2. + CompactFlash)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.RWQueuedDMA)) + { + sb.AppendLine().Append("READ DMA QUEUED and WRITE DMA QUEUED are supported"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2. + RWQueuedDMA)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2.DownloadMicrocode)) + { + sb.AppendLine().Append("DOWNLOAD MICROCODE is supported"); + + if(ATAID.EnabledCommandSet2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit2. + DownloadMicrocode)) + sb.Append(" and enabled"); + } + } + + if(ATAID.CommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.SMART)) + { + sb.AppendLine().Append("S.M.A.R.T. is supported"); + + if(ATAID.EnabledCommandSet.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit.SMART)) + sb.Append(" and enabled"); + } + + if(ATAID.SCTCommandTransport.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SCTCommandTransportBit. + Supported)) + sb.AppendLine().Append("S.M.A.R.T. Command Transport is supported"); + + if(ATAID.CommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.MustBeSet) && + !ATAID.CommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.MustBeClear)) + { + if(ATAID.CommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.SMARTSelfTest)) + { + sb.AppendLine().Append("S.M.A.R.T. self-testing is supported"); + + if(ATAID.EnabledCommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3. + SMARTSelfTest)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.SMARTLog)) + { + sb.AppendLine().Append("S.M.A.R.T. error logging is supported"); + + if(ATAID.EnabledCommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3. + SMARTLog)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.IdleImmediate)) + { + sb.AppendLine().Append("IDLE IMMEDIATE with UNLOAD FEATURE is supported"); + + if(ATAID.EnabledCommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3. + IdleImmediate)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.WriteURG)) + sb.AppendLine().Append("URG bit is supported in WRITE STREAM DMA EXT and WRITE STREAM EXT"); + + if(ATAID.CommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.ReadURG)) + sb.AppendLine().Append("URG bit is supported in READ STREAM DMA EXT and READ STREAM EXT"); + + if(ATAID.CommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.WWN)) + sb.AppendLine().Append("Device has a World Wide Name"); + + if(ATAID.CommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.FUAWriteQ)) + { + sb.AppendLine().Append("WRITE DMA QUEUED FUA EXT is supported"); + + if(ATAID.EnabledCommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3. + FUAWriteQ)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.FUAWrite)) + { + sb.AppendLine().Append("WRITE DMA FUA EXT and WRITE MULTIPLE FUA EXT are supported"); + + if(ATAID.EnabledCommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3. + FUAWrite)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.GPL)) + { + sb.AppendLine().Append("General Purpose Logging is supported"); + + if(ATAID.EnabledCommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.GPL)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.Streaming)) + { + sb.AppendLine().Append("Streaming feature set is supported"); + + if(ATAID.EnabledCommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3. + Streaming)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.MCPT)) + { + sb.AppendLine().Append("Media Card Pass Through command set is supported"); + + if(ATAID.EnabledCommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.MCPT)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.MediaSerial)) + { + sb.AppendLine().Append("Media Serial is supported"); + + if(ATAID.EnabledCommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3. + MediaSerial)) + sb.Append(" and valid"); + } + } + + if(ATAID.CommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4.MustBeSet) && + !ATAID.CommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4.MustBeClear)) + { + if(ATAID.CommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4.DSN)) + { + sb.AppendLine().Append("DSN feature set is supported"); + + if(ATAID.EnabledCommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4.DSN)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4.AMAC)) + { + sb.AppendLine().Append("Accessible Max Address Configuration is supported"); + + if(ATAID.EnabledCommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4.AMAC)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4.ExtPowerCond)) + { + sb.AppendLine().Append("Extended Power Conditions are supported"); + + if(ATAID.EnabledCommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4. + ExtPowerCond)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4.ExtStatusReport)) + { + sb.AppendLine().Append("Extended Status Reporting is supported"); + + if(ATAID.EnabledCommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4. + ExtStatusReport)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4.FreeFallControl)) + { + sb.AppendLine().Append("Free-fall control feature set is supported"); + + if(ATAID.EnabledCommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4. + FreeFallControl)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4. + SegmentedDownloadMicrocode)) + { + sb.AppendLine().Append("Segmented feature in DOWNLOAD MICROCODE is supported"); + + if(ATAID.EnabledCommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4. + SegmentedDownloadMicrocode)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4.RWDMAExtGpl)) + { + sb.AppendLine().Append("READ/WRITE DMA EXT GPL are supported"); + + if(ATAID.EnabledCommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4. + RWDMAExtGpl)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4.WriteUnc)) + { + sb.AppendLine().Append("WRITE UNCORRECTABLE is supported"); + + if(ATAID.EnabledCommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4. + WriteUnc)) + sb.Append(" and enabled"); + } + + if(ATAID.CommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4.WRV)) + { + sb.AppendLine().Append("Write/Read/Verify is supported"); + + if(ATAID.EnabledCommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4.WRV)) + sb.Append(" and enabled"); + + sb.AppendLine().AppendFormat("{0} sectors for Write/Read/Verify mode 2", ATAID.WRVSectorCountMode2); + sb.AppendLine().AppendFormat("{0} sectors for Write/Read/Verify mode 3", ATAID.WRVSectorCountMode3); + + if(ATAID.EnabledCommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4.WRV)) + sb.AppendLine().AppendFormat("Current Write/Read/Verify mode: {0}", ATAID.WRVMode); + } + + if(ATAID.CommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4.DT1825)) + { + sb.AppendLine().Append("DT1825 is supported"); + + if(ATAID.EnabledCommandSet4.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit4.DT1825)) + sb.Append(" and enabled"); + } + } + + if(ATAID.Capabilities3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit3.BlockErase)) + sb.AppendLine().Append("BLOCK ERASE EXT is supported"); + + if(ATAID.Capabilities3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit3.Overwrite)) + sb.AppendLine().Append("OVERWRITE EXT is supported"); + + if(ATAID.Capabilities3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit3.CryptoScramble)) + sb.AppendLine().Append("CRYPTO SCRAMBLE EXT is supported"); + + if(ATAID.CommandSet5.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit5.DeviceConfDMA)) + sb.AppendLine(). + Append("DEVICE CONFIGURATION IDENTIFY DMA and DEVICE CONFIGURATION SET DMA are supported"); + + if(ATAID.CommandSet5.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit5.ReadBufferDMA)) + sb.AppendLine().Append("READ BUFFER DMA is supported"); + + if(ATAID.CommandSet5.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit5.WriteBufferDMA)) + sb.AppendLine().Append("WRITE BUFFER DMA is supported"); + + if(ATAID.CommandSet5.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit5.DownloadMicroCodeDMA)) + sb.AppendLine().Append("DOWNLOAD MICROCODE DMA is supported"); + + if(ATAID.CommandSet5.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit5.SetMaxDMA)) + sb.AppendLine().Append("SET PASSWORD DMA and SET UNLOCK DMA are supported"); + + if(ATAID.CommandSet5.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit5.Ata28)) + sb.AppendLine().Append("Not all 28-bit commands are supported"); + + if(ATAID.CommandSet5.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit5.CFast)) + sb.AppendLine().Append("Device follows CFast specification"); + + if(ATAID.CommandSet5.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit5.IEEE1667)) + sb.AppendLine().Append("Device follows IEEE-1667"); + + if(ATAID.CommandSet5.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit5.DeterministicTrim)) + { + sb.AppendLine().Append("Read after TRIM is deterministic"); + + if(ATAID.CommandSet5.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit5.ReadZeroTrim)) + sb.AppendLine().Append("Read after TRIM returns empty data"); + } + + if(ATAID.CommandSet5.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit5. + LongPhysSectorAligError)) + sb.AppendLine().Append("Device supports Long Physical Sector Alignment Error Reporting Control"); + + if(ATAID.CommandSet5.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit5.Encrypted)) + sb.AppendLine().Append("Device encrypts all user data"); + + if(ATAID.CommandSet5.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit5.AllCacheNV)) + sb.AppendLine().Append("Device's write cache is non-volatile"); + + if(ATAID.CommandSet5.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit5.ZonedBit0) || + ATAID.CommandSet5.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit5.ZonedBit1)) + sb.AppendLine().Append("Device is zoned"); + + if(ATAID.Capabilities3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit3.Sanitize)) + { + sb.AppendLine().Append("Sanitize feature set is supported"); + + sb.AppendLine(). + Append(ATAID.Capabilities3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit3. + SanitizeCommands) + ? "Sanitize commands are specified by ACS-3 or higher" + : "Sanitize commands are specified by ACS-2"); + + if(ATAID.Capabilities3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CapabilitiesBit3. + SanitizeAntifreeze)) + sb.AppendLine().Append("SANITIZE ANTIFREEZE LOCK EXT is supported"); + } + + if(!ata1 && + maxatalevel >= 8) + if(ATAID.TrustedComputing.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TrustedComputingBit.Set) && + !ATAID.TrustedComputing.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TrustedComputingBit. + Clear) && + ATAID.TrustedComputing.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.TrustedComputingBit. + TrustedComputing)) + sb.AppendLine().Append("Trusted Computing feature set is supported"); + + if((ATAID.TransportMajorVersion & 0xF000) >> 12 == 0x1 || + (ATAID.TransportMajorVersion & 0xF000) >> 12 == 0xE) + { + if(!ATAID.SATACapabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATACapabilitiesBit.Clear)) + if(ATAID.SATACapabilities.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATACapabilitiesBit. + ReadLogDMAExt)) + sb.AppendLine().Append("READ LOG DMA EXT is supported"); + + if(!ATAID.SATACapabilities2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATACapabilitiesBit2. + Clear)) + if(ATAID.SATACapabilities2.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATACapabilitiesBit2. + FPDMAQ)) + sb.AppendLine().Append("RECEIVE FPDMA QUEUED and SEND FPDMA QUEUED are supported"); + + if(!ATAID.SATAFeatures.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATAFeaturesBit.Clear)) + { + if(ATAID.SATAFeatures.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATAFeaturesBit. + NonZeroBufferOffset)) + { + sb.AppendLine().Append("Non-zero buffer offsets are supported"); + + if(ATAID.EnabledSATAFeatures.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATAFeaturesBit. + NonZeroBufferOffset)) + sb.Append(" and enabled"); + } + + if(ATAID.SATAFeatures.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATAFeaturesBit.DMASetup)) + { + sb.AppendLine().Append("DMA Setup auto-activation is supported"); + + if(ATAID.EnabledSATAFeatures.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATAFeaturesBit. + DMASetup)) + sb.Append(" and enabled"); + } + + if(ATAID.SATAFeatures.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATAFeaturesBit. + InitPowerMgmt)) + { + sb.AppendLine().Append("Device-initiated power management is supported"); + + if(ATAID.EnabledSATAFeatures.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATAFeaturesBit. + InitPowerMgmt)) + sb.Append(" and enabled"); + } + + if(ATAID.SATAFeatures.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATAFeaturesBit.InOrderData)) + { + sb.AppendLine().Append("In-order data delivery is supported"); + + if(ATAID.EnabledSATAFeatures.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATAFeaturesBit. + InOrderData)) + sb.Append(" and enabled"); + } + + if(!atapi) + if(ATAID.SATAFeatures.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATAFeaturesBit. + HardwareFeatureControl)) + { + sb.AppendLine().Append("Hardware Feature Control is supported"); + + if(ATAID.EnabledSATAFeatures.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + SATAFeaturesBit.HardwareFeatureControl)) + sb.Append(" and enabled"); + } + + if(atapi) + if(ATAID.SATAFeatures.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATAFeaturesBit. + AsyncNotification)) + { + sb.AppendLine().Append("Asynchronous notification is supported"); + + if(ATAID.EnabledSATAFeatures.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + SATAFeaturesBit.AsyncNotification)) + sb.Append(" and enabled"); + } + + if(ATAID.SATAFeatures.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATAFeaturesBit. + SettingsPreserve)) + { + sb.AppendLine().Append("Software Settings Preservation is supported"); + + if(ATAID.EnabledSATAFeatures.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATAFeaturesBit. + SettingsPreserve)) + sb.Append(" and enabled"); + } + + if(ATAID.SATAFeatures.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATAFeaturesBit. + NCQAutoSense)) + sb.AppendLine().Append("NCQ Autosense is supported"); + + if(ATAID.EnabledSATAFeatures.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SATAFeaturesBit. + EnabledSlumber)) + sb.AppendLine().Append("Automatic Partial to Slumber transitions are enabled"); + } + } + + if((ATAID.RemovableStatusSet & 0x03) > 0) + sb.AppendLine().Append("Removable Media Status Notification feature set is supported"); + + if(ATAID.FreeFallSensitivity != 0x00 && + ATAID.FreeFallSensitivity != 0xFF) + sb.AppendLine().AppendFormat("Free-fall sensitivity set to {0}", ATAID.FreeFallSensitivity); + + if(ATAID.DataSetMgmt.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.DataSetMgmtBit.Trim)) + sb.AppendLine().Append("TRIM is supported"); + + if(ATAID.DataSetMgmtSize > 0) + sb.AppendLine().AppendFormat("DATA SET MANAGEMENT can receive a maximum of {0} blocks of 512 bytes", + ATAID.DataSetMgmtSize); + + sb.AppendLine().AppendLine(); + + if(ATAID.SecurityStatus.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SecurityStatusBit.Supported)) + { + sb.AppendLine("Security:"); + + if(ATAID.SecurityStatus.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SecurityStatusBit.Enabled)) + { + sb.AppendLine("Security is enabled"); + + sb.AppendLine(ATAID.SecurityStatus.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + SecurityStatusBit.Locked) + ? "Security is locked" : "Security is not locked"); + + sb.AppendLine(ATAID.SecurityStatus.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + SecurityStatusBit.Frozen) + ? "Security is frozen" : "Security is not frozen"); + + sb.AppendLine(ATAID.SecurityStatus.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + SecurityStatusBit.Expired) + ? "Security count has expired" : "Security count has not expired"); + + sb.AppendLine(ATAID.SecurityStatus.HasFlag(CommonTypes.Structs.Devices.ATA.Identify. + SecurityStatusBit.Maximum) + ? "Security level is maximum" : "Security level is high"); + } + else + sb.AppendLine("Security is not enabled"); + + if(ATAID.SecurityStatus.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SecurityStatusBit.Enhanced)) + sb.AppendLine("Supports enhanced security erase"); + + sb.AppendFormat("{0} minutes to complete secure erase", ATAID.SecurityEraseTime * 2).AppendLine(); + + if(ATAID.SecurityStatus.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SecurityStatusBit.Enhanced)) + sb.AppendFormat("{0} minutes to complete enhanced secure erase", + ATAID.EnhancedSecurityEraseTime * 2).AppendLine(); + + sb.AppendFormat("Master password revision code: {0}", ATAID.MasterPasswordRevisionCode).AppendLine(); + } + + if(ATAID.CommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.MustBeSet) && + !ATAID.CommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.MustBeClear) && + ATAID.CommandSet3.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.CommandSetBit3.Streaming)) + { + sb.AppendLine().AppendLine("Streaming:"); + sb.AppendFormat("Minimum request size is {0}", ATAID.StreamMinReqSize); + sb.AppendFormat("Streaming transfer time in PIO is {0}", ATAID.StreamTransferTimePIO); + sb.AppendFormat("Streaming transfer time in DMA is {0}", ATAID.StreamTransferTimeDMA); + sb.AppendFormat("Streaming access latency is {0}", ATAID.StreamAccessLatency); + sb.AppendFormat("Streaming performance granularity is {0}", ATAID.StreamPerformanceGranularity); + } + + if(ATAID.SCTCommandTransport.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SCTCommandTransportBit. + Supported)) + { + sb.AppendLine().AppendLine("S.M.A.R.T. Command Transport (SCT):"); + + if(ATAID.SCTCommandTransport.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SCTCommandTransportBit. + LongSectorAccess)) + sb.AppendLine("SCT Long Sector Address is supported"); + + if(ATAID.SCTCommandTransport.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SCTCommandTransportBit. + WriteSame)) + sb.AppendLine("SCT Write Same is supported"); + + if(ATAID.SCTCommandTransport.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SCTCommandTransportBit. + ErrorRecoveryControl)) + sb.AppendLine("SCT Error Recovery Control is supported"); + + if(ATAID.SCTCommandTransport.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SCTCommandTransportBit. + FeaturesControl)) + sb.AppendLine("SCT Features Control is supported"); + + if(ATAID.SCTCommandTransport.HasFlag(CommonTypes.Structs.Devices.ATA.Identify.SCTCommandTransportBit. + DataTables)) + sb.AppendLine("SCT Data Tables are supported"); + } + + if((ATAID.NVCacheCaps & 0x0010) == 0x0010) + { + sb.AppendLine().AppendLine("Non-Volatile Cache:"); + sb.AppendLine().AppendFormat("Version {0}", (ATAID.NVCacheCaps & 0xF000) >> 12).AppendLine(); + + if((ATAID.NVCacheCaps & 0x0001) == 0x0001) + { + sb.Append("Power mode feature set is supported"); + + if((ATAID.NVCacheCaps & 0x0002) == 0x0002) + sb.Append(" and enabled"); + + sb.AppendLine(); + + sb.AppendLine().AppendFormat("Version {0}", (ATAID.NVCacheCaps & 0x0F00) >> 8).AppendLine(); + } + + sb.AppendLine().AppendFormat("Non-Volatile Cache is {0} bytes", ATAID.NVCacheSize * logicalSectorSize). + AppendLine(); + } + + #if DEBUG + sb.AppendLine(); + + if(ATAID.VendorWord9 != 0x0000 && + ATAID.VendorWord9 != 0xFFFF) + sb.AppendFormat("Word 9: 0x{0:X4}", ATAID.VendorWord9).AppendLine(); + + if((ATAID.VendorWord47 & 0x7F) != 0x7F && + (ATAID.VendorWord47 & 0x7F) != 0x00) + sb.AppendFormat("Word 47 bits 15 to 8: 0x{0:X2}", ATAID.VendorWord47).AppendLine(); + + if(ATAID.VendorWord51 != 0x00 && + ATAID.VendorWord51 != 0xFF) + sb.AppendFormat("Word 51 bits 7 to 0: 0x{0:X2}", ATAID.VendorWord51).AppendLine(); + + if(ATAID.VendorWord52 != 0x00 && + ATAID.VendorWord52 != 0xFF) + sb.AppendFormat("Word 52 bits 7 to 0: 0x{0:X2}", ATAID.VendorWord52).AppendLine(); + + if(ATAID.ReservedWord64 != 0x00 && + ATAID.ReservedWord64 != 0xFF) + sb.AppendFormat("Word 64 bits 15 to 8: 0x{0:X2}", ATAID.ReservedWord64).AppendLine(); + + if(ATAID.ReservedWord70 != 0x0000 && + ATAID.ReservedWord70 != 0xFFFF) + sb.AppendFormat("Word 70: 0x{0:X4}", ATAID.ReservedWord70).AppendLine(); + + if(ATAID.ReservedWord73 != 0x0000 && + ATAID.ReservedWord73 != 0xFFFF) + sb.AppendFormat("Word 73: 0x{0:X4}", ATAID.ReservedWord73).AppendLine(); + + if(ATAID.ReservedWord74 != 0x0000 && + ATAID.ReservedWord74 != 0xFFFF) + sb.AppendFormat("Word 74: 0x{0:X4}", ATAID.ReservedWord74).AppendLine(); + + if(ATAID.ReservedWord116 != 0x0000 && + ATAID.ReservedWord116 != 0xFFFF) + sb.AppendFormat("Word 116: 0x{0:X4}", ATAID.ReservedWord116).AppendLine(); + + for(int i = 0; i < ATAID.ReservedWords121.Length; i++) + if(ATAID.ReservedWords121[i] != 0x0000 && + ATAID.ReservedWords121[i] != 0xFFFF) + sb.AppendFormat("Word {1}: 0x{0:X4}", ATAID.ReservedWords121[i], 121 + i).AppendLine(); + + for(int i = 0; i < ATAID.ReservedWords129.Length; i++) + if(ATAID.ReservedWords129[i] != 0x0000 && + ATAID.ReservedWords129[i] != 0xFFFF) + sb.AppendFormat("Word {1}: 0x{0:X4}", ATAID.ReservedWords129[i], 129 + i).AppendLine(); + + for(int i = 0; i < ATAID.ReservedCFA.Length; i++) + if(ATAID.ReservedCFA[i] != 0x0000 && + ATAID.ReservedCFA[i] != 0xFFFF) + sb.AppendFormat("Word {1} (CFA): 0x{0:X4}", ATAID.ReservedCFA[i], 161 + i).AppendLine(); + + if(ATAID.ReservedWord174 != 0x0000 && + ATAID.ReservedWord174 != 0xFFFF) + sb.AppendFormat("Word 174: 0x{0:X4}", ATAID.ReservedWord174).AppendLine(); + + if(ATAID.ReservedWord175 != 0x0000 && + ATAID.ReservedWord175 != 0xFFFF) + sb.AppendFormat("Word 175: 0x{0:X4}", ATAID.ReservedWord175).AppendLine(); + + if(ATAID.ReservedCEATAWord207 != 0x0000 && + ATAID.ReservedCEATAWord207 != 0xFFFF) + sb.AppendFormat("Word 207 (CE-ATA): 0x{0:X4}", ATAID.ReservedCEATAWord207).AppendLine(); + + if(ATAID.ReservedCEATAWord208 != 0x0000 && + ATAID.ReservedCEATAWord208 != 0xFFFF) + sb.AppendFormat("Word 208 (CE-ATA): 0x{0:X4}", ATAID.ReservedCEATAWord208).AppendLine(); + + if(ATAID.NVReserved != 0x00 && + ATAID.NVReserved != 0xFF) + sb.AppendFormat("Word 219 bits 15 to 8: 0x{0:X2}", ATAID.NVReserved).AppendLine(); + + if(ATAID.WRVReserved != 0x00 && + ATAID.WRVReserved != 0xFF) + sb.AppendFormat("Word 220 bits 15 to 8: 0x{0:X2}", ATAID.WRVReserved).AppendLine(); + + if(ATAID.ReservedWord221 != 0x0000 && + ATAID.ReservedWord221 != 0xFFFF) + sb.AppendFormat("Word 221: 0x{0:X4}", ATAID.ReservedWord221).AppendLine(); + + for(int i = 0; i < ATAID.ReservedCEATA224.Length; i++) + if(ATAID.ReservedCEATA224[i] != 0x0000 && + ATAID.ReservedCEATA224[i] != 0xFFFF) + sb.AppendFormat("Word {1} (CE-ATA): 0x{0:X4}", ATAID.ReservedCEATA224[i], 224 + i).AppendLine(); + + for(int i = 0; i < ATAID.ReservedWords.Length; i++) + if(ATAID.ReservedWords[i] != 0x0000 && + ATAID.ReservedWords[i] != 0xFFFF) + sb.AppendFormat("Word {1}: 0x{0:X4}", ATAID.ReservedWords[i], 236 + i).AppendLine(); + #endif + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/ATA/Registers.cs b/Aaru.Decoders/ATA/Registers.cs new file mode 100644 index 000000000..5e3bab5ca --- /dev/null +++ b/Aaru.Decoders/ATA/Registers.cs @@ -0,0 +1,114 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Errors.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes ATA error registers. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Runtime.InteropServices; + +namespace Aaru.Decoders.ATA +{ + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct AtaRegistersChs + { + public byte Feature; + public byte SectorCount; + public byte Sector; + public byte CylinderLow; + public byte CylinderHigh; + public byte DeviceHead; + public byte Command; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct AtaRegistersLba28 + { + public byte Feature; + public byte SectorCount; + public byte LbaLow; + public byte LbaMid; + public byte LbaHigh; + public byte DeviceHead; + public byte Command; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct AtaRegistersLba48 + { + public ushort Feature; + public ushort SectorCount; + public byte LbaLowPrevious; + public byte LbaLowCurrent; + public byte LbaMidPrevious; + public byte LbaMidCurrent; + public byte LbaHighPrevious; + public byte LbaHighCurrent; + public byte DeviceHead; + public byte Command; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct AtaErrorRegistersChs + { + public byte Status; + public byte Error; + public byte SectorCount; + public byte Sector; + public byte CylinderLow; + public byte CylinderHigh; + public byte DeviceHead; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct AtaErrorRegistersLba28 + { + public byte Status; + public byte Error; + public byte SectorCount; + public byte LbaLow; + public byte LbaMid; + public byte LbaHigh; + public byte DeviceHead; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct AtaErrorRegistersLba48 + { + public byte Status; + public byte Error; + public ushort SectorCount; + public byte LbaLowPrevious; + public byte LbaLowCurrent; + public byte LbaMidPrevious; + public byte LbaMidCurrent; + public byte LbaHighPrevious; + public byte LbaHighCurrent; + public byte DeviceHead; + } +} \ No newline at end of file diff --git a/Aaru.Decoders/Aaru.Decoders.csproj b/Aaru.Decoders/Aaru.Decoders.csproj new file mode 100644 index 000000000..4fea38565 --- /dev/null +++ b/Aaru.Decoders/Aaru.Decoders.csproj @@ -0,0 +1,197 @@ + + + + 2.0 + {0BEB3088-B634-4289-AE17-CDF2D25D00D5} + Library + Aaru.Decoders + Aaru.Decoders + $(Version) + false + true + 5.3.2 + Claunia.com + Copyright © 2011-2023 Natalia Portillo + Aaru Data Preservation Suite + Aaru.Decoders + $(Version) + netcoreapp3.1 + 8 + Binary structure decoders used by the Aaru Data Preservation Suite. + https://github.com/aaru-dps/ + LGPL-2.1-only + https://github.com/aaru-dps/Aaru + true + en-US + true + true + snupkg + Natalia Portillo <claunia@claunia.com> + + + $(Version)+{chash:8} + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {F8BDF57B-1571-4CD0-84B3-B422088D359A} + Aaru.Helpers + + + {CCAA7AFE-C094-4D82-A66D-630DE8A3F545} + Aaru.Console + + + + + + + + + + + + + + + + + + + + LICENSE.LGPL + + + + + + + + \ No newline at end of file diff --git a/Aaru.Decoders/Aaru.Decoders.csproj.DotSettings b/Aaru.Decoders/Aaru.Decoders.csproj.DotSettings new file mode 100644 index 000000000..8b3c7dbf6 --- /dev/null +++ b/Aaru.Decoders/Aaru.Decoders.csproj.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/Aaru.Decoders/Bluray/BCA.cs b/Aaru.Decoders/Bluray/BCA.cs new file mode 100644 index 000000000..a1563c14a --- /dev/null +++ b/Aaru.Decoders/Bluray/BCA.cs @@ -0,0 +1,124 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : BCA.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes Blu-ray Burst Cutting Area. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Console; +using Aaru.Helpers; + +namespace Aaru.Decoders.Bluray +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class BCA + { + #region Public structures + public struct BurstCuttingArea + { + /// Bytes 0 to 1 Always 66 + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4 to 67 BCA data + public byte[] BCA; + } + #endregion Public structures + #region Public methods + public static BurstCuttingArea? Decode(byte[] BCAResponse) + { + if(BCAResponse == null) + return null; + + if(BCAResponse.Length != 68) + { + AaruConsole.DebugWriteLine("BD BCA decoder", "Found incorrect Blu-ray BCA size ({0} bytes)", + BCAResponse.Length); + + return null; + } + + var decoded = new BurstCuttingArea + { + DataLength = BigEndianBitConverter.ToUInt16(BCAResponse, 0), + Reserved1 = BCAResponse[2], + Reserved2 = BCAResponse[3], + BCA = new byte[64] + }; + + Array.Copy(BCAResponse, 4, decoded.BCA, 0, 64); + + return decoded; + } + + public static string Prettify(BurstCuttingArea? BCAResponse) + { + if(BCAResponse == null) + return null; + + BurstCuttingArea response = BCAResponse.Value; + + var sb = new StringBuilder(); + + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + #endif + + sb.AppendFormat("Blu-ray Burst Cutting Area in hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.BCA, 80)); + + return sb.ToString(); + } + + public static string Prettify(byte[] BCAResponse) => Prettify(Decode(BCAResponse)); + #endregion Public methods + } +} \ No newline at end of file diff --git a/Aaru.Decoders/Bluray/Cartridge.cs b/Aaru.Decoders/Bluray/Cartridge.cs new file mode 100644 index 000000000..6f1fff830 --- /dev/null +++ b/Aaru.Decoders/Bluray/Cartridge.cs @@ -0,0 +1,180 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Cartridge.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes Blu-ray cartridge structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Console; +using Aaru.Helpers; + +namespace Aaru.Decoders.Bluray +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global"), + SuppressMessage("ReSharper", "UnassignedField.Global")] + public static class Cartridge + { + #region Public structures + public struct CartridgeStatus + { + /// Bytes 0 to 1 Always 6 + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4, bit 7 Medium is inserted in a cartridge + public bool Cartridge; + /// Byte 4, bit 6 Medium taken out / put in a cartridge + public bool OUT; + /// Byte 4, bits 5 to 3 Reserved + public byte Reserved3; + /// Byte 4, bit 2 Cartridge sets write protection + public bool CWP; + /// Byte 4, bits 1 to 0 Reserved + public byte Reserved4; + /// Byte 5 Reserved + public byte Reserved5; + /// Byte 6 Reserved + public byte Reserved6; + /// Byte 7 Reserved + public byte Reserved7; + } + #endregion Public structures + #region Public methods + public static CartridgeStatus? Decode(byte[] CSResponse) + { + if(CSResponse == null) + return null; + + if(CSResponse.Length != 8) + { + AaruConsole.DebugWriteLine("BD Cartridge Status decoder", + "Found incorrect Blu-ray Cartridge Status size ({0} bytes)", + CSResponse.Length); + + return null; + } + + var decoded = new CartridgeStatus + { + DataLength = BigEndianBitConverter.ToUInt16(CSResponse, 0), + Reserved1 = CSResponse[2], + Reserved2 = CSResponse[3], + Cartridge = Convert.ToBoolean(CSResponse[4] & 0x80), + OUT = Convert.ToBoolean(CSResponse[4] & 0x40), + Reserved3 = (byte)((CSResponse[4] & 0x38) >> 3), + CWP = Convert.ToBoolean(CSResponse[4] & 0x04), + Reserved4 = (byte)(CSResponse[4] & 0x03), + Reserved5 = CSResponse[5], + Reserved6 = CSResponse[6], + Reserved7 = CSResponse[7] + }; + + return decoded; + } + + public static string Prettify(CartridgeStatus? CSResponse) + { + if(CSResponse == null) + return null; + + CartridgeStatus response = CSResponse.Value; + + var sb = new StringBuilder(); + + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + + if(response.Reserved3 != 0) + sb.AppendFormat("Reserved3 = 0x{0:X8}", response.Reserved3).AppendLine(); + + if(response.Reserved4 != 0) + sb.AppendFormat("Reserved4 = 0x{0:X8}", response.Reserved4).AppendLine(); + + if(response.Reserved5 != 0) + sb.AppendFormat("Reserved5 = 0x{0:X8}", response.Reserved5).AppendLine(); + + if(response.Reserved6 != 0) + sb.AppendFormat("Reserved6 = 0x{0:X8}", response.Reserved6).AppendLine(); + + if(response.Reserved7 != 0) + sb.AppendFormat("Reserved7 = 0x{0:X8}", response.Reserved7).AppendLine(); + #endif + + if(response.Cartridge) + { + sb.AppendLine("Media is inserted in a cartridge"); + + if(response.OUT) + sb.AppendLine("Media has been taken out, or inserted in, the cartridge"); + + if(response.CWP) + sb.AppendLine("Media is write protected"); + } + else + { + sb.AppendLine("Media is not in a cartridge"); + + #if DEBUG + if(response.OUT) + sb.AppendLine("Media has out bit marked, shouldn't"); + + if(response.CWP) + sb.AppendLine("Media has write protection bit marked, shouldn't"); + #endif + } + + return sb.ToString(); + } + + public static string Prettify(byte[] CSResponse) => Prettify(Decode(CSResponse)); + #endregion Public methods + } +} \ No newline at end of file diff --git a/Aaru.Decoders/Bluray/DDS.cs b/Aaru.Decoders/Bluray/DDS.cs new file mode 100644 index 000000000..8e610137d --- /dev/null +++ b/Aaru.Decoders/Bluray/DDS.cs @@ -0,0 +1,229 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : DDS.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes Blu-ray Disc Definition Structure. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Console; +using Aaru.Helpers; + +namespace Aaru.Decoders.Bluray +{ + /// Information from the following standards: + /// ANSI X3.304-1997 + /// T10/1048-D revision 9.0 + /// T10/1048-D revision 10a + /// T10/1228-D revision 7.0c + /// T10/1228-D revision 11a + /// T10/1363-D revision 10g + /// T10/1545-D revision 1d + /// T10/1545-D revision 5 + /// T10/1545-D revision 5a + /// T10/1675-D revision 2c + /// T10/1675-D revision 4 + /// T10/1836-D revision 2g + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class DDS + { + #region Private constants + /// Disc Definition Structure Identifier "DS" + const ushort DDSIdentifier = 0x4453; + #endregion Private constants + + #region Public structures + public struct DiscDefinitionStructure + { + /// Bytes 0 to 1 Data Length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to 5 "DS" + public ushort Signature; + /// Byte 6 DDS format + public byte Format; + /// Byte 7 Reserved + public byte Reserved3; + /// Bytes 8 to 11 DDS update count + public uint UpdateCount; + /// Bytes 12 to 19 Reserved + public ulong Reserved4; + /// Bytes 20 to 23 First PSN of Drive Area + public uint DriveAreaPSN; + /// Bytes 24 to 27 Reserved + public uint Reserved5; + /// Bytes 28 to 31 First PSN of Defect List + public uint DefectListPSN; + /// Bytes 32 to 35 Reserved + public uint Reserved6; + /// Bytes 36 to 39 PSN of LSN 0 of user data area + public uint PSNofLSNZero; + /// Bytes 40 to 43 Last LSN of user data area + public uint LastUserAreaLSN; + /// Bytes 44 to 47 ISA0 size + public uint ISA0; + /// Bytes 48 to 51 OSA size + public uint OSA; + /// Bytes 52 to 55 ISA1 size + public uint ISA1; + /// Byte 56 Spare Area full flags + public byte SpareAreaFullFlags; + /// Byte 57 Reserved + public byte Reserved7; + /// Byte 58 Disc type specific field + public byte DiscTypeSpecificField1; + /// Byte 59 Reserved + public byte Reserved8; + /// Byte 60 to 63 Disc type specific field + public uint DiscTypeSpecificField2; + /// Byte 64 to 67 Reserved + public uint Reserved9; + /// Bytes 68 to 99 Status bits of INFO1/2 and PAC1/2 on L0 and L1 + public byte[] StatusBits; + /// Bytes 100 to end Disc type specific data + public byte[] DiscTypeSpecificData; + } + #endregion Public structures + + #region Public methods + public static DiscDefinitionStructure? Decode(byte[] DDSResponse) + { + if(DDSResponse == null) + return null; + + var decoded = new DiscDefinitionStructure + { + DataLength = BigEndianBitConverter.ToUInt16(DDSResponse, 0), + Reserved1 = DDSResponse[2], + Reserved2 = DDSResponse[3], + Signature = BigEndianBitConverter.ToUInt16(DDSResponse, 4) + }; + + if(decoded.Signature != DDSIdentifier) + { + AaruConsole.DebugWriteLine("BD DDS decoder", "Found incorrect DDS signature (0x{0:X4})", + decoded.Signature); + + return null; + } + + decoded.Format = DDSResponse[6]; + decoded.Reserved3 = DDSResponse[7]; + decoded.UpdateCount = BigEndianBitConverter.ToUInt32(DDSResponse, 8); + decoded.Reserved4 = BigEndianBitConverter.ToUInt64(DDSResponse, 12); + decoded.DriveAreaPSN = BigEndianBitConverter.ToUInt32(DDSResponse, 20); + decoded.Reserved5 = BigEndianBitConverter.ToUInt32(DDSResponse, 24); + decoded.DefectListPSN = BigEndianBitConverter.ToUInt32(DDSResponse, 28); + decoded.Reserved6 = BigEndianBitConverter.ToUInt32(DDSResponse, 32); + decoded.PSNofLSNZero = BigEndianBitConverter.ToUInt32(DDSResponse, 36); + decoded.LastUserAreaLSN = BigEndianBitConverter.ToUInt32(DDSResponse, 40); + decoded.ISA0 = BigEndianBitConverter.ToUInt32(DDSResponse, 44); + decoded.OSA = BigEndianBitConverter.ToUInt32(DDSResponse, 48); + decoded.ISA1 = BigEndianBitConverter.ToUInt32(DDSResponse, 52); + decoded.SpareAreaFullFlags = DDSResponse[56]; + decoded.Reserved7 = DDSResponse[57]; + decoded.DiscTypeSpecificField1 = DDSResponse[58]; + decoded.Reserved8 = DDSResponse[59]; + decoded.DiscTypeSpecificField2 = BigEndianBitConverter.ToUInt32(DDSResponse, 60); + decoded.Reserved9 = BigEndianBitConverter.ToUInt32(DDSResponse, 64); + decoded.StatusBits = new byte[32]; + Array.Copy(DDSResponse, 68, decoded.StatusBits, 0, 32); + decoded.DiscTypeSpecificData = new byte[DDSResponse.Length - 100]; + Array.Copy(DDSResponse, 100, decoded.DiscTypeSpecificData, 0, DDSResponse.Length - 100); + + return decoded; + } + + public static string Prettify(DiscDefinitionStructure? DDSResponse) + { + if(DDSResponse == null) + return null; + + DiscDefinitionStructure response = DDSResponse.Value; + + var sb = new StringBuilder(); + + sb.AppendFormat("DDS Format: 0x{0:X2}", response.Format).AppendLine(); + sb.AppendFormat("DDS has ben updated {0} times", response.UpdateCount).AppendLine(); + sb.AppendFormat("First PSN of Drive Area: 0x{0:X8}", response.DriveAreaPSN).AppendLine(); + sb.AppendFormat("First PSN of Defect List: 0x{0:X8}", response.DefectListPSN).AppendLine(); + sb.AppendFormat("PSN of User Data Area's LSN 0: 0x{0:X8}", response.PSNofLSNZero).AppendLine(); + sb.AppendFormat("Last User Data Area's LSN 0: 0x{0:X8}", response.LastUserAreaLSN).AppendLine(); + sb.AppendFormat("ISA0 size: {0}", response.ISA0).AppendLine(); + sb.AppendFormat("OSA size: {0}", response.OSA).AppendLine(); + sb.AppendFormat("ISA1 size: {0}", response.ISA1).AppendLine(); + sb.AppendFormat("Spare Area Full Flags: 0x{0:X2}", response.SpareAreaFullFlags).AppendLine(); + sb.AppendFormat("Disc Type Specific Field 1: 0x{0:X2}", response.DiscTypeSpecificField1).AppendLine(); + sb.AppendFormat("Disc Type Specific Field 2: 0x{0:X8}", response.DiscTypeSpecificField2).AppendLine(); + sb.AppendFormat("Blu-ray DDS Status Bits in hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.StatusBits, 80)); + sb.AppendFormat("Blu-ray DDS Disc Type Specific Data in hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.DiscTypeSpecificData, 80)); + + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + + if(response.Reserved3 != 0) + sb.AppendFormat("Reserved3 = 0x{0:X2}", response.Reserved3).AppendLine(); + + if(response.Reserved4 != 0) + sb.AppendFormat("Reserved4 = 0x{0:X16}", response.Reserved4).AppendLine(); + + if(response.Reserved5 != 0) + sb.AppendFormat("Reserved5 = 0x{0:X8}", response.Reserved5).AppendLine(); + + if(response.Reserved6 != 0) + sb.AppendFormat("Reserved6 = 0x{0:X8}", response.Reserved6).AppendLine(); + + if(response.Reserved7 != 0) + sb.AppendFormat("Reserved7 = 0x{0:X2}", response.Reserved7).AppendLine(); + + if(response.Reserved8 != 0) + sb.AppendFormat("Reserved8 = 0x{0:X2}", response.Reserved8).AppendLine(); + + if(response.Reserved9 != 0) + sb.AppendFormat("Reserved9 = 0x{0:X8}", response.Reserved9).AppendLine(); + #endif + + return sb.ToString(); + } + + public static string Prettify(byte[] DDSResponse) => Prettify(Decode(DDSResponse)); + #endregion Public methods + } +} \ No newline at end of file diff --git a/Aaru.Decoders/Bluray/DI.cs b/Aaru.Decoders/Bluray/DI.cs new file mode 100644 index 000000000..967d07ee1 --- /dev/null +++ b/Aaru.Decoders/Bluray/DI.cs @@ -0,0 +1,580 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : DI.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes Blu-ray Disc Information. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Console; +using Aaru.Helpers; + +namespace Aaru.Decoders.Bluray +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class DI + { + public enum BluSize : byte + { + /// 120mm + OneTwenty = 0, + /// 80mm + Eighty = 1 + } + + public enum ChannelLength : byte + { + /// 74.5nm channel or 25Gb/layer + Seventy = 1, + /// 69.0nm channel or 27Gb/layer + Sixty = 2 + } + + public enum HybridLayer : byte + { + /// No hybrid layer + None = 0, + /// -ROM layer + ReadOnly = 1, + /// -R layer + Recordable = 2, + /// -RW layer + Rewritable = 3 + } + + #region Private constants + const string DiscTypeBDROM = "BDO"; + const string DiscTypeBDRE = "BDW"; + const string DiscTypeBDR = "BDR"; + + /// Disc Information Unit Identifier "DI" + const ushort DIUIdentifier = 0x4449; + #endregion Private constants + + #region Public methods + public static DiscInformation? Decode(byte[] DIResponse) + { + if(DIResponse == null) + return null; + + if(DIResponse.Length != 4100) + { + AaruConsole.DebugWriteLine("BD Disc Information decoder", + "Found incorrect Blu-ray Disc Information size ({0} bytes)", + DIResponse.Length); + + return null; + } + + var decoded = new DiscInformation + { + DataLength = BigEndianBitConverter.ToUInt16(DIResponse, 0), + Reserved1 = DIResponse[2], + Reserved2 = DIResponse[3] + }; + + int offset = 4; + List units = new List(); + + while(true) + { + if(offset >= 4100) + break; + + var unit = new DiscInformationUnits + { + Signature = BigEndianBitConverter.ToUInt16(DIResponse, 0 + offset) + }; + + if(unit.Signature != DIUIdentifier) + break; + + unit.Format = DIResponse[2 + offset]; + unit.UnitsPerBlock = (byte)((DIResponse[3 + offset] & 0xF8) >> 3); + unit.Layer = (byte)(DIResponse[3 + offset] & 0x07); + unit.Legacy = DIResponse[4 + offset]; + unit.Sequence = DIResponse[5 + offset]; + unit.Continuation = (DIResponse[6 + offset] & 0x80) == 0x80; + unit.Length = (byte)(DIResponse[6 + offset] & 0x7F); + unit.Reserved = DIResponse[7 + offset]; + unit.DiscTypeIdentifier = new byte[3]; + Array.Copy(DIResponse, 8 + offset, unit.DiscTypeIdentifier, 0, 3); + unit.DiscSize = (BluSize)((DIResponse[11 + offset] & 0xC0) >> 6); + unit.DiscClass = (byte)((DIResponse[11 + offset] & 0x30) >> 4); + unit.DiscVersion = (byte)(DIResponse[11 + offset] & 0x0F); + unit.Layers = (byte)((DIResponse[12 + offset] & 0xF0) >> 4); + unit.DvdLayer = (HybridLayer)((DIResponse[13 + offset] & 0xC0) >> 6); + unit.CdLayer = (HybridLayer)((DIResponse[13 + offset] & 0x30) >> 4); + unit.ChannelLength = (ChannelLength)(DIResponse[13 + offset] & 0x0F); + unit.Polarity = DIResponse[14 + offset]; + unit.RecordedPolarity = DIResponse[14 + offset]; + unit.Bca = (byte)(DIResponse[16 + offset] & 0x0F); + unit.MaxTransfer = DIResponse[17 + offset]; + + unit.LastPsn = (uint)((DIResponse[20 + offset] << 24) + (DIResponse[21 + offset] << 16) + + (DIResponse[22 + offset] << 8) + DIResponse[23 + offset]); + + // TODO: In -R/-RE how does this relate to layer size??? + unit.FirstAun = (uint)((DIResponse[24 + offset] << 24) + (DIResponse[25 + offset] << 16) + + (DIResponse[26 + offset] << 8) + DIResponse[27 + offset]); + + unit.LastAun = (uint)((DIResponse[28 + offset] << 24) + (DIResponse[29 + offset] << 16) + + (DIResponse[30 + offset] << 8) + DIResponse[31 + offset]); + + switch(Encoding.ASCII.GetString(unit.DiscTypeIdentifier)) + { + case DiscTypeBDROM: + { + unit.FormatDependentContents = new byte[32]; + Array.Copy(DIResponse, 32 + offset, unit.FormatDependentContents, 0, 32); + + break; + } + + case DiscTypeBDRE: + case DiscTypeBDR: + { + unit.FormatDependentContents = new byte[66]; + Array.Copy(DIResponse, 32 + offset, unit.FormatDependentContents, 0, 66); + unit.ManufacturerID = new byte[6]; + Array.Copy(DIResponse, 100 + offset, unit.ManufacturerID, 0, 6); + unit.MediaTypeID = new byte[3]; + Array.Copy(DIResponse, 106 + offset, unit.MediaTypeID, 0, 3); + unit.TimeStamp = BigEndianBitConverter.ToUInt16(DIResponse, 109 + offset); + unit.ProductRevisionNumber = DIResponse[111 + offset]; + + offset += 14; + + break; + } + + default: + { + AaruConsole.DebugWriteLine("BD Disc Information decoder", + "Found unknown disc type identifier \"{0}\"", + Encoding.ASCII.GetString(unit.DiscTypeIdentifier)); + + break; + } + } + + units.Add(unit); + + offset += unit.Length; + } + + if(units.Count <= 0) + return decoded; + + decoded.Units = new DiscInformationUnits[units.Count]; + + for(int i = 0; i < units.Count; i++) + decoded.Units[i] = units[i]; + + return decoded; + } + + public static string Prettify(DiscInformation? DIResponse) + { + if(DIResponse == null) + return null; + + DiscInformation response = DIResponse.Value; + + var sb = new StringBuilder(); + + foreach(DiscInformationUnits unit in response.Units) + { + sb.AppendFormat("DI Unit Sequence: {0}", unit.Sequence).AppendLine(); + sb.AppendFormat("DI Unit Format: 0x{0:X2}", unit.Format).AppendLine(); + sb.AppendFormat("There are {0} per block", unit.UnitsPerBlock).AppendLine(); + sb.AppendFormat("This DI refers to layer {0}", unit.Layer).AppendLine(); + + if(Encoding.ASCII.GetString(unit.DiscTypeIdentifier) == DiscTypeBDRE) + sb.AppendFormat("Legacy value: 0x{0:X2}", unit.Legacy).AppendLine(); + + sb.AppendLine(unit.Continuation ? "This DI continues previous unit" : "This DI starts a new unit"); + sb.AppendFormat("DI Unit is {0} bytes", unit.Length).AppendLine(); + + sb.AppendFormat("Disc type identifier: \"{0}\"", Encoding.ASCII.GetString(unit.DiscTypeIdentifier)). + AppendLine(); + + switch(unit.DiscSize) + { + case BluSize.OneTwenty: + sb.AppendLine("Disc size: 120mm"); + + break; + case BluSize.Eighty: + sb.AppendLine("Disc size: 80mm"); + + break; + default: + sb.AppendFormat("Disc size: Unknown code {0}", (byte)unit.DiscSize).AppendLine(); + + break; + } + + sb.AppendFormat("Disc class: {0}", unit.DiscClass).AppendLine(); + sb.AppendFormat("Disc version: {0}", unit.DiscVersion).AppendLine(); + sb.AppendFormat("This disc has {0} layers", unit.Layers).AppendLine(); + + switch(unit.DvdLayer) + { + case HybridLayer.None: + sb.AppendLine("This disc does not contain a DVD layer."); + + break; + case HybridLayer.ReadOnly: + sb.AppendLine("This disc contains a DVD-ROM layer."); + + break; + case HybridLayer.Recordable: + sb.AppendLine("This disc contains a DVD-R layer."); + + break; + case HybridLayer.Rewritable: + sb.AppendLine("This disc contains a DVD-RW layer."); + + break; + } + + switch(unit.CdLayer) + { + case HybridLayer.None: + sb.AppendLine("This disc does not contain a CD layer."); + + break; + case HybridLayer.ReadOnly: + sb.AppendLine("This disc contains a CD-ROM layer."); + + break; + case HybridLayer.Recordable: + sb.AppendLine("This disc contains a CD-R layer."); + + break; + case HybridLayer.Rewritable: + sb.AppendLine("This disc contains a CD-RW layer."); + + break; + } + + switch(unit.ChannelLength) + { + case ChannelLength.Seventy: + sb.AppendLine("Disc uses a 74.5nm channel giving 25 Gb per layer."); + + break; + case ChannelLength.Sixty: + sb.AppendLine("Disc uses a 69.0nm channel giving 27 Gb per layer."); + + break; + default: + sb.AppendFormat("Disc uses unknown channel length with code {0}", (byte)unit.ChannelLength). + AppendLine(); + + break; + } + + switch(unit.Polarity) + { + case 0: + sb.AppendLine("Disc uses positive polarity."); + + break; + case 1: + sb.AppendLine("Disc uses negative polarity."); + + break; + default: + sb.AppendFormat("Disc uses unknown polarity with code {0}", unit.Polarity).AppendLine(); + + break; + } + + if(Encoding.ASCII.GetString(unit.DiscTypeIdentifier) == DiscTypeBDR) + switch(unit.RecordedPolarity) + { + case 0: + sb.AppendLine("Recorded marks have a lower reflectivity than unrecorded ones (HTL disc)."); + + break; + case 1: + sb.AppendLine("Recorded marks have a higher reflectivity than unrecorded ones (LTH disc)."); + + break; + default: + sb.AppendFormat("Disc uses unknown recorded reflectivity polarity with code {0}", + unit.RecordedPolarity).AppendLine(); + + break; + } + + switch(unit.Bca) + { + case 0: + sb.AppendLine("Disc doesn't have a BCA."); + + break; + case 1: + sb.AppendLine("Disc has a BCA."); + + break; + default: + sb.AppendFormat("Disc uses unknown BCA code {0}", unit.Bca).AppendLine(); + + break; + } + + if(unit.MaxTransfer > 0) + sb.AppendFormat("Disc has a maximum transfer rate of {0} Mbit/sec.", unit.MaxTransfer).AppendLine(); + else + sb.AppendLine("Disc does not specify a maximum transfer rate."); + + sb.AppendFormat("Last user data PSN for disc: {0}", unit.LastPsn).AppendLine(); + + sb.AppendFormat("First address unit number of data zone in this layer: {0}", unit.FirstAun). + AppendLine(); + + sb.AppendFormat("Last address unit number of data zone in this layer: {0}", unit.LastAun).AppendLine(); + + if(Encoding.ASCII.GetString(unit.DiscTypeIdentifier) == DiscTypeBDR || + Encoding.ASCII.GetString(unit.DiscTypeIdentifier) == DiscTypeBDRE) + { + sb.AppendFormat("Disc manufacturer ID: \"{0}\"", Encoding.ASCII.GetString(unit.ManufacturerID)). + AppendLine(); + + sb.AppendFormat("Disc media type ID: \"{0}\"", Encoding.ASCII.GetString(unit.MediaTypeID)). + AppendLine(); + + sb.AppendFormat("Disc timestamp: 0x{0:X2}", unit.TimeStamp).AppendLine(); + sb.AppendFormat("Disc product revison number: {0}", unit.ProductRevisionNumber).AppendLine(); + } + + sb.AppendFormat("Blu-ray DI Unit format dependent contents as hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(unit.FormatDependentContents, 80)); + } + + return sb.ToString(); + } + + public static string Prettify(byte[] DIResponse) => Prettify(Decode(DIResponse)); + + public static string ManufacturerFromDI(string manufacturerId) + { + string manufacturer = ""; + + switch(manufacturerId) + { + case "AMESOB": + case "OTCBDR": + manufacturer = "Amethystum Storage Technology Co., Ltd."; + + break; + case "UMEBDR": + case "ANWELL": + manufacturer = "Avic Umedisc HK Ltd."; + + break; + case "MAXELL": + manufacturer = "Hitachi Maxell, Ltd."; + + break; + case "CMCMAG": + manufacturer = "CMC Magnetics Corporation"; + + break; + case "ISMMBD": + manufacturer = "Info Source Digital Media (Zhong Shan) Co., Ltd."; + + break; + case "LGEBRA": + manufacturer = "LG Electronics Inc."; + + break; + case "MILLEN": + manufacturer = "Millenniata, Inc."; + + break; + case "VERBAT": + case "VAMKM": + manufacturer = "Mitsubishi Chemical Media Co., Ltd."; + + break; + case "PHILIP": + case "MBI": + manufacturer = "Moser Baer India Ltd."; + + break; + case "MEI": + case "PAN": + manufacturer = "Matsushita Electric Industrial Co., Ltd."; + + break; + case "PRODIS": + manufacturer = "Prodisc Technology Inc."; + + break; + case "RITEK": + manufacturer = "Ritek Co."; + + break; + case "SONY": + manufacturer = "Sony Corporation"; + + break; + case "TYG-BD": + manufacturer = "Taiyo Yuden Company Ltd."; + + break; + case "TDKBLD": + manufacturer = "TDK Corporation"; + + break; + case "JVC-AM": + case "JVCVAM": + manufacturer = "Victor Advanced media Co., Ltd."; + + break; + case "JVCRE1": + manufacturer = "JVC KENWOOD Corporation"; + + break; + case "INFOME": + manufacturer = "InfoMedia Inc."; + + break; + } + + return manufacturer != "" ? $"{manufacturer} (\"{manufacturerId}\")" : $"\"{manufacturerId}\""; + } + #endregion Public methods + + #region Public structures + public struct DiscInformation + { + /// Bytes 0 to 1 Always 4098 + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4 to 4099 Disc information units + public DiscInformationUnits[] Units; + } + + public struct DiscInformationUnits + { + /// Byte 0 "DI" + public ushort Signature; + /// Byte 2 Disc information format + public byte Format; + /// Byte 3, bits 7 to 3 Number of DI units per block + public byte UnitsPerBlock; + /// Byte 3, bits 2 to 0 Layer this DI refers to + public byte Layer; + /// Byte 4 Reserved for BD-ROM, legacy information for BD-R/-RE + public byte Legacy; + /// Byte 5 Sequence number for this DI unit + public byte Sequence; + /// Byte 6, bit 7 If set this DI is a continuation of the previous one + public bool Continuation; + /// Byte 6, bits 6 to 0 Number of bytes used by this DI unit, should be 64 for BD-ROM and 112 for BD-R/-RE + public byte Length; + /// Byte 7 Reserved + public byte Reserved; + /// Bytes 8 to 10 Disc type identifier + public byte[] DiscTypeIdentifier; + /// Byte 11, bits 7 to 6 Disc size + public BluSize DiscSize; + /// Byte 11, bits 5 to 4 Disc class + public byte DiscClass; + /// Byte 11, bits 3 to 0 Disc version + public byte DiscVersion; + /// Byte 12, bits 7 to 4 Layers in this disc + public byte Layers; + /// Byte 12, bits 3 to 0 Reserved + public byte Reserved2; + /// Byte 13, bits 7 to 6 DVD layer + public HybridLayer DvdLayer; + /// Byte 13, bits 5 to 4 CD layer + public HybridLayer CdLayer; + /// Byte 13, bits 3 to 0 Channel length + public ChannelLength ChannelLength; + /// Byte 14 Polarity + public byte Polarity; + /// Byte 15 Recorded polarity + public byte RecordedPolarity; + /// Byte 16, bits 7 to 4 Reserved + public byte Reserved3; + /// Byte 16, bits 3 to 0 If 0 no BCA, if 1 BCA, rest not defined + public byte Bca; + /// Byte 17 Maximum transfer speed in megabits/second, 0 if no maximum + public byte MaxTransfer; + /// Bytes 18 to 19 Reserved + public ushort Reserved4; + /// Bytes 20 to 23 Last user data PSN for disc + public uint LastPsn; + /// Bytes 24 to 27 First address unit number of data zone in this layer + public uint FirstAun; + /// Bytes 28 to 31 Last address unit number of data zone in this layer + public uint LastAun; + /// + /// Bytes 32 to 63 for BD-ROM, bytes 32 to 99 for BD-R/-RE Format dependent contents, disclosed in private blu-ray + /// specifications + /// + public byte[] FormatDependentContents; + /// Bytes 100 to 105, BD-R/-RE only Manufacturer ID + public byte[] ManufacturerID; + /// Bytes 106 to 108, BD-R/-RE only Media type ID + public byte[] MediaTypeID; + /// Bytes 109 to 110, BD-R/-RE only Timestamp + public ushort TimeStamp; + /// Byte 111 Product revision number + public byte ProductRevisionNumber; + } + #endregion Public structures + } +} \ No newline at end of file diff --git a/Aaru.Decoders/Bluray/Spare.cs b/Aaru.Decoders/Bluray/Spare.cs new file mode 100644 index 000000000..db861d26d --- /dev/null +++ b/Aaru.Decoders/Bluray/Spare.cs @@ -0,0 +1,130 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Spare.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes Blu-ray Spare Area Information. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Console; +using Aaru.Helpers; + +namespace Aaru.Decoders.Bluray +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class Spare + { + #region Public structures + public struct SpareAreaInformation + { + /// Bytes 0 to 1 Always 14 + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to 7 Reserved + public uint Reserved3; + /// Bytes 8 to 11 Free spare blocks + public uint FreeSpareBlocks; + /// Bytes 12 to 15 Allocated spare blocks + public uint AllocatedSpareBlocks; + } + #endregion Public structures + #region Public methods + public static SpareAreaInformation? Decode(byte[] SAIResponse) + { + if(SAIResponse == null) + return null; + + if(SAIResponse.Length != 16) + { + AaruConsole.DebugWriteLine("BD Spare Area Information decoder", + "Found incorrect Blu-ray Spare Area Information size ({0} bytes)", + SAIResponse.Length); + + return null; + } + + var decoded = new SpareAreaInformation + { + DataLength = BigEndianBitConverter.ToUInt16(SAIResponse, 0), + Reserved1 = SAIResponse[2], + Reserved2 = SAIResponse[3], + Reserved3 = BigEndianBitConverter.ToUInt32(SAIResponse, 4), + FreeSpareBlocks = BigEndianBitConverter.ToUInt32(SAIResponse, 8), + AllocatedSpareBlocks = BigEndianBitConverter.ToUInt32(SAIResponse, 12) + }; + + return decoded; + } + + public static string Prettify(SpareAreaInformation? SAIResponse) + { + if(SAIResponse == null) + return null; + + SpareAreaInformation response = SAIResponse.Value; + + var sb = new StringBuilder(); + + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + + if(response.Reserved3 != 0) + sb.AppendFormat("Reserved3 = 0x{0:X8}", response.Reserved3).AppendLine(); + #endif + sb.AppendFormat("{0} free spare blocks", response.FreeSpareBlocks).AppendLine(); + sb.AppendFormat("{0} allocated spare blocks", response.AllocatedSpareBlocks).AppendLine(); + + return sb.ToString(); + } + + public static string Prettify(byte[] SAIResponse) => Prettify(Decode(SAIResponse)); + #endregion Public methods + } +} \ No newline at end of file diff --git a/Aaru.Decoders/CD/ATIP.cs b/Aaru.Decoders/CD/ATIP.cs new file mode 100644 index 000000000..5d6d9f306 --- /dev/null +++ b/Aaru.Decoders/CD/ATIP.cs @@ -0,0 +1,679 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ATIP.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes CD Absolute-Time-In-Pregroove +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Console; +using Aaru.Helpers; + +namespace Aaru.Decoders.CD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class ATIP + { + public static CDATIP Decode(byte[] CDATIPResponse) + { + if(CDATIPResponse == null || + CDATIPResponse.Length <= 4) + return null; + + var decoded = new CDATIP(); + + if(CDATIPResponse.Length != 32 && + CDATIPResponse.Length != 28) + { + AaruConsole.DebugWriteLine("CD ATIP decoder", + "Expected CD ATIP size (32 bytes) is not received size ({0} bytes), not decoding", + CDATIPResponse.Length); + + return null; + } + + decoded.DataLength = BigEndianBitConverter.ToUInt16(CDATIPResponse, 0); + decoded.Reserved1 = CDATIPResponse[2]; + decoded.Reserved2 = CDATIPResponse[3]; + decoded.ITWP = (byte)((CDATIPResponse[4] & 0xF0) >> 4); + decoded.DDCD = Convert.ToBoolean(CDATIPResponse[4] & 0x08); + decoded.ReferenceSpeed = (byte)(CDATIPResponse[4] & 0x07); + decoded.AlwaysZero = Convert.ToBoolean(CDATIPResponse[5] & 0x80); + decoded.URU = Convert.ToBoolean(CDATIPResponse[5] & 0x40); + decoded.Reserved3 = (byte)(CDATIPResponse[5] & 0x3F); + + decoded.AlwaysOne = Convert.ToBoolean(CDATIPResponse[6] & 0x80); + decoded.DiscType = Convert.ToBoolean(CDATIPResponse[6] & 0x40); + decoded.DiscSubType = (byte)((CDATIPResponse[6] & 0x38) >> 3); + decoded.A1Valid = Convert.ToBoolean(CDATIPResponse[6] & 0x04); + decoded.A2Valid = Convert.ToBoolean(CDATIPResponse[6] & 0x02); + decoded.A3Valid = Convert.ToBoolean(CDATIPResponse[6] & 0x01); + + decoded.Reserved4 = CDATIPResponse[7]; + decoded.LeadInStartMin = CDATIPResponse[8]; + decoded.LeadInStartSec = CDATIPResponse[9]; + decoded.LeadInStartFrame = CDATIPResponse[10]; + decoded.Reserved5 = CDATIPResponse[11]; + decoded.LeadOutStartMin = CDATIPResponse[12]; + decoded.LeadOutStartSec = CDATIPResponse[13]; + decoded.LeadOutStartFrame = CDATIPResponse[14]; + decoded.Reserved6 = CDATIPResponse[15]; + + decoded.A1Values = new byte[3]; + decoded.A2Values = new byte[3]; + decoded.A3Values = new byte[3]; + + Array.Copy(CDATIPResponse, 16, decoded.A1Values, 0, 3); + Array.Copy(CDATIPResponse, 20, decoded.A2Values, 0, 3); + Array.Copy(CDATIPResponse, 24, decoded.A3Values, 0, 3); + + decoded.Reserved7 = CDATIPResponse[19]; + decoded.Reserved8 = CDATIPResponse[23]; + decoded.Reserved9 = CDATIPResponse[27]; + + if(CDATIPResponse.Length < 32) + return decoded.AlwaysOne ? decoded : null; + + decoded.S4Values = new byte[3]; + Array.Copy(CDATIPResponse, 28, decoded.S4Values, 0, 3); + decoded.Reserved10 = CDATIPResponse[31]; + + return decoded.AlwaysOne ? decoded : null; + } + + public static string Prettify(CDATIP response) + { + if(response == null) + return null; + + var sb = new StringBuilder(); + + if(response.DDCD) + { + sb.AppendFormat("Indicative Target Writing Power: 0x{0:X2}", response.ITWP).AppendLine(); + sb.AppendLine(response.DiscType ? "Disc is DDCD-RW" : "Disc is DDCD-R"); + + switch(response.ReferenceSpeed) + { + case 2: + sb.AppendLine("Reference speed is 4x"); + + break; + case 3: + sb.AppendLine("Reference speed is 8x"); + + break; + default: + sb.AppendFormat("Reference speed set is unknown: {0}", response.ReferenceSpeed).AppendLine(); + + break; + } + + sb.AppendFormat("ATIP Start time of Lead-in: 0x{0:X6}", + (response.LeadInStartMin << 16) + (response.LeadInStartSec << 8) + + response.LeadInStartFrame).AppendLine(); + + sb.AppendFormat("ATIP Last possible start time of Lead-out: 0x{0:X6}", + (response.LeadOutStartMin << 16) + (response.LeadOutStartSec << 8) + + response.LeadOutStartFrame).AppendLine(); + + sb.AppendFormat("S4 value: 0x{0:X6}", + (response.S4Values[0] << 16) + (response.S4Values[1] << 8) + response.S4Values[2]). + AppendLine(); + } + else + { + sb.AppendFormat("Indicative Target Writing Power: 0x{0:X2}", response.ITWP & 0x07).AppendLine(); + + if(response.DiscType) + { + switch(response.DiscSubType) + { + case 0: + sb.AppendLine("Disc is CD-RW"); + + break; + case 1: + sb.AppendLine("Disc is High-Speed CD-RW"); + + break; + case 2: + sb.AppendLine("Disc is Ultra-Speed CD-RW"); + + break; + case 3: + sb.AppendLine("Disc is Ultra-Speed+ CD-RW"); + + break; + case 4: + sb.AppendLine("Disc is medium type B, low beta category (B-) CD-RW"); + + break; + case 5: + sb.AppendLine("Disc is medium type B, high beta category (B+) CD-RW"); + + break; + case 6: + sb.AppendLine("Disc is medium type C, low beta category (C-) CD-RW"); + + break; + case 7: + sb.AppendLine("Disc is medium type C, high beta category (C+) CD-RW"); + + break; + default: + sb.AppendFormat("Unknown CD-RW disc subtype: {0}", response.DiscSubType).AppendLine(); + + break; + } + + switch(response.ReferenceSpeed) + { + case 1: + sb.AppendLine("Reference speed is 2x"); + + break; + default: + sb.AppendFormat("Reference speed set is unknown: {0}", response.ReferenceSpeed). + AppendLine(); + + break; + } + } + else + { + sb.AppendLine("Disc is CD-R"); + + switch(response.DiscSubType) + { + case 0: + sb.AppendLine("Disc is normal speed (CLV) CD-R"); + + break; + case 1: + sb.AppendLine("Disc is high speed (CAV) CD-R"); + + break; + case 2: + sb.AppendLine("Disc is medium type A, low beta category (A-) CD-R"); + + break; + case 3: + sb.AppendLine("Disc is medium type A, high beta category (A+) CD-R"); + + break; + case 4: + sb.AppendLine("Disc is medium type B, low beta category (B-) CD-R"); + + break; + case 5: + sb.AppendLine("Disc is medium type B, high beta category (B+) CD-R"); + + break; + case 6: + sb.AppendLine("Disc is medium type C, low beta category (C-) CD-R"); + + break; + case 7: + sb.AppendLine("Disc is medium type C, high beta category (C+) CD-R"); + + break; + default: + sb.AppendFormat("Unknown CD-R disc subtype: {0}", response.DiscSubType).AppendLine(); + + break; + } + } + + sb.AppendLine(response.URU ? "Disc use is unrestricted" : "Disc use is restricted"); + + sb.AppendFormat("ATIP Start time of Lead-in: {0}:{1:D2}:{2:D2}", response.LeadInStartMin, + response.LeadInStartSec, response.LeadInStartFrame).AppendLine(); + + sb.AppendFormat("ATIP Last possible start time of Lead-out: {0}:{1:D2}:{2:D2}", + response.LeadOutStartMin, response.LeadOutStartSec, response.LeadOutStartFrame). + AppendLine(); + + if(response.A1Valid) + sb.AppendFormat("A1 value: 0x{0:X6}", + (response.A1Values[0] << 16) + (response.A1Values[1] << 8) + response.A1Values[2]). + AppendLine(); + + if(response.A2Valid) + sb.AppendFormat("A2 value: 0x{0:X6}", + (response.A2Values[0] << 16) + (response.A2Values[1] << 8) + response.A2Values[2]). + AppendLine(); + + if(response.A3Valid) + sb.AppendFormat("A3 value: 0x{0:X6}", + (response.A3Values[0] << 16) + (response.A3Values[1] << 8) + response.A3Values[2]). + AppendLine(); + + if(response.S4Values != null) + sb.AppendFormat("S4 value: 0x{0:X6}", + (response.S4Values[0] << 16) + (response.S4Values[1] << 8) + response.S4Values[2]). + AppendLine(); + } + + if(response.LeadInStartMin != 97) + return sb.ToString(); + + int type = response.LeadInStartFrame % 10; + int frm = response.LeadInStartFrame - type; + + if(response.DiscType) + sb.AppendLine("Disc uses phase change"); + else + sb.AppendLine(type < 5 ? "Disc uses long strategy type dye (Cyanine, AZO, etc...)" + : "Disc uses short strategy type dye (Phthalocyanine, etc...)"); + + string manufacturer = ManufacturerFromATIP(response.LeadInStartSec, frm); + + if(manufacturer != "") + sb.AppendFormat("Disc manufactured by: {0}", manufacturer).AppendLine(); + + return sb.ToString(); + } + + public static string Prettify(byte[] CDATIPResponse) + { + CDATIP decoded = Decode(CDATIPResponse); + + return Prettify(decoded); + } + + public static string ManufacturerFromATIP(byte sec, int frm) + { + switch(sec) + { + case 10: + switch(frm) + { + case 00: return "Ritek Co."; + } + + break; + case 15: + switch(frm) + { + case 00: return "TDK Corporation"; + case 10: return "Ritek Co."; + case 20: return "Mitsubishi Chemical Corporation"; + case 30: return "NAN-YA Plastics Corporation"; + } + + break; + case 16: + switch(frm) + { + case 20: return "Shenzen SG&Gast Digital Optical Discs"; + case 30: return "Grand Advance Technology Ltd."; + } + + break; + case 17: + if(frm == 00) + return "Moser Baer India Ltd."; + + break; + case 18: + switch(frm) + { + case 10: return "Wealth Fair Investment Ltd."; + case 60: return "Taroko International Co. Ltd."; + } + + break; + case 20: + if(frm == 10) + return "CDA Datenträger Albrechts GmbH"; + + break; + case 21: + switch(frm) + { + case 10: return "Grupo Condor S.L."; + case 20: return "E-TOP Mediatek Inc."; + case 30: return "Bestdisc Technology Corporation"; + case 40: return "Optical Disc Manufacturing Equipment"; + case 50: return "Sound Sound Multi-Media Development Ltd."; + } + + break; + case 22: + switch(frm) + { + case 00: return "Woongjin Media Corp."; + case 10: return "Seantram Technology Inc."; + case 20: return "Advanced Digital Media"; + case 30: return "EXIMPO"; + case 40: return "CIS Technology Inc."; + case 50: return "Hong Kong Digital Technology Co., Ltd."; + case 60: return "Acer Media Technology, Inc."; + } + + break; + case 23: + switch(frm) + { + case 00: return "Matsushita Electric Industrial Co., Ltd."; + case 10: return "Doremi Media Co., Ltd."; + case 20: return "Nacar Media s.r.l."; + case 30: return "Audio Distributors Co., Ltd."; + case 40: return "Victor Company of Japan, Ltd."; + case 50: return "Optrom Inc."; + case 60: return "Customer Pressing Oosterhout"; + } + + break; + case 24: + switch(frm) + { + case 00: return "Taiyo Yuden Company Ltd."; + case 10: return "SONY Corporation"; + case 20: return "Computer Support Italy s.r.l."; + case 30: return "Unitech Japan Inc."; + case 40: return "kdg mediatech AG"; + case 50: return "Guann Yinn Co., Ltd."; + case 60: return "Harmonic Hall Optical Disc Ltd."; + } + + break; + case 25: + switch(frm) + { + case 00: return "MPO"; + case 20: return "Hitachi Maxell, Ltd."; + case 30: return "Infodisc Technology Co. Ltd."; + case 40: return "Vivastar AG"; + case 50: return "AMS Technology Inc."; + case 60: return "Xcitec Inc."; + } + + break; + case 26: + switch(frm) + { + case 00: return "Fornet International Pte Ltd."; + case 10: return "POSTECH Corporation"; + case 20: return "SKC Co., Ltd."; + case 30: return "Optical Disc Corporation"; + case 40: return "FUJI Photo Film Co., Ltd."; + case 50: return "Lead Data Inc."; + case 60: return "CMC Magnetics Corporation"; + } + + break; + case 27: + switch(frm) + { + case 00: return "Digital Storage Technology Co., Ltd."; + case 10: return "Plasmon Data systems Ltd."; + case 20: return "Princo Corporation"; + case 30: return "Pioneer Video Corporation"; + case 40: return "Kodak Japan Ltd."; + case 50: return "Mitsui Chemicals, Inc."; + case 60: return "Ricoh Company Ltd."; + } + + break; + case 28: + switch(frm) + { + case 00: return "Opti.Me.S. S.p.A."; + case 10: return "Gigastore Corporation"; + case 20: return "Multi Media Masters & Machinary SA"; + case 30: return "Auvistar Industry Co., Ltd."; + case 40: return "King Pro Mediatek Inc."; + case 50: return "Delphi Technology Inc."; + case 60: return "Friendly CD-Tek Co."; + } + + break; + case 29: + switch(frm) + { + case 00: return "Taeil Media Co., Ltd."; + case 10: return "Vanguard Disc Inc."; + case 20: return "Unidisc Technology Co., Ltd."; + case 30: return "Hile Optical Disc Technology Corp."; + case 40: return "Viva Magnetics Ltd."; + case 50: return "General Magnetics Ltd."; + } + + break; + case 30: + if(frm == 10) + return "CDA Datenträger Albrechts GmbH"; + + break; + case 31: + switch(frm) + { + case 00: return "Ritek Co."; + case 30: return "Grand Advance Technology Ltd."; + } + + break; + case 32: + switch(frm) + { + case 00: return "TDK Corporation"; + case 10: return "Prodisc Technology Inc."; + } + + break; + case 34: + switch(frm) + { + case 20: + case 22: return "Mitsubishi Chemical Corporation"; + } + + break; + case 36: + switch(frm) + { + case 00: return "Gish International Co., Ltd."; + } + + break; + case 42: + if(frm == 20) + return "Advanced Digital Media"; + + break; + case 45: + switch(frm) + { + case 00: return "Fornet International Pte Ltd."; + case 10: return "Unitech Japan Inc."; + case 20: return "Acer Media Technology, Inc."; + case 40: return "CIS Technology Inc."; + case 50: return "Guann Yinn Co., Ltd."; + case 60: return "Xcitec Inc."; + } + + break; + case 46: + switch(frm) + { + case 00: return "Taiyo Yuden Company Ltd."; + case 10: return "Hong Kong Digital Technology Co., Ltd."; + case 20: return "Multi Media Masters & Machinary SA"; + case 30: return "Computer Support Italy s.r.l."; + case 40: return "FUJI Photo Film Co., Ltd."; + case 50: return "Auvistar Industry Co., Ltd."; + case 60: return "CMC Magnetics Corporation"; + } + + break; + case 47: + switch(frm) + { + case 10: return "Hitachi Maxell, Ltd."; + case 20: return "Princo Corporation"; + case 40: return "POSTECH Corporation"; + case 50: return "Ritek Co."; + case 60: return "Prodisc Technology Inc."; + } + + break; + case 48: + switch(frm) + { + case 00: return "Ricoh Company Ltd."; + case 10: return "Kodak Japan Ltd."; + case 20: return "Plasmon Data systems Ltd."; + case 30: return "Pioneer Video Corporation"; + case 40: return "Digital Storage Technology Co., Ltd."; + case 50: return "Mitsui Chemicals, Inc."; + case 60: return "Lead Data Inc."; + } + + break; + case 49: + switch(frm) + { + case 00: return "TDK Corporation"; + case 10: return "Gigastore Corporation"; + case 20: return "King Pro Mediatek Inc."; + case 30: return "Opti.Me.S. S.p.A."; + case 40: return "Victor Company of Japan, Ltd."; + case 60: return "Matsushita Electric Industrial Co., Ltd."; + } + + break; + case 50: + switch(frm) + { + case 10: return "Vanguard Disc Inc."; + case 20: return "Mitsubishi Chemical Corporation"; + case 30: return "CDA Datenträger Albrechts GmbH"; + } + + break; + case 51: + switch(frm) + { + case 10: return "Grand Advance Technology Ltd."; + case 20: return "Infodisc Technology Co. Ltd."; + case 50: return "Hile Optical Disc Technology Corp."; + } + + break; + } + + return ""; + } + + public class CDATIP + { + /// Byte 6, bit 2 A1 values are valid + public bool A1Valid; + /// Bytes 16 to 18 A1 values + public byte[] A1Values; + /// Byte 6, bit 1 A2 values are valid + public bool A2Valid; + /// Bytes 20 to 22 A2 values + public byte[] A2Values; + /// Byte 6, bit 0 A3 values are valid + public bool A3Valid; + /// Bytes 24 to 26 A3 values + public byte[] A3Values; + /// Byte 6, bit 7 Always set + public bool AlwaysOne; + /// Byte 5, bit 7 Always unset + public bool AlwaysZero; + /// Bytes 1 to 0 Total size of returned session information minus this field + public ushort DataLength; + /// Byte 4, bit 3 Set if DDCD + public bool DDCD; + /// Byte 6, bits 5 to 3 Disc subtype + public byte DiscSubType; + /// Byte 6, bit 6 Set if rewritable (CD-RW or DDCD-RW) + public bool DiscType; + /// Byte 4, bits 7 to 4 Indicative target writing power + public byte ITWP; + /// Byte 10 ATIP Start time of Lead-In (Frame) + public byte LeadInStartFrame; + /// Byte 8 ATIP Start time of Lead-In (Minute) + public byte LeadInStartMin; + /// Byte 9 ATIP Start time of Lead-In (Second) + public byte LeadInStartSec; + /// Byte 14 ATIP Last possible start time of Lead-Out (Frame) + public byte LeadOutStartFrame; + /// Byte 12 ATIP Last possible start time of Lead-Out (Minute) + public byte LeadOutStartMin; + /// Byte 13 ATIP Last possible start time of Lead-Out (Second) + public byte LeadOutStartSec; + /// Byte 4, bits 2 to 0 Reference speed + public byte ReferenceSpeed; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 31 Reserved + public byte Reserved10; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 5, bits 5 to 0 Reserved + public byte Reserved3; + /// Byte 7 Reserved + public byte Reserved4; + /// Byte 11 Reserved + public byte Reserved5; + /// Byte 15 Reserved + public byte Reserved6; + /// Byte 19 Reserved + public byte Reserved7; + /// Byte 23 Reserved + public byte Reserved8; + /// Byte 27 Reserved + public byte Reserved9; + /// Bytes 28 to 30 S4 values + public byte[] S4Values; + /// Byte 5, bit 6 Unrestricted media + public bool URU; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/CD/CDTextOnLeadIn.cs b/Aaru.Decoders/CD/CDTextOnLeadIn.cs new file mode 100644 index 000000000..934b07390 --- /dev/null +++ b/Aaru.Decoders/CD/CDTextOnLeadIn.cs @@ -0,0 +1,377 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CDTextOnLeadIn.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes CD-TEXT on Lead-In. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Console; +using Aaru.Helpers; + +namespace Aaru.Decoders.CD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class CDTextOnLeadIn + { + public enum PackTypeIndicator : byte + { + /// Title of the track (or album if track == 0) + Title = 0x80, + /// Performer + Performer = 0x81, + /// Songwriter + Songwriter = 0x82, + /// Composer + Composer = 0x83, + /// Arranger + Arranger = 0x84, + /// Message from the content provider or artist + Message = 0x85, + /// Disc identification information + DiscIdentification = 0x86, + /// Genre identification + GenreIdentification = 0x87, + /// Table of content information + TOCInformation = 0x88, + /// Second table of content information + SecondTOCInformation = 0x89, + /// Reserved + Reserved1 = 0x8A, + /// Reserved + Reserved2 = 0x8B, + /// Reserved + Reserved3 = 0x8C, + /// Reserved for content provider only + ReservedForContentProvider = 0x8D, + /// UPC of album or ISRC of track + UPCorISRC = 0x8E, + /// Size information of the block + BlockSizeInformation = 0x8F + } + + public static CDText? Decode(byte[] CDTextResponse) + { + if(CDTextResponse == null || + CDTextResponse.Length <= 4) + return null; + + var decoded = new CDText + { + DataLength = BigEndianBitConverter.ToUInt16(CDTextResponse, 0), + Reserved1 = CDTextResponse[2], + Reserved2 = CDTextResponse[3] + }; + + decoded.DataPacks = new CDTextPack[(decoded.DataLength - 2) / 18]; + + if(decoded.DataLength == 2) + return null; + + if(decoded.DataLength + 2 != CDTextResponse.Length) + { + AaruConsole.DebugWriteLine("CD-TEXT decoder", + "Expected CD-TEXT size ({0} bytes) is not received size ({1} bytes), not decoding", + decoded.DataLength + 2, CDTextResponse.Length); + + return null; + } + + for(int i = 0; i < (decoded.DataLength - 2) / 18; i++) + { + decoded.DataPacks[i].HeaderID1 = CDTextResponse[0 + (i * 18) + 4]; + decoded.DataPacks[i].HeaderID2 = CDTextResponse[1 + (i * 18) + 4]; + decoded.DataPacks[i].HeaderID3 = CDTextResponse[2 + (i * 18) + 4]; + decoded.DataPacks[i].DBCC = Convert.ToBoolean(CDTextResponse[3 + (i * 18) + 4] & 0x80); + decoded.DataPacks[i].BlockNumber = (byte)((CDTextResponse[3 + (i * 18) + 4] & 0x70) >> 4); + decoded.DataPacks[i].CharacterPosition = (byte)(CDTextResponse[3 + (i * 18) + 4] & 0x0F); + decoded.DataPacks[i].TextDataField = new byte[12]; + Array.Copy(CDTextResponse, 4 + (i * 18) + 4, decoded.DataPacks[i].TextDataField, 0, 12); + decoded.DataPacks[i].CRC = BigEndianBitConverter.ToUInt16(CDTextResponse, 16 + (i * 18) + 4); + } + + return decoded; + } + + public static string Prettify(CDText? CDTextResponse) + { + if(CDTextResponse == null) + return null; + + CDText response = CDTextResponse.Value; + var sb = new StringBuilder(); + + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + #endif + + foreach(CDTextPack descriptor in response.DataPacks) + if((descriptor.HeaderID1 & 0x80) != 0x80) + { + // Ignore NOPs + if((descriptor.HeaderID1 & 0x80) != 0) + sb.AppendFormat("Incorrect CD-Text pack type {0}, not decoding", descriptor.HeaderID1). + AppendLine(); + } + else + { + switch(descriptor.HeaderID1) + { + case 0x80: + { + sb.Append("CD-Text pack contains title for "); + + if(descriptor.HeaderID2 == 0x00) + sb.AppendLine("album"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + + break; + } + + case 0x81: + { + sb.Append("CD-Text pack contains performer for "); + + if(descriptor.HeaderID2 == 0x00) + sb.AppendLine("album"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + + break; + } + + case 0x82: + { + sb.Append("CD-Text pack contains songwriter for "); + + if(descriptor.HeaderID2 == 0x00) + sb.AppendLine("album"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + + break; + } + + case 0x83: + { + if(descriptor.HeaderID2 == 0x00) + sb.AppendLine("album"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + + break; + } + + case 0x84: + { + sb.Append("CD-Text pack contains arranger for "); + + if(descriptor.HeaderID2 == 0x00) + sb.AppendLine("album"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + + break; + } + + case 0x85: + { + sb.Append("CD-Text pack contains content provider's message for "); + + if(descriptor.HeaderID2 == 0x00) + sb.AppendLine("album"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + + break; + } + + case 0x86: + { + sb.AppendLine("CD-Text pack contains disc identification information"); + + break; + } + + case 0x87: + { + sb.AppendLine("CD-Text pack contains genre identification information"); + + break; + } + + case 0x88: + { + sb.AppendLine("CD-Text pack contains table of contents information"); + + break; + } + + case 0x89: + { + sb.AppendLine("CD-Text pack contains second table of contents information"); + + break; + } + + case 0x8A: + case 0x8B: + case 0x8C: + { + sb.AppendLine("CD-Text pack contains reserved data"); + + break; + } + + case 0x8D: + { + sb.AppendLine("CD-Text pack contains data reserved for content provider only"); + + break; + } + + case 0x8E: + { + if(descriptor.HeaderID2 == 0x00) + sb.AppendLine("CD-Text pack contains UPC"); + else + sb.AppendFormat("track {0}", descriptor.HeaderID2).AppendLine(); + + break; + } + + case 0x8F: + { + sb.AppendLine("CD-Text pack contains size block information"); + + break; + } + } + + switch(descriptor.HeaderID1) + { + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x8E: + { + if(descriptor.DBCC) + sb.AppendLine("Double Byte Character Code is used"); + + sb.AppendFormat("Block number {0}", descriptor.BlockNumber).AppendLine(); + sb.AppendFormat("Character position {0}", descriptor.CharacterPosition).AppendLine(); + + sb.AppendFormat("Text field: \"{0}\"", + StringHandlers.CToString(descriptor.TextDataField, + Encoding.GetEncoding("iso-8859-1"))).AppendLine(); + + break; + } + + default: + { + sb.AppendFormat("Binary contents: {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.TextDataField, 28)). + AppendLine(); + + break; + } + } + + sb.AppendFormat("CRC: 0x{0:X4}", descriptor.CRC).AppendLine(); + } + + return sb.ToString(); + } + + public static string Prettify(byte[] CDTextResponse) + { + CDText? decoded = Decode(CDTextResponse); + + return Prettify(decoded); + } + + public struct CDText + { + /// Total size of returned CD-Text information minus this field + public ushort DataLength; + /// Reserved + public byte Reserved1; + /// Reserved + public byte Reserved2; + /// CD-Text data packs + public CDTextPack[] DataPacks; + } + + public struct CDTextPack + { + /// Byte 0 Pack ID1 (Pack Type) + public byte HeaderID1; + /// Byte 1 Pack ID2 (Track number) + public byte HeaderID2; + /// Byte 2 Pack ID3 + public byte HeaderID3; + /// Byte 3, bit 7 Double Byte Character Code + public bool DBCC; + /// Byte 3, bits 6 to 4 Block number + public byte BlockNumber; + /// Byte 3, bits 3 to 0 Character position + public byte CharacterPosition; + /// Bytes 4 to 15 Text data + public byte[] TextDataField; + /// Bytes 16 to 17 CRC16 + public ushort CRC; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/CD/Enums.cs b/Aaru.Decoders/CD/Enums.cs new file mode 100644 index 000000000..33780b761 --- /dev/null +++ b/Aaru.Decoders/CD/Enums.cs @@ -0,0 +1,73 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Enums.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Contains various CD enumerations. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.Decoders.CD +{ + [SuppressMessage("ReSharper", "MemberCanBeInternal")] + public enum TocAdr : byte + { + /// Q Sub-channel mode information not supplied + NoInformation = 0x00, + /// Q Sub-channel encodes current position data + CurrentPosition = 0x01, + /// Q Sub-channel encodes the media catalog number + MediaCatalogNumber = 0x02, + /// Q Sub-channel encodes the ISRC + ISRC = 0x03, + /// Q Sub-channel encodes the start of an audio/data track (if found in TOC) + TrackPointer = 0x01, + /// Q Sub-channel encodes the start of a video track (if found in TOC) for CD-V + VideoTrackPointer = 0x04 + } + + public enum TocControl : byte + { + /// Stereo audio, no pre-emphasis + TwoChanNoPreEmph = 0x00, + /// Stereo audio with pre-emphasis + TwoChanPreEmph = 0x01, + /// If mask applied, track can be copied + CopyPermissionMask = 0x02, + /// Data track, recorded uninterrumpted + DataTrack = 0x04, + /// Data track, recorded incrementally + DataTrackIncremental = 0x05, + /// Quadraphonic audio, no pre-emphasis + FourChanNoPreEmph = 0x08, + /// Quadraphonic audio with pre-emphasis + FourChanPreEmph = 0x09, + /// Reserved mask + ReservedMask = 0x0C + } +} \ No newline at end of file diff --git a/Aaru.Decoders/CD/FullTOC.cs b/Aaru.Decoders/CD/FullTOC.cs new file mode 100644 index 000000000..2950f89bf --- /dev/null +++ b/Aaru.Decoders/CD/FullTOC.cs @@ -0,0 +1,789 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : FullTOC.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes CD full Table of Contents. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Structs; +using Aaru.Console; +using Aaru.Helpers; + +namespace Aaru.Decoders.CD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + // ISO/IEC 61104: Compact disc video system - 12 cm CD-V + // ISO/IEC 60908: Audio recording - Compact disc digital audio system + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class FullTOC + { + const string StereoNoPre = "Stereo audio track with no pre-emphasis"; + const string StereoPreEm = "Stereo audio track with 50/15 μs pre-emphasis"; + const string QuadNoPreEm = "Quadraphonic audio track with no pre-emphasis"; + const string QuadPreEmph = "Quadraphonic audio track with 50/15 μs pre-emphasis"; + const string DataUnintrp = "Data track, recorded uninterrupted"; + const string DataIncrtly = "Data track, recorded incrementally"; + + public static CDFullTOC? Decode(byte[] CDFullTOCResponse) + { + if(CDFullTOCResponse == null || + CDFullTOCResponse.Length <= 4) + return null; + + var decoded = new CDFullTOC + { + DataLength = BigEndianBitConverter.ToUInt16(CDFullTOCResponse, 0), + FirstCompleteSession = CDFullTOCResponse[2], + LastCompleteSession = CDFullTOCResponse[3] + }; + + decoded.TrackDescriptors = new TrackDataDescriptor[(decoded.DataLength - 2) / 11]; + + if(decoded.DataLength + 2 != CDFullTOCResponse.Length) + { + AaruConsole.DebugWriteLine("CD full TOC decoder", + "Expected CDFullTOC size ({0} bytes) is not received size ({1} bytes), not decoding", + decoded.DataLength + 2, CDFullTOCResponse.Length); + + return null; + } + + for(int i = 0; i < (decoded.DataLength - 2) / 11; i++) + { + decoded.TrackDescriptors[i].SessionNumber = CDFullTOCResponse[0 + (i * 11) + 4]; + decoded.TrackDescriptors[i].ADR = (byte)((CDFullTOCResponse[1 + (i * 11) + 4] & 0xF0) >> 4); + decoded.TrackDescriptors[i].CONTROL = (byte)(CDFullTOCResponse[1 + (i * 11) + 4] & 0x0F); + decoded.TrackDescriptors[i].TNO = CDFullTOCResponse[2 + (i * 11) + 4]; + decoded.TrackDescriptors[i].POINT = CDFullTOCResponse[3 + (i * 11) + 4]; + decoded.TrackDescriptors[i].Min = CDFullTOCResponse[4 + (i * 11) + 4]; + decoded.TrackDescriptors[i].Sec = CDFullTOCResponse[5 + (i * 11) + 4]; + decoded.TrackDescriptors[i].Frame = CDFullTOCResponse[6 + (i * 11) + 4]; + decoded.TrackDescriptors[i].Zero = CDFullTOCResponse[7 + (i * 11) + 4]; + decoded.TrackDescriptors[i].HOUR = (byte)((CDFullTOCResponse[7 + (i * 11) + 4] & 0xF0) >> 4); + decoded.TrackDescriptors[i].PHOUR = (byte)(CDFullTOCResponse[7 + (i * 11) + 4] & 0x0F); + decoded.TrackDescriptors[i].PMIN = CDFullTOCResponse[8 + (i * 11) + 4]; + decoded.TrackDescriptors[i].PSEC = CDFullTOCResponse[9 + (i * 11) + 4]; + decoded.TrackDescriptors[i].PFRAME = CDFullTOCResponse[10 + (i * 11) + 4]; + } + + return decoded; + } + + public static string Prettify(CDFullTOC? CDFullTOCResponse) + { + if(CDFullTOCResponse == null) + return null; + + CDFullTOC response = CDFullTOCResponse.Value; + + var sb = new StringBuilder(); + + int lastSession = 0; + + sb.AppendFormat("First complete session number: {0}", response.FirstCompleteSession).AppendLine(); + sb.AppendFormat("Last complete session number: {0}", response.LastCompleteSession).AppendLine(); + + foreach(TrackDataDescriptor descriptor in response.TrackDescriptors) + if((descriptor.CONTROL & 0x08) == 0x08 || + (descriptor.ADR != 1 && descriptor.ADR != 5 && descriptor.ADR != 4 && descriptor.ADR != 6) || + descriptor.TNO != 0) + { + sb.AppendLine("Unknown TOC entry format, printing values as-is"); + sb.AppendFormat("SessionNumber = {0}", descriptor.SessionNumber).AppendLine(); + sb.AppendFormat("ADR = {0}", descriptor.ADR).AppendLine(); + sb.AppendFormat("CONTROL = {0}", descriptor.CONTROL).AppendLine(); + sb.AppendFormat("TNO = {0}", descriptor.TNO).AppendLine(); + sb.AppendFormat("POINT = {0}", descriptor.POINT).AppendLine(); + sb.AppendFormat("Min = {0}", descriptor.Min).AppendLine(); + sb.AppendFormat("Sec = {0}", descriptor.Sec).AppendLine(); + sb.AppendFormat("Frame = {0}", descriptor.Frame).AppendLine(); + sb.AppendFormat("HOUR = {0}", descriptor.HOUR).AppendLine(); + sb.AppendFormat("PHOUR = {0}", descriptor.PHOUR).AppendLine(); + sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine(); + sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine(); + sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine(); + } + else + { + if(descriptor.SessionNumber > lastSession) + { + sb.AppendFormat("Session {0}", descriptor.SessionNumber).AppendLine(); + lastSession = descriptor.SessionNumber; + } + + switch(descriptor.ADR) + { + case 1: + case 4: + { + switch(descriptor.POINT) + { + case 0xA0 when descriptor.ADR == 4: + { + sb.AppendFormat("First video track number: {0}", descriptor.PMIN).AppendLine(); + + switch(descriptor.PSEC) + { + case 0x10: + sb.AppendLine("CD-V single in NTSC format with digital stereo sound"); + + break; + case 0x11: + sb.AppendLine("CD-V single in NTSC format with digital bilingual sound"); + + break; + case 0x12: + sb.AppendLine("CD-V disc in NTSC format with digital stereo sound"); + + break; + case 0x13: + sb.AppendLine("CD-V disc in NTSC format with digital bilingual sound"); + + break; + case 0x20: + sb.AppendLine("CD-V single in PAL format with digital stereo sound"); + + break; + case 0x21: + sb.AppendLine("CD-V single in PAL format with digital bilingual sound"); + + break; + case 0x22: + sb.AppendLine("CD-V disc in PAL format with digital stereo sound"); + + break; + case 0x23: + sb.AppendLine("CD-V disc in PAL format with digital bilingual sound"); + + break; + } + + break; + } + + case 0xA0 when descriptor.ADR == 1: + { + sb.AppendFormat("First track number: {0} (", descriptor.PMIN); + + switch((TocControl)(descriptor.CONTROL & 0x0D)) + { + case TocControl.TwoChanNoPreEmph: + sb.Append(StereoNoPre); + + break; + case TocControl.TwoChanPreEmph: + sb.Append(StereoPreEm); + + break; + case TocControl.FourChanNoPreEmph: + sb.Append(QuadNoPreEm); + + break; + case TocControl.FourChanPreEmph: + sb.Append(QuadPreEmph); + + break; + case TocControl.DataTrack: + sb.Append(DataUnintrp); + + break; + case TocControl.DataTrackIncremental: + sb.Append(DataIncrtly); + + break; + } + + sb.AppendLine(")"); + sb.AppendFormat("Disc type: {0}", descriptor.PSEC).AppendLine(); + + //sb.AppendFormat("Absolute time: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine(); + break; + } + + case 0xA1 when descriptor.ADR == 4: + sb.AppendFormat("Last video track number: {0}", descriptor.PMIN).AppendLine(); + + break; + case 0xA1 when descriptor.ADR == 1: + { + sb.AppendFormat("Last track number: {0} (", descriptor.PMIN); + + switch((TocControl)(descriptor.CONTROL & 0x0D)) + { + case TocControl.TwoChanNoPreEmph: + sb.Append(StereoNoPre); + + break; + case TocControl.TwoChanPreEmph: + sb.Append(StereoPreEm); + + break; + case TocControl.FourChanNoPreEmph: + sb.Append(QuadNoPreEm); + + break; + case TocControl.FourChanPreEmph: + sb.Append(QuadPreEmph); + + break; + case TocControl.DataTrack: + sb.Append(DataUnintrp); + + break; + case TocControl.DataTrackIncremental: + sb.Append(DataIncrtly); + + break; + } + + sb.AppendLine(")"); + + //sb.AppendFormat("Absolute time: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine(); + break; + } + + case 0xA2: + { + if(descriptor.PHOUR > 0) + sb.AppendFormat("Lead-out start position: {3:D2}:{0:D2}:{1:D2}:{2:D2}", + descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, + descriptor.PHOUR).AppendLine(); + else + sb.AppendFormat("Lead-out start position: {0:D2}:{1:D2}:{2:D2}", + descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME). + AppendLine(); + + //sb.AppendFormat("Absolute time: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine(); + + switch((TocControl)(descriptor.CONTROL & 0x0D)) + { + case TocControl.TwoChanNoPreEmph: + case TocControl.TwoChanPreEmph: + case TocControl.FourChanNoPreEmph: + case TocControl.FourChanPreEmph: + sb.AppendLine("Lead-out is audio type"); + + break; + case TocControl.DataTrack: + case TocControl.DataTrackIncremental: + sb.AppendLine("Lead-out is data type"); + + break; + } + + break; + } + + case 0xF0: + { + sb.AppendFormat("Book type: 0x{0:X2}", descriptor.PMIN); + sb.AppendFormat("Material type: 0x{0:X2}", descriptor.PSEC); + sb.AppendFormat("Moment of inertia: 0x{0:X2}", descriptor.PFRAME); + + if(descriptor.PHOUR > 0) + sb.AppendFormat("Absolute time: {3:D2}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, + descriptor.Sec, descriptor.Frame, descriptor.HOUR).AppendLine(); + else + sb.AppendFormat("Absolute time: {0:D2}:{1:D2}:{2:D2}", descriptor.Min, + descriptor.Sec, descriptor.Frame).AppendLine(); + + break; + } + + default: + { + if(descriptor.POINT >= 0x01 && + descriptor.POINT <= 0x63) + if(descriptor.ADR == 4) + sb.AppendFormat("Video track {3} starts at: {0:D2}:{1:D2}:{2:D2}", + descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, + descriptor.POINT).AppendLine(); + else + { + string type = "Audio"; + + if((TocControl)(descriptor.CONTROL & 0x0D) == TocControl.DataTrack || + (TocControl)(descriptor.CONTROL & 0x0D) == + TocControl.DataTrackIncremental) + type = "Data"; + + if(descriptor.PHOUR > 0) + sb.AppendFormat("{5} track {3} starts at: {4:D2}:{0:D2}:{1:D2}:{2:D2} (", + descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, + descriptor.POINT, descriptor.PHOUR, type); + else + sb.AppendFormat("{4} track {3} starts at: {0:D2}:{1:D2}:{2:D2} (", + descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, + descriptor.POINT, type); + + switch((TocControl)(descriptor.CONTROL & 0x0D)) + { + case TocControl.TwoChanNoPreEmph: + sb.Append(StereoNoPre); + + break; + case TocControl.TwoChanPreEmph: + sb.Append(StereoPreEm); + + break; + case TocControl.FourChanNoPreEmph: + sb.Append(QuadNoPreEm); + + break; + case TocControl.FourChanPreEmph: + sb.Append(QuadPreEmph); + + break; + case TocControl.DataTrack: + sb.Append(DataUnintrp); + + break; + case TocControl.DataTrackIncremental: + sb.Append(DataIncrtly); + + break; + } + + sb.AppendLine(")"); + } + else + { + sb.AppendFormat("ADR = {0}", descriptor.ADR).AppendLine(); + sb.AppendFormat("CONTROL = {0}", descriptor.CONTROL).AppendLine(); + sb.AppendFormat("TNO = {0}", descriptor.TNO).AppendLine(); + sb.AppendFormat("POINT = {0}", descriptor.POINT).AppendLine(); + sb.AppendFormat("Min = {0}", descriptor.Min).AppendLine(); + sb.AppendFormat("Sec = {0}", descriptor.Sec).AppendLine(); + sb.AppendFormat("Frame = {0}", descriptor.Frame).AppendLine(); + sb.AppendFormat("HOUR = {0}", descriptor.HOUR).AppendLine(); + sb.AppendFormat("PHOUR = {0}", descriptor.PHOUR).AppendLine(); + sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine(); + sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine(); + sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine(); + } + + break; + } + } + + break; + } + + case 5: + { + switch(descriptor.POINT) + { + case 0xB0: + { + if(descriptor.PHOUR > 0) + { + sb. + AppendFormat("Start of next possible program in the recordable area of the disc: {3:D2}:{0:D2}:{1:D2}:{2:D2}", + descriptor.Min, descriptor.Sec, descriptor.Frame, + descriptor.HOUR).AppendLine(); + + sb. + AppendFormat("Maximum start of outermost Lead-out in the recordable area of the disc: {3:D2}:{0:D2}:{1:D2}:{2:D2}", + descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, + descriptor.PHOUR).AppendLine(); + } + else + { + sb. + AppendFormat("Start of next possible program in the recordable area of the disc: {0:D2}:{1:D2}:{2:D2}", + descriptor.Min, descriptor.Sec, descriptor.Frame).AppendLine(); + + sb. + AppendFormat("Maximum start of outermost Lead-out in the recordable area of the disc: {0:D2}:{1:D2}:{2:D2}", + descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME). + AppendLine(); + } + + break; + } + + case 0xB1: + { + sb.AppendFormat("Number of skip interval pointers: {0}", descriptor.PMIN). + AppendLine(); + + sb.AppendFormat("Number of skip track pointers: {0}", descriptor.PSEC).AppendLine(); + + break; + } + + case 0xB2: + case 0xB3: + case 0xB4: + { + sb.AppendFormat("Skip track {0}", descriptor.Min).AppendLine(); + sb.AppendFormat("Skip track {0}", descriptor.Sec).AppendLine(); + sb.AppendFormat("Skip track {0}", descriptor.Frame).AppendLine(); + sb.AppendFormat("Skip track {0}", descriptor.Zero).AppendLine(); + sb.AppendFormat("Skip track {0}", descriptor.PMIN).AppendLine(); + sb.AppendFormat("Skip track {0}", descriptor.PSEC).AppendLine(); + sb.AppendFormat("Skip track {0}", descriptor.PFRAME).AppendLine(); + + break; + } + + case 0xC0: + { + sb.AppendFormat("Optimum recording power: 0x{0:X2}", descriptor.Min).AppendLine(); + + if(descriptor.PHOUR > 0) + sb. + AppendFormat("Start time of the first Lead-in area in the disc: {3:D2}:{0:D2}:{1:D2}:{2:D2}", + descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, + descriptor.PHOUR).AppendLine(); + else + sb. + AppendFormat("Start time of the first Lead-in area in the disc: {0:D2}:{1:D2}:{2:D2}", + descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME). + AppendLine(); + + break; + } + + case 0xC1: + { + sb.AppendFormat("Copy of information of A1 from ATIP found"); + sb.AppendFormat("Min = {0}", descriptor.Min).AppendLine(); + sb.AppendFormat("Sec = {0}", descriptor.Sec).AppendLine(); + sb.AppendFormat("Frame = {0}", descriptor.Frame).AppendLine(); + sb.AppendFormat("Zero = {0}", descriptor.Zero).AppendLine(); + sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine(); + sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine(); + sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine(); + + break; + } + + case 0xCF: + { + if(descriptor.PHOUR > 0) + { + sb. + AppendFormat("Start position of outer part lead-in area: {3:D2}:{0:D2}:{1:D2}:{2:D2}", + descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME, + descriptor.PHOUR).AppendLine(); + + sb. + AppendFormat("Stop position of inner part lead-out area: {3:D2}:{0:D2}:{1:D2}:{2:D2}", + descriptor.Min, descriptor.Sec, descriptor.Frame, + descriptor.HOUR).AppendLine(); + } + else + { + sb. + AppendFormat("Start position of outer part lead-in area: {0:D2}:{1:D2}:{2:D2}", + descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME). + AppendLine(); + + sb. + AppendFormat("Stop position of inner part lead-out area: {0:D2}:{1:D2}:{2:D2}", + descriptor.Min, descriptor.Sec, descriptor.Frame).AppendLine(); + } + + break; + } + + default: + { + if(descriptor.POINT >= 0x01 && + descriptor.POINT <= 0x40) + { + sb. + AppendFormat("Start time for interval that should be skipped: {0:D2}:{1:D2}:{2:D2}", + descriptor.PMIN, descriptor.PSEC, descriptor.PFRAME). + AppendLine(); + + sb. + AppendFormat("Ending time for interval that should be skipped: {0:D2}:{1:D2}:{2:D2}", + descriptor.Min, descriptor.Sec, descriptor.Frame).AppendLine(); + } + else + { + sb.AppendFormat("ADR = {0}", descriptor.ADR).AppendLine(); + sb.AppendFormat("CONTROL = {0}", descriptor.CONTROL).AppendLine(); + sb.AppendFormat("TNO = {0}", descriptor.TNO).AppendLine(); + sb.AppendFormat("POINT = {0}", descriptor.POINT).AppendLine(); + sb.AppendFormat("Min = {0}", descriptor.Min).AppendLine(); + sb.AppendFormat("Sec = {0}", descriptor.Sec).AppendLine(); + sb.AppendFormat("Frame = {0}", descriptor.Frame).AppendLine(); + sb.AppendFormat("HOUR = {0}", descriptor.HOUR).AppendLine(); + sb.AppendFormat("PHOUR = {0}", descriptor.PHOUR).AppendLine(); + sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine(); + sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine(); + sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine(); + } + + break; + } + } + + break; + } + + case 6: + { + uint id = (uint)((descriptor.Min << 16) + (descriptor.Sec << 8) + descriptor.Frame); + sb.AppendFormat("Disc ID: {0:X6}", id & 0x00FFFFFF).AppendLine(); + + break; + } + } + } + + return sb.ToString(); + } + + public static string Prettify(byte[] CDFullTOCResponse) + { + CDFullTOC? decoded = Decode(CDFullTOCResponse); + + return Prettify(decoded); + } + + public struct CDFullTOC + { + /// Total size of returned session information minus this field + public ushort DataLength; + /// First complete session number in hex + public byte FirstCompleteSession; + /// Last complete session number in hex + public byte LastCompleteSession; + /// Track descriptors + public TrackDataDescriptor[] TrackDescriptors; + } + + public struct TrackDataDescriptor + { + /// Byte 0 Session number in hex + public byte SessionNumber; + /// Byte 1, bits 7 to 4 Type of information in Q subchannel of block where this TOC entry was found + public byte ADR; + /// Byte 1, bits 3 to 0 Track attributes + public byte CONTROL; + /// Byte 2 + public byte TNO; + /// Byte 3 + public byte POINT; + /// Byte 4 + public byte Min; + /// Byte 5 + public byte Sec; + /// Byte 6 + public byte Frame; + /// Byte 7, CD only + public byte Zero; + /// Byte 7, bits 7 to 4, DDCD only + public byte HOUR; + /// Byte 7, bits 3 to 0, DDCD only + public byte PHOUR; + /// Byte 8 + public byte PMIN; + /// Byte 9 + public byte PSEC; + /// Byte 10 + public byte PFRAME; + } + + public static CDFullTOC Create(List tracks, Dictionary trackFlags, + bool createC0Entry = false) + { + var toc = new CDFullTOC(); + Dictionary sessionEndingTrack = new Dictionary(); + toc.FirstCompleteSession = byte.MaxValue; + toc.LastCompleteSession = byte.MinValue; + List trackDescriptors = new List(); + byte currentTrack = 0; + + foreach(Track track in tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence)) + { + if(track.TrackSession < toc.FirstCompleteSession) + toc.FirstCompleteSession = (byte)track.TrackSession; + + if(track.TrackSession <= toc.LastCompleteSession) + { + currentTrack = (byte)track.TrackSequence; + + continue; + } + + if(toc.LastCompleteSession > 0) + sessionEndingTrack.Add(toc.LastCompleteSession, currentTrack); + + toc.LastCompleteSession = (byte)track.TrackSession; + } + + if(!sessionEndingTrack.ContainsKey(toc.LastCompleteSession)) + sessionEndingTrack[toc.LastCompleteSession] = (byte)tracks. + Where(t => t.TrackSession == + toc.LastCompleteSession). + Max(t => t.TrackSequence); + + byte currentSession = 0; + + foreach(Track track in tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence)) + { + trackFlags.TryGetValue((byte)track.TrackSequence, out byte trackControl); + + if(trackControl == 0 && + track.TrackType != TrackType.Audio) + trackControl = (byte)CdFlags.DataTrack; + + // Lead-Out + if(track.TrackSession > currentSession && + currentSession != 0) + { + (byte minute, byte second, byte frame) leadoutAmsf = LbaToMsf(track.TrackStartSector - 150); + + (byte minute, byte second, byte frame) leadoutPmsf = + LbaToMsf(tracks.OrderBy(t => t.TrackSession).ThenBy(t => t.TrackSequence).Last(). + TrackStartSector); + + // Lead-out + trackDescriptors.Add(new TrackDataDescriptor + { + SessionNumber = currentSession, + POINT = 0xB0, + ADR = 5, + CONTROL = 0, + HOUR = 0, + Min = leadoutAmsf.minute, + Sec = leadoutAmsf.second, + Frame = leadoutAmsf.frame, + PHOUR = 2, + PMIN = leadoutPmsf.minute, + PSEC = leadoutPmsf.second, + PFRAME = leadoutPmsf.frame + }); + + // This seems to be constant? It should not exist on CD-ROM but CloneCD creates them anyway + // Format seems like ATIP, but ATIP should not be as 0xC0 in TOC... + if(createC0Entry) + trackDescriptors.Add(new TrackDataDescriptor + { + SessionNumber = currentSession, + POINT = 0xC0, + ADR = 5, + CONTROL = 0, + Min = 128, + PMIN = 97, + PSEC = 25 + }); + } + + // Lead-in + if(track.TrackSession > currentSession) + { + currentSession = (byte)track.TrackSession; + sessionEndingTrack.TryGetValue(currentSession, out byte endingTrackNumber); + + (byte minute, byte second, byte frame) leadinPmsf = + LbaToMsf((tracks.FirstOrDefault(t => t.TrackSequence == endingTrackNumber)?.TrackEndSector ?? + 0) + 1); + + // Starting track + trackDescriptors.Add(new TrackDataDescriptor + { + SessionNumber = currentSession, + POINT = 0xA0, + ADR = 1, + CONTROL = trackControl, + PMIN = (byte)track.TrackSequence + }); + + // Ending track + trackDescriptors.Add(new TrackDataDescriptor + { + SessionNumber = currentSession, + POINT = 0xA1, + ADR = 1, + CONTROL = trackControl, + PMIN = endingTrackNumber + }); + + // Lead-out start + trackDescriptors.Add(new TrackDataDescriptor + { + SessionNumber = currentSession, + POINT = 0xA2, + ADR = 1, + CONTROL = trackControl, + PHOUR = 0, + PMIN = leadinPmsf.minute, + PSEC = leadinPmsf.second, + PFRAME = leadinPmsf.frame + }); + } + + (byte minute, byte second, byte frame) pmsf = LbaToMsf((ulong)track.Indexes[1]); + + // Track + trackDescriptors.Add(new TrackDataDescriptor + { + SessionNumber = (byte)track.TrackSession, + POINT = (byte)track.TrackSequence, + ADR = 1, + CONTROL = trackControl, + PHOUR = 0, + PMIN = pmsf.minute, + PSEC = pmsf.second, + PFRAME = pmsf.frame + }); + } + + toc.TrackDescriptors = trackDescriptors.ToArray(); + + return toc; + } + + static (byte minute, byte second, byte frame) LbaToMsf(ulong sector) => + ((byte)((sector + 150) / 75 / 60), (byte)((sector + 150) / 75 % 60), (byte)((sector + 150) % 75)); + } +} \ No newline at end of file diff --git a/Aaru.Decoders/CD/PMA.cs b/Aaru.Decoders/CD/PMA.cs new file mode 100644 index 000000000..a5cb29f79 --- /dev/null +++ b/Aaru.Decoders/CD/PMA.cs @@ -0,0 +1,345 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : PMA.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes CD Power Management Area. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Console; +using Aaru.Helpers; + +namespace Aaru.Decoders.CD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class PMA + { + public static CDPMA? Decode(byte[] CDPMAResponse) + { + if(CDPMAResponse == null || + CDPMAResponse.Length <= 4) + return null; + + var decoded = new CDPMA + { + DataLength = BigEndianBitConverter.ToUInt16(CDPMAResponse, 0), + Reserved1 = CDPMAResponse[2], + Reserved2 = CDPMAResponse[3] + }; + + decoded.PMADescriptors = new CDPMADescriptors[(decoded.DataLength - 2) / 11]; + + if(decoded.PMADescriptors.Length == 0) + return null; + + if(decoded.DataLength + 2 != CDPMAResponse.Length) + { + AaruConsole.DebugWriteLine("CD PMA decoder", + "Expected CDPMA size ({0} bytes) is not received size ({1} bytes), not decoding", + decoded.DataLength + 2, CDPMAResponse.Length); + + return null; + } + + for(int i = 0; i < (decoded.DataLength - 2) / 11; i++) + { + decoded.PMADescriptors[i].Reserved = CDPMAResponse[0 + (i * 11) + 4]; + decoded.PMADescriptors[i].ADR = (byte)((CDPMAResponse[1 + (i * 11) + 4] & 0xF0) >> 4); + decoded.PMADescriptors[i].CONTROL = (byte)(CDPMAResponse[1 + (i * 11) + 4] & 0x0F); + decoded.PMADescriptors[i].TNO = CDPMAResponse[2 + (i * 11) + 4]; + decoded.PMADescriptors[i].POINT = CDPMAResponse[3 + (i * 11) + 4]; + decoded.PMADescriptors[i].Min = CDPMAResponse[4 + (i * 11) + 4]; + decoded.PMADescriptors[i].Sec = CDPMAResponse[5 + (i * 11) + 4]; + decoded.PMADescriptors[i].Frame = CDPMAResponse[6 + (i * 11) + 4]; + decoded.PMADescriptors[i].HOUR = (byte)((CDPMAResponse[7 + (i * 11) + 4] & 0xF0) >> 4); + decoded.PMADescriptors[i].PHOUR = (byte)(CDPMAResponse[7 + (i * 11) + 4] & 0x0F); + decoded.PMADescriptors[i].PMIN = CDPMAResponse[8 + (i * 11) + 4]; + decoded.PMADescriptors[i].PSEC = CDPMAResponse[9 + (i * 11) + 4]; + decoded.PMADescriptors[i].PFRAME = CDPMAResponse[10 + (i * 11) + 4]; + } + + return decoded; + } + + public static string Prettify(CDPMA? CDPMAResponse) + { + if(CDPMAResponse == null) + return null; + + CDPMA response = CDPMAResponse.Value; + + var sb = new StringBuilder(); + + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + #endif + + foreach(CDPMADescriptors descriptor in response.PMADescriptors) + { + #if DEBUG + if(descriptor.Reserved != 0) + sb.AppendFormat("Reserved = 0x{0:X2}", descriptor.Reserved).AppendLine(); + #endif + + switch(descriptor.ADR) + { + case 1: + if(descriptor.POINT > 0) + { + sb.AppendFormat("Track {0}", descriptor.POINT); + + switch((TocControl)(descriptor.CONTROL & 0x0D)) + { + case TocControl.TwoChanNoPreEmph: + sb.Append(" (Stereo audio track with no pre-emphasis)"); + + break; + case TocControl.TwoChanPreEmph: + sb.Append(" (Stereo audio track with 50/15 μs pre-emphasis)"); + + break; + case TocControl.FourChanNoPreEmph: + sb.Append(" (Quadraphonic audio track with no pre-emphasis)"); + + break; + case TocControl.FourChanPreEmph: + sb.Append(" (Quadraphonic audio track with 50/15 μs pre-emphasis)"); + + break; + case TocControl.DataTrack: + sb.Append(" (Data track, recorded uninterrupted)"); + + break; + case TocControl.DataTrackIncremental: + sb.Append(" (Data track, recorded incrementally)"); + + break; + } + + if(descriptor.PHOUR > 0) + sb.AppendFormat(" starts at {3}:{0:D2}:{1:D2}:{2:D2}", descriptor.PMIN, descriptor.PSEC, + descriptor.PFRAME, descriptor.PHOUR); + else + sb.AppendFormat(" starts at {0:D2}:{1:D2}:{2:D2}", descriptor.PMIN, descriptor.PSEC, + descriptor.PFRAME); + + if(descriptor.PHOUR > 0) + sb.AppendFormat(" and ends at {3}:{0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, + descriptor.Frame, descriptor.HOUR); + else + sb.AppendFormat(" and ends at {0:D2}:{1:D2}:{2:D2}", descriptor.Min, descriptor.Sec, + descriptor.Frame); + + sb.AppendLine(); + } + else + goto default; + + break; + case 2: + uint id = (uint)((descriptor.Min << 16) + (descriptor.Sec << 8) + descriptor.Frame); + sb.AppendFormat("Disc ID: {0:X6}", id & 0x00FFFFFF).AppendLine(); + + break; + case 3: + sb.AppendFormat("Skip track assignment {0} says that tracks ", descriptor.POINT); + + if(descriptor.Min > 0) + sb.AppendFormat("{0} ", descriptor.Min); + + if(descriptor.Sec > 0) + sb.AppendFormat("{0} ", descriptor.Sec); + + if(descriptor.Frame > 0) + sb.AppendFormat("{0} ", descriptor.Frame); + + if(descriptor.PMIN > 0) + sb.AppendFormat("{0} ", descriptor.PMIN); + + if(descriptor.PSEC > 0) + sb.AppendFormat("{0} ", descriptor.PSEC); + + if(descriptor.PFRAME > 0) + sb.AppendFormat("{0} ", descriptor.PFRAME); + + sb.AppendLine("should be skipped"); + + break; + case 4: + sb.AppendFormat("Unskip track assignment {0} says that tracks ", descriptor.POINT); + + if(descriptor.Min > 0) + sb.AppendFormat("{0} ", descriptor.Min); + + if(descriptor.Sec > 0) + sb.AppendFormat("{0} ", descriptor.Sec); + + if(descriptor.Frame > 0) + sb.AppendFormat("{0} ", descriptor.Frame); + + if(descriptor.PMIN > 0) + sb.AppendFormat("{0} ", descriptor.PMIN); + + if(descriptor.PSEC > 0) + sb.AppendFormat("{0} ", descriptor.PSEC); + + if(descriptor.PFRAME > 0) + sb.AppendFormat("{0} ", descriptor.PFRAME); + + sb.AppendLine("should not be skipped"); + + break; + case 5: + sb.AppendFormat("Skip time interval assignment {0} says that from ", descriptor.POINT); + + if(descriptor.PHOUR > 0) + sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC, + descriptor.PFRAME, descriptor.PHOUR); + else + sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC, + descriptor.PFRAME); + + if(descriptor.PHOUR > 0) + sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec, + descriptor.Frame, descriptor.HOUR); + else + sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec, descriptor.Frame); + + sb.AppendLine("should be skipped"); + + break; + case 6: + sb.AppendFormat("Unskip time interval assignment {0} says that from ", descriptor.POINT); + + if(descriptor.PHOUR > 0) + sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC, + descriptor.PFRAME, descriptor.PHOUR); + else + sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} to ", descriptor.PMIN, descriptor.PSEC, + descriptor.PFRAME); + + if(descriptor.PHOUR > 0) + sb.AppendFormat("{3}:{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec, + descriptor.Frame, descriptor.HOUR); + else + sb.AppendFormat("{0:D2}:{1:D2}:{2:D2} ", descriptor.Min, descriptor.Sec, descriptor.Frame); + + sb.AppendLine("should not be skipped"); + + break; + default: + + sb.AppendFormat("ADR = {0}", descriptor.ADR).AppendLine(); + sb.AppendFormat("CONTROL = {0}", descriptor.CONTROL).AppendLine(); + sb.AppendFormat("TNO = {0}", descriptor.TNO).AppendLine(); + sb.AppendFormat("POINT = {0}", descriptor.POINT).AppendLine(); + sb.AppendFormat("Min = {0}", descriptor.Min).AppendLine(); + sb.AppendFormat("Sec = {0}", descriptor.Sec).AppendLine(); + sb.AppendFormat("Frame = {0}", descriptor.Frame).AppendLine(); + sb.AppendFormat("HOUR = {0}", descriptor.HOUR).AppendLine(); + sb.AppendFormat("PHOUR = {0}", descriptor.PHOUR).AppendLine(); + sb.AppendFormat("PMIN = {0}", descriptor.PMIN).AppendLine(); + sb.AppendFormat("PSEC = {0}", descriptor.PSEC).AppendLine(); + sb.AppendFormat("PFRAME = {0}", descriptor.PFRAME).AppendLine(); + + break; + } + } + + return sb.ToString(); + } + + public static string Prettify(byte[] CDPMAResponse) + { + CDPMA? decoded = Decode(CDPMAResponse); + + return Prettify(decoded); + } + + public struct CDPMA + { + /// Total size of returned session information minus this field + public ushort DataLength; + /// Reserved + public byte Reserved1; + /// Reserved + public byte Reserved2; + /// Track descriptors + public CDPMADescriptors[] PMADescriptors; + } + + public struct CDPMADescriptors + { + /// Byte 0 Reserved + public byte Reserved; + /// Byte 1, bits 7 to 4 Type of information in Q subchannel of block where this TOC entry was found + public byte ADR; + /// Byte 1, bits 3 to 0 Track attributes + public byte CONTROL; + /// Byte 2 + public byte TNO; + /// Byte 3 + public byte POINT; + /// Byte 4 + public byte Min; + /// Byte 5 + public byte Sec; + /// Byte 6 + public byte Frame; + /// Byte 7, bits 7 to 4 + public byte HOUR; + /// Byte 7, bits 3 to 0 + public byte PHOUR; + /// Byte 8 + public byte PMIN; + /// Byte 9 + public byte PSEC; + /// Byte 10 + public byte PFRAME; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/CD/Sector.cs b/Aaru.Decoders/CD/Sector.cs new file mode 100644 index 000000000..6ef3410bd --- /dev/null +++ b/Aaru.Decoders/CD/Sector.cs @@ -0,0 +1,476 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Sector.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes and descrambles CompactDisc sectors. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using Aaru.Checksums; + +namespace Aaru.Decoders.CD +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class Sector + { + public static readonly byte[] ScrambleTable = + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x60, 0x00, 0x28, + 0x00, 0x1E, 0x80, 0x08, 0x60, 0x06, 0xA8, 0x02, 0xFE, 0x81, 0x80, 0x60, 0x60, 0x28, 0x28, 0x1E, 0x9E, 0x88, + 0x68, 0x66, 0xAE, 0xAA, 0xFC, 0x7F, 0x01, 0xE0, 0x00, 0x48, 0x00, 0x36, 0x80, 0x16, 0xE0, 0x0E, 0xC8, 0x04, + 0x56, 0x83, 0x7E, 0xE1, 0xE0, 0x48, 0x48, 0x36, 0xB6, 0x96, 0xF6, 0xEE, 0xC6, 0xCC, 0x52, 0xD5, 0xFD, 0x9F, + 0x01, 0xA8, 0x00, 0x7E, 0x80, 0x20, 0x60, 0x18, 0x28, 0x0A, 0x9E, 0x87, 0x28, 0x62, 0x9E, 0xA9, 0xA8, 0x7E, + 0xFE, 0xA0, 0x40, 0x78, 0x30, 0x22, 0x94, 0x19, 0xAF, 0x4A, 0xFC, 0x37, 0x01, 0xD6, 0x80, 0x5E, 0xE0, 0x38, + 0x48, 0x12, 0xB6, 0x8D, 0xB6, 0xE5, 0xB6, 0xCB, 0x36, 0xD7, 0x56, 0xDE, 0xBE, 0xD8, 0x70, 0x5A, 0xA4, 0x3B, + 0x3B, 0x53, 0x53, 0x7D, 0xFD, 0xE1, 0x81, 0x88, 0x60, 0x66, 0xA8, 0x2A, 0xFE, 0x9F, 0x00, 0x68, 0x00, 0x2E, + 0x80, 0x1C, 0x60, 0x09, 0xE8, 0x06, 0xCE, 0x82, 0xD4, 0x61, 0x9F, 0x68, 0x68, 0x2E, 0xAE, 0x9C, 0x7C, 0x69, + 0xE1, 0xEE, 0xC8, 0x4C, 0x56, 0xB5, 0xFE, 0xF7, 0x00, 0x46, 0x80, 0x32, 0xE0, 0x15, 0x88, 0x0F, 0x26, 0x84, + 0x1A, 0xE3, 0x4B, 0x09, 0xF7, 0x46, 0xC6, 0xB2, 0xD2, 0xF5, 0x9D, 0x87, 0x29, 0xA2, 0x9E, 0xF9, 0xA8, 0x42, + 0xFE, 0xB1, 0x80, 0x74, 0x60, 0x27, 0x68, 0x1A, 0xAE, 0x8B, 0x3C, 0x67, 0x51, 0xEA, 0xBC, 0x4F, 0x31, 0xF4, + 0x14, 0x47, 0x4F, 0x72, 0xB4, 0x25, 0xB7, 0x5B, 0x36, 0xBB, 0x56, 0xF3, 0x7E, 0xC5, 0xE0, 0x53, 0x08, 0x3D, + 0xC6, 0x91, 0x92, 0xEC, 0x6D, 0x8D, 0xED, 0xA5, 0x8D, 0xBB, 0x25, 0xB3, 0x5B, 0x35, 0xFB, 0x57, 0x03, 0x7E, + 0x81, 0xE0, 0x60, 0x48, 0x28, 0x36, 0x9E, 0x96, 0xE8, 0x6E, 0xCE, 0xAC, 0x54, 0x7D, 0xFF, 0x61, 0x80, 0x28, + 0x60, 0x1E, 0xA8, 0x08, 0x7E, 0x86, 0xA0, 0x62, 0xF8, 0x29, 0x82, 0x9E, 0xE1, 0xA8, 0x48, 0x7E, 0xB6, 0xA0, + 0x76, 0xF8, 0x26, 0xC2, 0x9A, 0xD1, 0xAB, 0x1C, 0x7F, 0x49, 0xE0, 0x36, 0xC8, 0x16, 0xD6, 0x8E, 0xDE, 0xE4, + 0x58, 0x4B, 0x7A, 0xB7, 0x63, 0x36, 0xA9, 0xD6, 0xFE, 0xDE, 0xC0, 0x58, 0x50, 0x3A, 0xBC, 0x13, 0x31, 0xCD, + 0xD4, 0x55, 0x9F, 0x7F, 0x28, 0x20, 0x1E, 0x98, 0x08, 0x6A, 0x86, 0xAF, 0x22, 0xFC, 0x19, 0x81, 0xCA, 0xE0, + 0x57, 0x08, 0x3E, 0x86, 0x90, 0x62, 0xEC, 0x29, 0x8D, 0xDE, 0xE5, 0x98, 0x4B, 0x2A, 0xB7, 0x5F, 0x36, 0xB8, + 0x16, 0xF2, 0x8E, 0xC5, 0xA4, 0x53, 0x3B, 0x7D, 0xD3, 0x61, 0x9D, 0xE8, 0x69, 0x8E, 0xAE, 0xE4, 0x7C, 0x4B, + 0x61, 0xF7, 0x68, 0x46, 0xAE, 0xB2, 0xFC, 0x75, 0x81, 0xE7, 0x20, 0x4A, 0x98, 0x37, 0x2A, 0x96, 0x9F, 0x2E, + 0xE8, 0x1C, 0x4E, 0x89, 0xF4, 0x66, 0xC7, 0x6A, 0xD2, 0xAF, 0x1D, 0xBC, 0x09, 0xB1, 0xC6, 0xF4, 0x52, 0xC7, + 0x7D, 0x92, 0xA1, 0xAD, 0xB8, 0x7D, 0xB2, 0xA1, 0xB5, 0xB8, 0x77, 0x32, 0xA6, 0x95, 0xBA, 0xEF, 0x33, 0x0C, + 0x15, 0xC5, 0xCF, 0x13, 0x14, 0x0D, 0xCF, 0x45, 0x94, 0x33, 0x2F, 0x55, 0xDC, 0x3F, 0x19, 0xD0, 0x0A, 0xDC, + 0x07, 0x19, 0xC2, 0x8A, 0xD1, 0xA7, 0x1C, 0x7A, 0x89, 0xE3, 0x26, 0xC9, 0xDA, 0xD6, 0xDB, 0x1E, 0xDB, 0x48, + 0x5B, 0x76, 0xBB, 0x66, 0xF3, 0x6A, 0xC5, 0xEF, 0x13, 0x0C, 0x0D, 0xC5, 0xC5, 0x93, 0x13, 0x2D, 0xCD, 0xDD, + 0x95, 0x99, 0xAF, 0x2A, 0xFC, 0x1F, 0x01, 0xC8, 0x00, 0x56, 0x80, 0x3E, 0xE0, 0x10, 0x48, 0x0C, 0x36, 0x85, + 0xD6, 0xE3, 0x1E, 0xC9, 0xC8, 0x56, 0xD6, 0xBE, 0xDE, 0xF0, 0x58, 0x44, 0x3A, 0xB3, 0x53, 0x35, 0xFD, 0xD7, + 0x01, 0x9E, 0x80, 0x68, 0x60, 0x2E, 0xA8, 0x1C, 0x7E, 0x89, 0xE0, 0x66, 0xC8, 0x2A, 0xD6, 0x9F, 0x1E, 0xE8, + 0x08, 0x4E, 0x86, 0xB4, 0x62, 0xF7, 0x69, 0x86, 0xAE, 0xE2, 0xFC, 0x49, 0x81, 0xF6, 0xE0, 0x46, 0xC8, 0x32, + 0xD6, 0x95, 0x9E, 0xEF, 0x28, 0x4C, 0x1E, 0xB5, 0xC8, 0x77, 0x16, 0xA6, 0x8E, 0xFA, 0xE4, 0x43, 0x0B, 0x71, + 0xC7, 0x64, 0x52, 0xAB, 0x7D, 0xBF, 0x61, 0xB0, 0x28, 0x74, 0x1E, 0xA7, 0x48, 0x7A, 0xB6, 0xA3, 0x36, 0xF9, + 0xD6, 0xC2, 0xDE, 0xD1, 0x98, 0x5C, 0x6A, 0xB9, 0xEF, 0x32, 0xCC, 0x15, 0x95, 0xCF, 0x2F, 0x14, 0x1C, 0x0F, + 0x49, 0xC4, 0x36, 0xD3, 0x56, 0xDD, 0xFE, 0xD9, 0x80, 0x5A, 0xE0, 0x3B, 0x08, 0x13, 0x46, 0x8D, 0xF2, 0xE5, + 0x85, 0x8B, 0x23, 0x27, 0x59, 0xDA, 0xBA, 0xDB, 0x33, 0x1B, 0x55, 0xCB, 0x7F, 0x17, 0x60, 0x0E, 0xA8, 0x04, + 0x7E, 0x83, 0x60, 0x61, 0xE8, 0x28, 0x4E, 0x9E, 0xB4, 0x68, 0x77, 0x6E, 0xA6, 0xAC, 0x7A, 0xFD, 0xE3, 0x01, + 0x89, 0xC0, 0x66, 0xD0, 0x2A, 0xDC, 0x1F, 0x19, 0xC8, 0x0A, 0xD6, 0x87, 0x1E, 0xE2, 0x88, 0x49, 0xA6, 0xB6, + 0xFA, 0xF6, 0xC3, 0x06, 0xD1, 0xC2, 0xDC, 0x51, 0x99, 0xFC, 0x6A, 0xC1, 0xEF, 0x10, 0x4C, 0x0C, 0x35, 0xC5, + 0xD7, 0x13, 0x1E, 0x8D, 0xC8, 0x65, 0x96, 0xAB, 0x2E, 0xFF, 0x5C, 0x40, 0x39, 0xF0, 0x12, 0xC4, 0x0D, 0x93, + 0x45, 0xAD, 0xF3, 0x3D, 0x85, 0xD1, 0xA3, 0x1C, 0x79, 0xC9, 0xE2, 0xD6, 0xC9, 0x9E, 0xD6, 0xE8, 0x5E, 0xCE, + 0xB8, 0x54, 0x72, 0xBF, 0x65, 0xB0, 0x2B, 0x34, 0x1F, 0x57, 0x48, 0x3E, 0xB6, 0x90, 0x76, 0xEC, 0x26, 0xCD, + 0xDA, 0xD5, 0x9B, 0x1F, 0x2B, 0x48, 0x1F, 0x76, 0x88, 0x26, 0xE6, 0x9A, 0xCA, 0xEB, 0x17, 0x0F, 0x4E, 0x84, + 0x34, 0x63, 0x57, 0x69, 0xFE, 0xAE, 0xC0, 0x7C, 0x50, 0x21, 0xFC, 0x18, 0x41, 0xCA, 0xB0, 0x57, 0x34, 0x3E, + 0x97, 0x50, 0x6E, 0xBC, 0x2C, 0x71, 0xDD, 0xE4, 0x59, 0x8B, 0x7A, 0xE7, 0x63, 0x0A, 0xA9, 0xC7, 0x3E, 0xD2, + 0x90, 0x5D, 0xAC, 0x39, 0xBD, 0xD2, 0xF1, 0x9D, 0x84, 0x69, 0xA3, 0x6E, 0xF9, 0xEC, 0x42, 0xCD, 0xF1, 0x95, + 0x84, 0x6F, 0x23, 0x6C, 0x19, 0xED, 0xCA, 0xCD, 0x97, 0x15, 0xAE, 0x8F, 0x3C, 0x64, 0x11, 0xEB, 0x4C, 0x4F, + 0x75, 0xF4, 0x27, 0x07, 0x5A, 0x82, 0xBB, 0x21, 0xB3, 0x58, 0x75, 0xFA, 0xA7, 0x03, 0x3A, 0x81, 0xD3, 0x20, + 0x5D, 0xD8, 0x39, 0x9A, 0x92, 0xEB, 0x2D, 0x8F, 0x5D, 0xA4, 0x39, 0xBB, 0x52, 0xF3, 0x7D, 0x85, 0xE1, 0xA3, + 0x08, 0x79, 0xC6, 0xA2, 0xD2, 0xF9, 0x9D, 0x82, 0xE9, 0xA1, 0x8E, 0xF8, 0x64, 0x42, 0xAB, 0x71, 0xBF, 0x64, + 0x70, 0x2B, 0x64, 0x1F, 0x6B, 0x48, 0x2F, 0x76, 0x9C, 0x26, 0xE9, 0xDA, 0xCE, 0xDB, 0x14, 0x5B, 0x4F, 0x7B, + 0x74, 0x23, 0x67, 0x59, 0xEA, 0xBA, 0xCF, 0x33, 0x14, 0x15, 0xCF, 0x4F, 0x14, 0x34, 0x0F, 0x57, 0x44, 0x3E, + 0xB3, 0x50, 0x75, 0xFC, 0x27, 0x01, 0xDA, 0x80, 0x5B, 0x20, 0x3B, 0x58, 0x13, 0x7A, 0x8D, 0xE3, 0x25, 0x89, + 0xDB, 0x26, 0xDB, 0x5A, 0xDB, 0x7B, 0x1B, 0x63, 0x4B, 0x69, 0xF7, 0x6E, 0xC6, 0xAC, 0x52, 0xFD, 0xFD, 0x81, + 0x81, 0xA0, 0x60, 0x78, 0x28, 0x22, 0x9E, 0x99, 0xA8, 0x6A, 0xFE, 0xAF, 0x00, 0x7C, 0x00, 0x21, 0xC0, 0x18, + 0x50, 0x0A, 0xBC, 0x07, 0x31, 0xC2, 0x94, 0x51, 0xAF, 0x7C, 0x7C, 0x21, 0xE1, 0xD8, 0x48, 0x5A, 0xB6, 0xBB, + 0x36, 0xF3, 0x56, 0xC5, 0xFE, 0xD3, 0x00, 0x5D, 0xC0, 0x39, 0x90, 0x12, 0xEC, 0x0D, 0x8D, 0xC5, 0xA5, 0x93, + 0x3B, 0x2D, 0xD3, 0x5D, 0x9D, 0xF9, 0xA9, 0x82, 0xFE, 0xE1, 0x80, 0x48, 0x60, 0x36, 0xA8, 0x16, 0xFE, 0x8E, + 0xC0, 0x64, 0x50, 0x2B, 0x7C, 0x1F, 0x61, 0xC8, 0x28, 0x56, 0x9E, 0xBE, 0xE8, 0x70, 0x4E, 0xA4, 0x34, 0x7B, + 0x57, 0x63, 0x7E, 0xA9, 0xE0, 0x7E, 0xC8, 0x20, 0x56, 0x98, 0x3E, 0xEA, 0x90, 0x4F, 0x2C, 0x34, 0x1D, 0xD7, + 0x49, 0x9E, 0xB6, 0xE8, 0x76, 0xCE, 0xA6, 0xD4, 0x7A, 0xDF, 0x63, 0x18, 0x29, 0xCA, 0x9E, 0xD7, 0x28, 0x5E, + 0x9E, 0xB8, 0x68, 0x72, 0xAE, 0xA5, 0xBC, 0x7B, 0x31, 0xE3, 0x54, 0x49, 0xFF, 0x76, 0xC0, 0x26, 0xD0, 0x1A, + 0xDC, 0x0B, 0x19, 0xC7, 0x4A, 0xD2, 0xB7, 0x1D, 0xB6, 0x89, 0xB6, 0xE6, 0xF6, 0xCA, 0xC6, 0xD7, 0x12, 0xDE, + 0x8D, 0x98, 0x65, 0xAA, 0xAB, 0x3F, 0x3F, 0x50, 0x10, 0x3C, 0x0C, 0x11, 0xC5, 0xCC, 0x53, 0x15, 0xFD, 0xCF, + 0x01, 0x94, 0x00, 0x6F, 0x40, 0x2C, 0x30, 0x1D, 0xD4, 0x09, 0x9F, 0x46, 0xE8, 0x32, 0xCE, 0x95, 0x94, 0x6F, + 0x2F, 0x6C, 0x1C, 0x2D, 0xC9, 0xDD, 0x96, 0xD9, 0xAE, 0xDA, 0xFC, 0x5B, 0x01, 0xFB, 0x40, 0x43, 0x70, 0x31, + 0xE4, 0x14, 0x4B, 0x4F, 0x77, 0x74, 0x26, 0xA7, 0x5A, 0xFA, 0xBB, 0x03, 0x33, 0x41, 0xD5, 0xF0, 0x5F, 0x04, + 0x38, 0x03, 0x52, 0x81, 0xFD, 0xA0, 0x41, 0xB8, 0x30, 0x72, 0x94, 0x25, 0xAF, 0x5B, 0x3C, 0x3B, 0x51, 0xD3, + 0x7C, 0x5D, 0xE1, 0xF9, 0x88, 0x42, 0xE6, 0xB1, 0x8A, 0xF4, 0x67, 0x07, 0x6A, 0x82, 0xAF, 0x21, 0xBC, 0x18, + 0x71, 0xCA, 0xA4, 0x57, 0x3B, 0x7E, 0x93, 0x60, 0x6D, 0xE8, 0x2D, 0x8E, 0x9D, 0xA4, 0x69, 0xBB, 0x6E, 0xF3, + 0x6C, 0x45, 0xED, 0xF3, 0x0D, 0x85, 0xC5, 0xA3, 0x13, 0x39, 0xCD, 0xD2, 0xD5, 0x9D, 0x9F, 0x29, 0xA8, 0x1E, + 0xFE, 0x88, 0x40, 0x66, 0xB0, 0x2A, 0xF4, 0x1F, 0x07, 0x48, 0x02, 0xB6, 0x81, 0xB6, 0xE0, 0x76, 0xC8, 0x26, + 0xD6, 0x9A, 0xDE, 0xEB, 0x18, 0x4F, 0x4A, 0xB4, 0x37, 0x37, 0x56, 0x96, 0xBE, 0xEE, 0xF0, 0x4C, 0x44, 0x35, + 0xF3, 0x57, 0x05, 0xFE, 0x83, 0x00, 0x61, 0xC0, 0x28, 0x50, 0x1E, 0xBC, 0x08, 0x71, 0xC6, 0xA4, 0x52, 0xFB, + 0x7D, 0x83, 0x61, 0xA1, 0xE8, 0x78, 0x4E, 0xA2, 0xB4, 0x79, 0xB7, 0x62, 0xF6, 0xA9, 0x86, 0xFE, 0xE2, 0xC0, + 0x49, 0x90, 0x36, 0xEC, 0x16, 0xCD, 0xCE, 0xD5, 0x94, 0x5F, 0x2F, 0x78, 0x1C, 0x22, 0x89, 0xD9, 0xA6, 0xDA, + 0xFA, 0xDB, 0x03, 0x1B, 0x41, 0xCB, 0x70, 0x57, 0x64, 0x3E, 0xAB, 0x50, 0x7F, 0x7C, 0x20, 0x21, 0xD8, 0x18, + 0x5A, 0x8A, 0xBB, 0x27, 0x33, 0x5A, 0x95, 0xFB, 0x2F, 0x03, 0x5C, 0x01, 0xF9, 0xC0, 0x42, 0xD0, 0x31, 0x9C, + 0x14, 0x69, 0xCF, 0x6E, 0xD4, 0x2C, 0x5F, 0x5D, 0xF8, 0x39, 0x82, 0x92, 0xE1, 0xAD, 0x88, 0x7D, 0xA6, 0xA1, + 0xBA, 0xF8, 0x73, 0x02, 0xA5, 0xC1, 0xBB, 0x10, 0x73, 0x4C, 0x25, 0xF5, 0xDB, 0x07, 0x1B, 0x42, 0x8B, 0x71, + 0xA7, 0x64, 0x7A, 0xAB, 0x63, 0x3F, 0x69, 0xD0, 0x2E, 0xDC, 0x1C, 0x59, 0xC9, 0xFA, 0xD6, 0xC3, 0x1E, 0xD1, + 0xC8, 0x5C, 0x56, 0xB9, 0xFE, 0xF2, 0xC0, 0x45, 0x90, 0x33, 0x2C, 0x15, 0xDD, 0xCF, 0x19, 0x94, 0x0A, 0xEF, + 0x47, 0x0C, 0x32, 0x85, 0xD5, 0xA3, 0x1F, 0x39, 0xC8, 0x12, 0xD6, 0x8D, 0x9E, 0xE5, 0xA8, 0x4B, 0x3E, 0xB7, + 0x50, 0x76, 0xBC, 0x26, 0xF1, 0xDA, 0xC4, 0x5B, 0x13, 0x7B, 0x4D, 0xE3, 0x75, 0x89, 0xE7, 0x26, 0xCA, 0x9A, + 0xD7, 0x2B, 0x1E, 0x9F, 0x48, 0x68, 0x36, 0xAE, 0x96, 0xFC, 0x6E, 0xC1, 0xEC, 0x50, 0x4D, 0xFC, 0x35, 0x81, + 0xD7, 0x20, 0x5E, 0x98, 0x38, 0x6A, 0x92, 0xAF, 0x2D, 0xBC, 0x1D, 0xB1, 0xC9, 0xB4, 0x56, 0xF7, 0x7E, 0xC6, + 0xA0, 0x52, 0xF8, 0x3D, 0x82, 0x91, 0xA1, 0xAC, 0x78, 0x7D, 0xE2, 0xA1, 0x89, 0xB8, 0x66, 0xF2, 0xAA, 0xC5, + 0xBF, 0x13, 0x30, 0x0D, 0xD4, 0x05, 0x9F, 0x43, 0x28, 0x31, 0xDE, 0x94, 0x58, 0x6F, 0x7A, 0xAC, 0x23, 0x3D, + 0xD9, 0xD1, 0x9A, 0xDC, 0x6B, 0x19, 0xEF, 0x4A, 0xCC, 0x37, 0x15, 0xD6, 0x8F, 0x1E, 0xE4, 0x08, 0x4B, 0x46, + 0xB7, 0x72, 0xF6, 0xA5, 0x86, 0xFB, 0x22, 0xC3, 0x59, 0x91, 0xFA, 0xEC, 0x43, 0x0D, 0xF1, 0xC5, 0x84, 0x53, + 0x23, 0x7D, 0xD9, 0xE1, 0x9A, 0xC8, 0x6B, 0x16, 0xAF, 0x4E, 0xFC, 0x34, 0x41, 0xD7, 0x70, 0x5E, 0xA4, 0x38, + 0x7B, 0x52, 0xA3, 0x7D, 0xB9, 0xE1, 0xB2, 0xC8, 0x75, 0x96, 0xA7, 0x2E, 0xFA, 0x9C, 0x43, 0x29, 0xF1, 0xDE, + 0xC4, 0x58, 0x53, 0x7A, 0xBD, 0xE3, 0x31, 0x89, 0xD4, 0x66, 0xDF, 0x6A, 0xD8, 0x2F, 0x1A, 0x9C, 0x0B, 0x29, + 0xC7, 0x5E, 0xD2, 0xB8, 0x5D, 0xB2, 0xB9, 0xB5, 0xB2, 0xF7, 0x35, 0x86, 0x97, 0x22, 0xEE, 0x99, 0x8C, 0x6A, + 0xE5, 0xEF, 0x0B, 0x0C, 0x07, 0x45, 0xC2, 0xB3, 0x11, 0xB5, 0xCC, 0x77, 0x15, 0xE6, 0x8F, 0x0A, 0xE4, 0x07, + 0x0B, 0x42, 0x87, 0x71, 0xA2, 0xA4, 0x79, 0xBB, 0x62, 0xF3, 0x69, 0x85, 0xEE, 0xE3, 0x0C, 0x49, 0xC5, 0xF6, + 0xD3, 0x06, 0xDD, 0xC2, 0xD9, 0x91, 0x9A, 0xEC, 0x6B, 0x0D, 0xEF, 0x45, 0x8C, 0x33, 0x25, 0xD5, 0xDB, 0x1F, + 0x1B, 0x48, 0x0B, 0x76, 0x87, 0x66, 0xE2, 0xAA, 0xC9, 0xBF, 0x16, 0xF0, 0x0E, 0xC4, 0x04, 0x53, 0x43, 0x7D, + 0xF1, 0xE1, 0x84, 0x48, 0x63, 0x76, 0xA9, 0xE6, 0xFE, 0xCA, 0xC0, 0x57, 0x10, 0x3E, 0x8C, 0x10, 0x65, 0xCC, + 0x2B, 0x15, 0xDF, 0x4F, 0x18, 0x34, 0x0A, 0x97, 0x47, 0x2E, 0xB2, 0x9C, 0x75, 0xA9, 0xE7, 0x3E, 0xCA, 0x90, + 0x57, 0x2C, 0x3E, 0x9D, 0xD0, 0x69, 0x9C, 0x2E, 0xE9, 0xDC, 0x4E, 0xD9, 0xF4, 0x5A, 0xC7, 0x7B, 0x12, 0xA3, + 0x4D, 0xB9, 0xF5, 0xB2, 0xC7, 0x35, 0x92, 0x97, 0x2D, 0xAE, 0x9D, 0xBC, 0x69, 0xB1, 0xEE, 0xF4, 0x4C, 0x47, + 0x75, 0xF2, 0xA7, 0x05, 0xBA, 0x83, 0x33, 0x21, 0xD5, 0xD8, 0x5F, 0x1A, 0xB8, 0x0B, 0x32, 0x87, 0x55, 0xA2, + 0xBF, 0x39, 0xB0, 0x12, 0xF4, 0x0D, 0x87, 0x45, 0xA2, 0xB3, 0x39, 0xB5, 0xD2, 0xF7, 0x1D, 0x86, 0x89, 0xA2, + 0xE6, 0xF9, 0x8A, 0xC2, 0xE7, 0x11, 0x8A, 0x8C, 0x67, 0x25, 0xEA, 0x9B, 0x0F, 0x2B, 0x44, 0x1F, 0x73, 0x48, + 0x25, 0xF6, 0x9B, 0x06, 0xEB, 0x42, 0xCF, 0x71, 0x94, 0x24, 0x6F, 0x5B, 0x6C, 0x3B, 0x6D, 0xD3, 0x6D, 0x9D, + 0xED, 0xA9, 0x8D, 0xBE, 0xE5, 0xB0, 0x4B, 0x34, 0x37, 0x57, 0x56, 0xBE, 0xBE, 0xF0, 0x70, 0x44, 0x24, 0x33, + 0x5B, 0x55, 0xFB, 0x7F, 0x03, 0x60, 0x01, 0xE8, 0x00, 0x4E, 0x80, 0x34, 0x60, 0x17, 0x68, 0x0E, 0xAE, 0x84, + 0x7C, 0x63, 0x61, 0xE9, 0xE8, 0x4E, 0xCE, 0xB4, 0x54, 0x77, 0x7F, 0x66, 0xA0, 0x2A, 0xF8, 0x1F, 0x02, 0x88, + 0x01, 0xA6, 0x80, 0x7A, 0xE0, 0x23, 0x08, 0x19, 0xC6, 0x8A, 0xD2, 0xE7, 0x1D, 0x8A, 0x89, 0xA7, 0x26, 0xFA, + 0x9A, 0xC3, 0x2B, 0x11, 0xDF, 0x4C, 0x58, 0x35, 0xFA, 0x97, 0x03, 0x2E, 0x81, 0xDC, 0x60, 0x59, 0xE8, 0x3A, + 0xCE, 0x93, 0x14, 0x6D, 0xCF, 0x6D, 0x94, 0x2D, 0xAF, 0x5D, 0xBC, 0x39, 0xB1, 0xD2, 0xF4, 0x5D, 0x87, 0x79, + 0xA2, 0xA2, 0xF9, 0xB9, 0x82, 0xF2, 0xE1, 0x85, 0x88, 0x63, 0x26, 0xA9, 0xDA, 0xFE, 0xDB, 0x00, 0x5B, 0x40, + 0x3B, 0x70, 0x13, 0x64, 0x0D, 0xEB, 0x45, 0x8F, 0x73, 0x24, 0x25, 0xDB, 0x5B, 0x1B, 0x7B, 0x4B, 0x63, 0x77, + 0x69, 0xE6, 0xAE, 0xCA, 0xFC, 0x57, 0x01, 0xFE, 0x80, 0x40, 0x60, 0x30, 0x28, 0x14, 0x1E, 0x8F, 0x48, 0x64, + 0x36, 0xAB, 0x56, 0xFF, 0x7E, 0xC0, 0x20, 0x50, 0x18, 0x3C, 0x0A, 0x91, 0xC7, 0x2C, 0x52, 0x9D, 0xFD, 0xA9, + 0x81, 0xBE, 0xE0, 0x70, 0x48, 0x24, 0x36, 0x9B, 0x56, 0xEB, 0x7E, 0xCF, 0x60, 0x54, 0x28, 0x3F, 0x5E, 0x90, + 0x38, 0x6C, 0x12, 0xAD, 0xCD, 0xBD, 0x95, 0xB1, 0xAF, 0x34, 0x7C, 0x17, 0x61, 0xCE, 0xA8, 0x54, 0x7E, 0xBF, + 0x60, 0x70, 0x28, 0x24, 0x1E, 0x9B, 0x48, 0x6B, 0x76, 0xAF, 0x66, 0xFC, 0x2A, 0xC1, 0xDF, 0x10, 0x58, 0x0C, + 0x3A, 0x85, 0xD3, 0x23, 0x1D, 0xD9, 0xC9, 0x9A, 0xD6, 0xEB, 0x1E, 0xCF, 0x48, 0x54, 0x36, 0xBF, 0x56, 0xF0, + 0x3E, 0xC4, 0x10, 0x53, 0x4C, 0x3D, 0xF5, 0xD1, 0x87, 0x1C, 0x62, 0x89, 0xE9, 0xA6, 0xCE, 0xFA, 0xD4, 0x43, + 0x1F, 0x71, 0xC8, 0x24, 0x56, 0x9B, 0x7E, 0xEB, 0x60, 0x4F, 0x68, 0x34, 0x2E, 0x97, 0x5C, 0x6E, 0xB9, 0xEC, + 0x72, 0xCD, 0xE5, 0x95, 0x8B, 0x2F, 0x27, 0x5C, 0x1A, 0xB9, 0xCB, 0x32, 0xD7, 0x55, 0x9E, 0xBF, 0x28, 0x70, + 0x1E, 0xA4, 0x08, 0x7B, 0x46, 0xA3, 0x72, 0xF9, 0xE5, 0x82, 0xCB, 0x21, 0x97, 0x58, 0x6E, 0xBA, 0xAC, 0x73, + 0x3D, 0xE5, 0xD1, 0x8B, 0x1C, 0x67, 0x49, 0xEA, 0xB6, 0xCF, 0x36, 0xD4, 0x16, 0xDF, 0x4E, 0xD8, 0x34, 0x5A, + 0x97, 0x7B, 0x2E, 0xA3, 0x5C, 0x79, 0xF9, 0xE2, 0xC2, 0xC9, 0x91, 0x96, 0xEC, 0x6E, 0xCD, 0xEC, 0x55, 0x8D, + 0xFF, 0x25, 0x80, 0x1B, 0x20, 0x0B, 0x58, 0x07, 0x7A, 0x82, 0xA3, 0x21, 0xB9, 0xD8, 0x72, 0xDA, 0xA5, 0x9B, + 0x3B, 0x2B, 0x53, 0x5F, 0x7D, 0xF8, 0x21, 0x82, 0x98, 0x61, 0xAA, 0xA8, 0x7F, 0x3E, 0xA0, 0x10, 0x78, 0x0C, + 0x22, 0x85, 0xD9, 0xA3, 0x1A, 0xF9, 0xCB, 0x02, 0xD7, 0x41, 0x9E, 0xB0, 0x68, 0x74, 0x2E, 0xA7, 0x5C, 0x7A, + 0xB9, 0xE3, 0x32, 0xC9, 0xD5, 0x96, 0xDF, 0x2E, 0xD8, 0x1C, 0x5A, 0x89, 0xFB, 0x26, 0xC3, 0x5A, 0xD1, 0xFB, + 0x1C, 0x43, 0x49, 0xF1, 0xF6, 0xC4, 0x46, 0xD3, 0x72, 0xDD, 0xE5, 0x99 + }; + + public static readonly byte[] SyncMark = + { + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 + }; + + public static byte[] Scramble(byte[] sector) + { + if(sector == null || + sector.Length < 2352) + return sector; + + byte[] sync = new byte[12]; + Array.Copy(sector, 0, sync, 0, 12); + + if(!SyncMark.SequenceEqual(sync)) + return sector; + + byte[] scrambled = new byte[sector.Length]; + + for(int i = 0; i < 2352; i++) + scrambled[i] = (byte)(sector[i] ^ ScrambleTable[i]); + + if(sector.Length <= 2352) + return scrambled; + + for(int i = 2352; i < sector.Length; i++) + scrambled[i] = sector[i]; + + return scrambled; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte[] GetUserData(byte[] data, bool interleaved = false, byte fileNumber = 0) + { + switch(data.Length) + { + case 2352 when data[0] != 0x00 || data[1] != 0xFF || data[2] != 0xFF || data[3] != 0xFF || + data[4] != 0xFF || data[5] != 0xFF || data[6] != 0xFF || data[7] != 0xFF || + data[8] != 0xFF || data[9] != 0xFF || data[10] != 0xFF || data[11] != 0x00: return data; + case 2352: + switch(data[15]) + { + case 0: return new byte[2048]; + case 1: + byte[] sector = new byte[2048]; + Array.Copy(data, 16, sector, 0, 2048); + + return sector; + case 2: return GetUserDataFromMode2(data, interleaved, fileNumber); + default: return data; + } + case 2336: return GetUserDataFromMode2(data, interleaved, fileNumber); + default: return data; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte[] GetUserDataFromMode2(byte[] data, bool interleaved = false, byte fileNumber = 0) + { + if(data.Length != 2352 && + data.Length != 2336) + return data; + + int pos = 0; + + if(data.Length == 2352) + { + if(data[0] != 0x00 || + data[1] != 0xFF || + data[2] != 0xFF || + data[3] != 0xFF || + data[4] != 0xFF || + data[5] != 0xFF || + data[6] != 0xFF || + data[7] != 0xFF || + data[8] != 0xFF || + data[9] != 0xFF || + data[10] != 0xFF || + data[11] != 0x00 || + data[15] != 0x02) + return data; + + pos = 16; + } + + // This is not the sector you are looking for + if(interleaved && data[pos] != fileNumber) + return null; + + int len = (data[pos + 2] & 0x20) == 0x20 ? 2324 : 2048; + pos += 8; + + byte[] sector = new byte[len]; + Array.Copy(data, pos, sector, 0, len); + + return sector; + } + + public static string Prettify(byte[] buffer) + { + if(buffer is null || + buffer.Length <= 0) + return null; + + if(buffer[0] != 0x00 || + buffer[1] != 0xFF || + buffer[2] != 0xFF || + buffer[3] != 0xFF || + buffer[4] != 0xFF || + buffer[5] != 0xFF || + buffer[6] != 0xFF || + buffer[7] != 0xFF || + buffer[8] != 0xFF || + buffer[9] != 0xFF || + buffer[10] != 0xFF || + buffer[11] != 0x00) + return "CD sector."; + + var sb = new StringBuilder(); + + sb.AppendLine("CD-ROM sector."); + + byte min = buffer[12]; + byte sec = buffer[13]; + byte frame = buffer[14]; + int lba = 0; + bool moreThan90 = false; + + if(min > 0x90) + { + lba += 405000; + min -= 0x90; + moreThan90 = true; + } + + lba += (((min >> 4) * 10) + (min & 0x0F)) * 75 * 60; + lba += (((sec >> 4) * 10) + (sec & 0x0F)) * 75; + lba += ((frame >> 4) * 10) + (frame & 0x0F); + lba -= 150; + + if(moreThan90) + min += 0x90; + + sb.AppendFormat("Position {0:X2}:{1:X2}:{2:X2} (LBA {3})", min, sec, frame, lba).AppendLine(); + + switch(buffer[15] & 0x03) + { + case 0: + sb.AppendLine("Mode 0."); + + break; + case 1: + sb.AppendLine("Mode 1."); + + break; + case 2: + sb.AppendLine("Mode 2."); + + break; + case 3: + sb.AppendLine("Invalid mode 0."); + + break; + } + + switch((buffer[15] & 0xE0) >> 5) + { + case 0: + sb.AppendLine("User data block"); + + break; + case 1: + sb.AppendLine("Fourth run-in block"); + + break; + case 2: + sb.AppendLine("Third run-in block"); + + break; + case 3: + sb.AppendLine("Second run-in block"); + + break; + case 4: + sb.AppendLine("First run-in block"); + + break; + case 5: + sb.AppendLine("Link block"); + + break; + case 6: + sb.AppendLine("Second run-out block"); + + break; + case 7: + sb.AppendLine("First run-out block"); + + break; + } + + CdChecksums.CheckCdSector(buffer, out bool? correctEccP, out bool? correctEccQ, out bool? correctEdc); + + bool empty = true; + + switch(buffer[15] & 0x03) + { + case 0: + + for(int i = 16; i < 2352; i++) + { + if(buffer[i] != 0x00) + { + empty = false; + + break; + } + } + + sb.AppendLine(empty ? "Correct sector contents." : "Incorrect sector contents."); + + break; + case 1: + sb.AppendLine(correctEdc == true ? "Correct EDC." : "Incorrect EDC."); + sb.AppendLine(correctEccP == true ? "Correct ECC P." : "Incorrect ECC P."); + sb.AppendLine(correctEccQ == true ? "Correct ECC Q." : "Incorrect ECC Q."); + + for(int i = 2068; i < 2076; i++) + { + if(buffer[i] != 0x00) + { + empty = false; + + break; + } + } + + sb.AppendLine(empty ? "Correct zero fill." : "Incorrect zero fill."); + + break; + case 2: + if(buffer[16] != buffer[20] || + buffer[17] != buffer[21] || + buffer[18] != buffer[22] || + buffer[19] != buffer[23]) + { + sb.AppendLine("Subheader copies differ."); + sb.AppendLine(correctEdc == true ? "Correct EDC." : "Incorrect EDC."); + sb.AppendLine(correctEccP == true ? "Correct ECC P." : "Incorrect ECC P."); + sb.AppendLine(correctEccQ == true ? "Correct ECC Q." : "Incorrect ECC Q."); + + break; + } + + sb.AppendFormat("File number: {0}", buffer[16]).AppendLine(); + sb.AppendFormat("Channel number: {0}", buffer[17]).AppendLine(); + sb.AppendFormat("Coding information number: {0}", buffer[19]).AppendLine(); + + if((buffer[18] & 0x80) == 0x80) + sb.AppendLine("End of file."); + + if((buffer[18] & 0x40) == 0x40) + sb.AppendLine("Real-time block."); + + sb.AppendLine((buffer[18] & 0x20) == 0x20 ? "Form 2." : "Form 1."); + + if((buffer[18] & 0x10) == 0x10) + sb.AppendLine("Trigger block."); + + if((buffer[18] & 0x08) == 0x08) + sb.AppendLine("Data block."); + + if((buffer[18] & 0x04) == 0x04) + sb.AppendLine("Audio block."); + + if((buffer[18] & 0x02) == 0x02) + sb.AppendLine("Video block."); + + if((buffer[18] & 0x01) == 0x01) + sb.AppendLine("End of record."); + + if((buffer[18] & 0x20) != 0x20) + { + sb.AppendLine(correctEccP == true ? "Correct ECC P." : "Incorrect ECC P."); + sb.AppendLine(correctEccQ == true ? "Correct ECC Q." : "Incorrect ECC Q."); + } + + sb.AppendLine(correctEdc == true ? "Correct EDC." : "Incorrect EDC."); + + break; + } + + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/CD/SectorBuilder.cs b/Aaru.Decoders/CD/SectorBuilder.cs new file mode 100644 index 000000000..e6e87f52b --- /dev/null +++ b/Aaru.Decoders/CD/SectorBuilder.cs @@ -0,0 +1,238 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : SectorBuilder.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using Aaru.CommonTypes.Enums; + +namespace Aaru.Decoders.CD +{ + public class SectorBuilder + { + readonly byte[] _eccBTable; + readonly byte[] _eccFTable; + readonly uint[] _edcTable; + + public SectorBuilder() + { + _eccFTable = new byte[256]; + _eccBTable = new byte[256]; + _edcTable = new uint[256]; + + for(uint i = 0; i < 256; i++) + { + uint edc = i; + uint j = (uint)((i << 1) ^ ((i & 0x80) == 0x80 ? 0x11D : 0)); + _eccFTable[i] = (byte)j; + _eccBTable[i ^ j] = (byte)i; + + for(j = 0; j < 8; j++) + edc = (edc >> 1) ^ ((edc & 1) > 0 ? 0xD8018001 : 0); + + _edcTable[i] = edc; + } + } + + static (byte minute, byte second, byte frame) LbaToMsf(long pos) => + ((byte)((pos + 150) / 75 / 60), (byte)((pos + 150) / 75 % 60), (byte)((pos + 150) % 75)); + + public void ReconstructPrefix(ref byte[] sector, // must point to a full 2352-byte sector + TrackType type, long lba) + { + // + // Sync + // + sector[0x000] = 0x00; + sector[0x001] = 0xFF; + sector[0x002] = 0xFF; + sector[0x003] = 0xFF; + sector[0x004] = 0xFF; + sector[0x005] = 0xFF; + sector[0x006] = 0xFF; + sector[0x007] = 0xFF; + sector[0x008] = 0xFF; + sector[0x009] = 0xFF; + sector[0x00A] = 0xFF; + sector[0x00B] = 0x00; + + (byte minute, byte second, byte frame) msf = LbaToMsf(lba); + + sector[0x00C] = (byte)(((msf.minute / 10) << 4) + (msf.minute % 10)); + sector[0x00D] = (byte)(((msf.second / 10) << 4) + (msf.second % 10)); + sector[0x00E] = (byte)(((msf.frame / 10) << 4) + (msf.frame % 10)); + + switch(type) + { + case TrackType.CdMode1: + // + // Mode + // + sector[0x00F] = 0x01; + + break; + case TrackType.CdMode2Form1: + case TrackType.CdMode2Form2: + case TrackType.CdMode2Formless: + // + // Mode + // + sector[0x00F] = 0x02; + + // + // Flags + // + sector[0x010] = sector[0x014]; + sector[0x011] = sector[0x015]; + sector[0x012] = sector[0x016]; + sector[0x013] = sector[0x017]; + + break; + default: return; + } + } + + uint ComputeEdc(uint edc, byte[] src, int size, int srcOffset = 0) + { + int pos = srcOffset; + + for(; size > 0; size--) + edc = (edc >> 8) ^ _edcTable[(edc ^ src[pos++]) & 0xFF]; + + return edc; + } + + public void ReconstructEcc(ref byte[] sector, // must point to a full 2352-byte sector + TrackType type) + { + byte[] computedEdc; + + switch(type) + { + // + // Compute EDC + // + case TrackType.CdMode1: + computedEdc = BitConverter.GetBytes(ComputeEdc(0, sector, 0x810)); + sector[0x810] = computedEdc[0]; + sector[0x811] = computedEdc[1]; + sector[0x812] = computedEdc[2]; + sector[0x813] = computedEdc[3]; + + break; + case TrackType.CdMode2Form1: + computedEdc = BitConverter.GetBytes(ComputeEdc(0, sector, 0x808, 0x10)); + sector[0x818] = computedEdc[0]; + sector[0x819] = computedEdc[1]; + sector[0x81A] = computedEdc[2]; + sector[0x81B] = computedEdc[3]; + + break; + case TrackType.CdMode2Form2: + computedEdc = BitConverter.GetBytes(ComputeEdc(0, sector, 0x91C, 0x10)); + sector[0x92C] = computedEdc[0]; + sector[0x92D] = computedEdc[1]; + sector[0x92E] = computedEdc[2]; + sector[0x92F] = computedEdc[3]; + + break; + default: return; + } + + byte[] zeroaddress = new byte[4]; + + switch(type) + { + // + // Compute ECC + // + case TrackType.CdMode1: + // + // Reserved + // + sector[0x814] = 0x00; + sector[0x815] = 0x00; + sector[0x816] = 0x00; + sector[0x817] = 0x00; + sector[0x818] = 0x00; + sector[0x819] = 0x00; + sector[0x81A] = 0x00; + sector[0x81B] = 0x00; + EccWriteSector(sector, sector, ref sector, 0xC, 0x10, 0x81C); + + break; + case TrackType.CdMode2Form1: + EccWriteSector(zeroaddress, sector, ref sector, 0, 0x10, 0x81C); + + break; + default: return; + } + + // + // Done + // + } + + void EccWriteSector(byte[] address, byte[] data, ref byte[] ecc, int addressOffset, int dataOffset, + int eccOffset) + { + WriteEcc(address, data, 86, 24, 2, 86, ref ecc, addressOffset, dataOffset, eccOffset); // P + WriteEcc(address, data, 52, 43, 86, 88, ref ecc, addressOffset, dataOffset, eccOffset + 0xAC); // Q + } + + void WriteEcc(byte[] address, byte[] data, uint majorCount, uint minorCount, uint majorMult, uint minorInc, + ref byte[] ecc, int addressOffset, int dataOffset, int eccOffset) + { + uint size = majorCount * minorCount; + uint major; + + for(major = 0; major < majorCount; major++) + { + uint idx = ((major >> 1) * majorMult) + (major & 1); + byte eccA = 0; + byte eccB = 0; + uint minor; + + for(minor = 0; minor < minorCount; minor++) + { + byte temp = idx < 4 ? address[idx + addressOffset] : data[idx + dataOffset - 4]; + idx += minorInc; + + if(idx >= size) + idx -= size; + + eccA ^= temp; + eccB ^= temp; + eccA = _eccFTable[eccA]; + } + + eccA = _eccBTable[_eccFTable[eccA] ^ eccB]; + ecc[major + eccOffset] = eccA; + ecc[major + majorCount + eccOffset] = (byte)(eccA ^ eccB); + } + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/CD/Session.cs b/Aaru.Decoders/CD/Session.cs new file mode 100644 index 000000000..a4a06272c --- /dev/null +++ b/Aaru.Decoders/CD/Session.cs @@ -0,0 +1,223 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Session.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes CD session structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Console; +using Aaru.Helpers; + +namespace Aaru.Decoders.CD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 T10/1836-D revision 2g + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class Session + { + public static CDSessionInfo? Decode(byte[] CDSessionInfoResponse) + { + if(CDSessionInfoResponse == null || + CDSessionInfoResponse.Length <= 4) + return null; + + var decoded = new CDSessionInfo + { + DataLength = BigEndianBitConverter.ToUInt16(CDSessionInfoResponse, 0), + FirstCompleteSession = CDSessionInfoResponse[2], + LastCompleteSession = CDSessionInfoResponse[3] + }; + + decoded.TrackDescriptors = new TrackDataDescriptor[(decoded.DataLength - 2) / 8]; + + if(decoded.DataLength + 2 != CDSessionInfoResponse.Length) + { + AaruConsole.DebugWriteLine("CD Session Info decoder", + "Expected CDSessionInfo size ({0} bytes) is not received size ({1} bytes), not decoding", + decoded.DataLength + 2, CDSessionInfoResponse.Length); + + return null; + } + + for(int i = 0; i < (decoded.DataLength - 2) / 8; i++) + { + decoded.TrackDescriptors[i].Reserved1 = CDSessionInfoResponse[0 + (i * 8) + 4]; + decoded.TrackDescriptors[i].ADR = (byte)((CDSessionInfoResponse[1 + (i * 8) + 4] & 0xF0) >> 4); + decoded.TrackDescriptors[i].CONTROL = (byte)(CDSessionInfoResponse[1 + (i * 8) + 4] & 0x0F); + decoded.TrackDescriptors[i].TrackNumber = CDSessionInfoResponse[2 + (i * 8) + 4]; + decoded.TrackDescriptors[i].Reserved2 = CDSessionInfoResponse[3 + (i * 8) + 4]; + + decoded.TrackDescriptors[i].TrackStartAddress = + BigEndianBitConverter.ToUInt32(CDSessionInfoResponse, 4 + (i * 8) + 4); + } + + return decoded; + } + + public static string Prettify(CDSessionInfo? CDSessionInfoResponse) + { + if(CDSessionInfoResponse == null) + return null; + + CDSessionInfo response = CDSessionInfoResponse.Value; + + var sb = new StringBuilder(); + + sb.AppendFormat("First complete session number: {0}", response.FirstCompleteSession).AppendLine(); + sb.AppendFormat("Last complete session number: {0}", response.LastCompleteSession).AppendLine(); + + foreach(TrackDataDescriptor descriptor in response.TrackDescriptors) + { + sb.AppendFormat("First track number in last complete session: {0}", descriptor.TrackNumber). + AppendLine(); + + sb.AppendFormat("Track starts at LBA {0}, or MSF {1:X2}:{2:X2}:{3:X2}", descriptor.TrackStartAddress, + (descriptor.TrackStartAddress & 0x0000FF00) >> 8, + (descriptor.TrackStartAddress & 0x00FF0000) >> 16, + (descriptor.TrackStartAddress & 0xFF000000) >> 24).AppendLine(); + + switch((TocAdr)descriptor.ADR) + { + case TocAdr.NoInformation: + sb.AppendLine("Q subchannel mode not given"); + + break; + case TocAdr.CurrentPosition: + sb.AppendLine("Q subchannel stores current position"); + + break; + case TocAdr.ISRC: + sb.AppendLine("Q subchannel stores ISRC"); + + break; + case TocAdr.MediaCatalogNumber: + sb.AppendLine("Q subchannel stores media catalog number"); + + break; + } + + if((descriptor.CONTROL & (byte)TocControl.ReservedMask) == (byte)TocControl.ReservedMask) + sb.AppendFormat("Reserved flags 0x{0:X2} set", descriptor.CONTROL).AppendLine(); + else + { + switch((TocControl)(descriptor.CONTROL & 0x0D)) + { + case TocControl.TwoChanNoPreEmph: + sb.AppendLine("Stereo audio track with no pre-emphasis"); + + break; + case TocControl.TwoChanPreEmph: + sb.AppendLine("Stereo audio track with 50/15 μs pre-emphasis"); + + break; + case TocControl.FourChanNoPreEmph: + sb.AppendLine("Quadraphonic audio track with no pre-emphasis"); + + break; + case TocControl.FourChanPreEmph: + sb.AppendLine("Stereo audio track with 50/15 μs pre-emphasis"); + + break; + case TocControl.DataTrack: + sb.AppendLine("Data track, recorded uninterrupted"); + + break; + case TocControl.DataTrackIncremental: + sb.AppendLine("Data track, recorded incrementally"); + + break; + } + + sb.AppendLine((descriptor.CONTROL & (byte)TocControl.CopyPermissionMask) == + (byte)TocControl.CopyPermissionMask ? "Digital copy of track is permitted" + : "Digital copy of track is prohibited"); + + #if DEBUG + if(descriptor.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", descriptor.Reserved1).AppendLine(); + + if(descriptor.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", descriptor.Reserved2).AppendLine(); + #endif + + sb.AppendLine(); + } + } + + return sb.ToString(); + } + + public static string Prettify(byte[] CDSessionInfoResponse) + { + CDSessionInfo? decoded = Decode(CDSessionInfoResponse); + + return Prettify(decoded); + } + + public struct CDSessionInfo + { + /// Total size of returned session information minus this field + public ushort DataLength; + /// First track number in hex + public byte FirstCompleteSession; + /// Last track number in hex + public byte LastCompleteSession; + /// Track descriptors + public TrackDataDescriptor[] TrackDescriptors; + } + + public struct TrackDataDescriptor + { + /// Byte 0 Reserved + public byte Reserved1; + /// Byte 1, bits 7 to 4 Type of information in Q subchannel of block where this TOC entry was found + public byte ADR; + /// Byte 1, bits 3 to 0 Track attributes + public byte CONTROL; + /// Byte 2 First track number in last complete session + public byte TrackNumber; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to 7 First track number in last complete session start address in LBA or in MSF + public uint TrackStartAddress; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/CD/Subchannel.cs b/Aaru.Decoders/CD/Subchannel.cs new file mode 100644 index 000000000..a72699602 --- /dev/null +++ b/Aaru.Decoders/CD/Subchannel.cs @@ -0,0 +1,594 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Subchannel.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using Aaru.Checksums; + +namespace Aaru.Decoders.CD +{ + public static class Subchannel + { + static readonly string[] _isrcTable = + { + // 0x00 + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "", "", "", "", "", "", + + // 0x10 + "", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", + + // 0x20 + "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "", "", "", "", "", + + // 0x30 + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" + }; + + public static void BinaryToBcdQ(byte[] q) + { + if((q[0] & 0xF) == 1 || + (q[0] & 0xF) == 5) + { + q[1] = (byte)(((q[1] / 10) << 4) + (q[1] % 10)); + q[2] = (byte)(((q[2] / 10) << 4) + (q[2] % 10)); + q[3] = (byte)(((q[3] / 10) << 4) + (q[3] % 10)); + q[4] = (byte)(((q[4] / 10) << 4) + (q[4] % 10)); + q[5] = (byte)(((q[5] / 10) << 4) + (q[5] % 10)); + q[6] = (byte)(((q[6] / 10) << 4) + (q[6] % 10)); + q[7] = (byte)(((q[7] / 10) << 4) + (q[7] % 10)); + q[8] = (byte)(((q[8] / 10) << 4) + (q[8] % 10)); + } + + q[9] = (byte)(((q[9] / 10) << 4) + (q[9] % 10)); + } + + public static void BcdToBinaryQ(byte[] q) + { + if((q[0] & 0xF) == 1 || + (q[0] & 0xF) == 5) + { + q[1] = (byte)((q[1] / 16 * 10) + (q[1] & 0x0F)); + q[2] = (byte)((q[2] / 16 * 10) + (q[2] & 0x0F)); + q[3] = (byte)((q[3] / 16 * 10) + (q[3] & 0x0F)); + q[4] = (byte)((q[4] / 16 * 10) + (q[4] & 0x0F)); + q[5] = (byte)((q[5] / 16 * 10) + (q[5] & 0x0F)); + q[6] = (byte)((q[6] / 16 * 10) + (q[6] & 0x0F)); + q[7] = (byte)((q[7] / 16 * 10) + (q[7] & 0x0F)); + q[8] = (byte)((q[8] / 16 * 10) + (q[8] & 0x0F)); + } + + q[9] = (byte)((q[9] / 16 * 10) + (q[9] & 0x0F)); + } + + public static byte[] ConvertQToRaw(byte[] subchannel) + { + int pos = 0; + byte[] subBuf = new byte[subchannel.Length * 6]; + + for(int i = 0; i < subchannel.Length; i += 16) + { + // P + if((subchannel[i + 15] & 0x80) <= 0) + { + pos += 12; + } + else + { + subBuf[pos++] = 0xFF; + subBuf[pos++] = 0xFF; + subBuf[pos++] = 0xFF; + subBuf[pos++] = 0xFF; + subBuf[pos++] = 0xFF; + subBuf[pos++] = 0xFF; + subBuf[pos++] = 0xFF; + subBuf[pos++] = 0xFF; + subBuf[pos++] = 0xFF; + subBuf[pos++] = 0xFF; + subBuf[pos++] = 0xFF; + subBuf[pos++] = 0xFF; + } + + // Q + subBuf[pos++] = subchannel[i + 0]; + subBuf[pos++] = subchannel[i + 1]; + subBuf[pos++] = subchannel[i + 2]; + subBuf[pos++] = subchannel[i + 3]; + subBuf[pos++] = subchannel[i + 4]; + subBuf[pos++] = subchannel[i + 5]; + subBuf[pos++] = subchannel[i + 6]; + subBuf[pos++] = subchannel[i + 7]; + subBuf[pos++] = subchannel[i + 8]; + subBuf[pos++] = subchannel[i + 9]; + subBuf[pos++] = subchannel[i + 10]; + subBuf[pos++] = subchannel[i + 11]; + + // R to W + pos += 72; + } + + return Interleave(subBuf); + } + + public static byte[] Interleave(byte[] subchannel) + { + byte[] subBuf = new byte[subchannel.Length]; + + int outPos = 0; + + for(int inPos = 0; inPos < subchannel.Length; inPos += 96) + { + for(int i = 0; i < 12; i++) + { + // P + subBuf[outPos + 0] += (byte)(subchannel[inPos + i + 0] & 0x80); + subBuf[outPos + 1] += (byte)((subchannel[inPos + i + 0] & 0x40) << 1); + subBuf[outPos + 2] += (byte)((subchannel[inPos + i + 0] & 0x20) << 2); + subBuf[outPos + 3] += (byte)((subchannel[inPos + i + 0] & 0x10) << 3); + subBuf[outPos + 4] += (byte)((subchannel[inPos + i + 0] & 0x08) << 4); + subBuf[outPos + 5] += (byte)((subchannel[inPos + i + 0] & 0x04) << 5); + subBuf[outPos + 6] += (byte)((subchannel[inPos + i + 0] & 0x02) << 6); + subBuf[outPos + 7] += (byte)((subchannel[inPos + i + 0] & 0x01) << 7); + + // Q + subBuf[outPos + 0] += (byte)((subchannel[inPos + i + 12] & 0x80) >> 1); + subBuf[outPos + 1] += (byte)(subchannel[inPos + i + 12] & 0x40); + subBuf[outPos + 2] += (byte)((subchannel[inPos + i + 12] & 0x20) << 1); + subBuf[outPos + 3] += (byte)((subchannel[inPos + i + 12] & 0x10) << 2); + subBuf[outPos + 4] += (byte)((subchannel[inPos + i + 12] & 0x08) << 3); + subBuf[outPos + 5] += (byte)((subchannel[inPos + i + 12] & 0x04) << 4); + subBuf[outPos + 6] += (byte)((subchannel[inPos + i + 12] & 0x02) << 5); + subBuf[outPos + 7] += (byte)((subchannel[inPos + i + 12] & 0x01) << 6); + + // R + subBuf[outPos + 0] += (byte)((subchannel[inPos + i + 24] & 0x80) >> 2); + subBuf[outPos + 1] += (byte)((subchannel[inPos + i + 24] & 0x40) >> 1); + subBuf[outPos + 2] += (byte)(subchannel[inPos + i + 24] & 0x20); + subBuf[outPos + 3] += (byte)((subchannel[inPos + i + 24] & 0x10) << 1); + subBuf[outPos + 4] += (byte)((subchannel[inPos + i + 24] & 0x08) << 2); + subBuf[outPos + 5] += (byte)((subchannel[inPos + i + 24] & 0x04) << 3); + subBuf[outPos + 6] += (byte)((subchannel[inPos + i + 24] & 0x02) << 4); + subBuf[outPos + 7] += (byte)((subchannel[inPos + i + 24] & 0x01) << 5); + + // S + subBuf[outPos + 0] += (byte)((subchannel[inPos + i + 36] & 0x80) >> 3); + subBuf[outPos + 1] += (byte)((subchannel[inPos + i + 36] & 0x40) >> 2); + subBuf[outPos + 2] += (byte)((subchannel[inPos + i + 36] & 0x20) >> 1); + subBuf[outPos + 3] += (byte)(subchannel[inPos + i + 36] & 0x10); + subBuf[outPos + 4] += (byte)((subchannel[inPos + i + 36] & 0x08) << 1); + subBuf[outPos + 5] += (byte)((subchannel[inPos + i + 36] & 0x04) << 2); + subBuf[outPos + 6] += (byte)((subchannel[inPos + i + 36] & 0x02) << 3); + subBuf[outPos + 7] += (byte)((subchannel[inPos + i + 36] & 0x01) << 4); + + // T + subBuf[outPos + 0] += (byte)((subchannel[inPos + i + 48] & 0x80) >> 4); + subBuf[outPos + 1] += (byte)((subchannel[inPos + i + 48] & 0x40) >> 3); + subBuf[outPos + 2] += (byte)((subchannel[inPos + i + 48] & 0x20) >> 2); + subBuf[outPos + 3] += (byte)((subchannel[inPos + i + 48] & 0x10) >> 1); + subBuf[outPos + 4] += (byte)(subchannel[inPos + i + 48] & 0x08); + subBuf[outPos + 5] += (byte)((subchannel[inPos + i + 48] & 0x04) << 1); + subBuf[outPos + 6] += (byte)((subchannel[inPos + i + 48] & 0x02) << 2); + subBuf[outPos + 7] += (byte)((subchannel[inPos + i + 48] & 0x01) << 3); + + // U + subBuf[outPos + 0] += (byte)((subchannel[inPos + i + 60] & 0x80) >> 5); + subBuf[outPos + 1] += (byte)((subchannel[inPos + i + 60] & 0x40) >> 4); + subBuf[outPos + 2] += (byte)((subchannel[inPos + i + 60] & 0x20) >> 3); + subBuf[outPos + 3] += (byte)((subchannel[inPos + i + 60] & 0x10) >> 2); + subBuf[outPos + 4] += (byte)((subchannel[inPos + i + 60] & 0x08) >> 1); + subBuf[outPos + 5] += (byte)(subchannel[inPos + i + 60] & 0x04); + subBuf[outPos + 6] += (byte)((subchannel[inPos + i + 60] & 0x02) << 1); + subBuf[outPos + 7] += (byte)((subchannel[inPos + i + 60] & 0x01) << 2); + + // V + subBuf[outPos + 0] += (byte)((subchannel[inPos + i + 72] & 0x80) >> 6); + subBuf[outPos + 1] += (byte)((subchannel[inPos + i + 72] & 0x40) >> 5); + subBuf[outPos + 2] += (byte)((subchannel[inPos + i + 72] & 0x20) >> 4); + subBuf[outPos + 3] += (byte)((subchannel[inPos + i + 72] & 0x10) >> 3); + subBuf[outPos + 4] += (byte)((subchannel[inPos + i + 72] & 0x08) >> 2); + subBuf[outPos + 5] += (byte)((subchannel[inPos + i + 72] & 0x04) >> 1); + subBuf[outPos + 6] += (byte)(subchannel[inPos + i + 72] & 0x02); + subBuf[outPos + 7] += (byte)((subchannel[inPos + i + 72] & 0x01) << 1); + + // W + subBuf[outPos + 0] += (byte)((subchannel[inPos + i + 84] & 0x80) >> 7); + subBuf[outPos + 1] += (byte)((subchannel[inPos + i + 84] & 0x40) >> 6); + subBuf[outPos + 2] += (byte)((subchannel[inPos + i + 84] & 0x20) >> 5); + subBuf[outPos + 3] += (byte)((subchannel[inPos + i + 84] & 0x10) >> 4); + subBuf[outPos + 4] += (byte)((subchannel[inPos + i + 84] & 0x08) >> 3); + subBuf[outPos + 5] += (byte)((subchannel[inPos + i + 84] & 0x04) >> 2); + subBuf[outPos + 6] += (byte)((subchannel[inPos + i + 84] & 0x02) >> 1); + subBuf[outPos + 7] += (byte)(subchannel[inPos + i + 84] & 0x01); + outPos += 8; + } + } + + return subBuf; + } + + public static byte[] Deinterleave(byte[] subchannel) + { + byte[] subBuf = new byte[subchannel.Length]; + int inPos = 0; + + for(int outPos = 0; outPos < subchannel.Length; outPos += 96) + { + for(int i = 0; i < 12; i++) + { + // P + subBuf[outPos + i + 0] += (byte)((subchannel[inPos + 0] & 0x80) >> 0); + subBuf[outPos + i + 0] += (byte)((subchannel[inPos + 1] & 0x80) >> 1); + subBuf[outPos + i + 0] += (byte)((subchannel[inPos + 2] & 0x80) >> 2); + subBuf[outPos + i + 0] += (byte)((subchannel[inPos + 3] & 0x80) >> 3); + subBuf[outPos + i + 0] += (byte)((subchannel[inPos + 4] & 0x80) >> 4); + subBuf[outPos + i + 0] += (byte)((subchannel[inPos + 5] & 0x80) >> 5); + subBuf[outPos + i + 0] += (byte)((subchannel[inPos + 6] & 0x80) >> 6); + subBuf[outPos + i + 0] += (byte)((subchannel[inPos + 7] & 0x80) >> 7); + + // Q + subBuf[outPos + i + 12] += (byte)((subchannel[inPos + 0] & 0x40) << 1); + subBuf[outPos + i + 12] += (byte)((subchannel[inPos + 1] & 0x40) >> 0); + subBuf[outPos + i + 12] += (byte)((subchannel[inPos + 2] & 0x40) >> 1); + subBuf[outPos + i + 12] += (byte)((subchannel[inPos + 3] & 0x40) >> 2); + subBuf[outPos + i + 12] += (byte)((subchannel[inPos + 4] & 0x40) >> 3); + subBuf[outPos + i + 12] += (byte)((subchannel[inPos + 5] & 0x40) >> 4); + subBuf[outPos + i + 12] += (byte)((subchannel[inPos + 6] & 0x40) >> 5); + subBuf[outPos + i + 12] += (byte)((subchannel[inPos + 7] & 0x40) >> 6); + + // R + subBuf[outPos + i + 24] += (byte)((subchannel[inPos + 0] & 0x20) << 2); + subBuf[outPos + i + 24] += (byte)((subchannel[inPos + 1] & 0x20) << 1); + subBuf[outPos + i + 24] += (byte)((subchannel[inPos + 2] & 0x20) >> 0); + subBuf[outPos + i + 24] += (byte)((subchannel[inPos + 3] & 0x20) >> 1); + subBuf[outPos + i + 24] += (byte)((subchannel[inPos + 4] & 0x20) >> 2); + subBuf[outPos + i + 24] += (byte)((subchannel[inPos + 5] & 0x20) >> 3); + subBuf[outPos + i + 24] += (byte)((subchannel[inPos + 6] & 0x20) >> 4); + subBuf[outPos + i + 24] += (byte)((subchannel[inPos + 7] & 0x20) >> 5); + + // S + subBuf[outPos + i + 36] += (byte)((subchannel[inPos + 0] & 0x10) << 3); + subBuf[outPos + i + 36] += (byte)((subchannel[inPos + 1] & 0x10) << 2); + subBuf[outPos + i + 36] += (byte)((subchannel[inPos + 2] & 0x10) << 1); + subBuf[outPos + i + 36] += (byte)((subchannel[inPos + 3] & 0x10) >> 0); + subBuf[outPos + i + 36] += (byte)((subchannel[inPos + 4] & 0x10) >> 1); + subBuf[outPos + i + 36] += (byte)((subchannel[inPos + 5] & 0x10) >> 2); + subBuf[outPos + i + 36] += (byte)((subchannel[inPos + 6] & 0x10) >> 3); + subBuf[outPos + i + 36] += (byte)((subchannel[inPos + 7] & 0x10) >> 4); + + // T + subBuf[outPos + i + 48] += (byte)((subchannel[inPos + 0] & 0x8) << 4); + subBuf[outPos + i + 48] += (byte)((subchannel[inPos + 1] & 0x8) << 3); + subBuf[outPos + i + 48] += (byte)((subchannel[inPos + 2] & 0x8) << 2); + subBuf[outPos + i + 48] += (byte)((subchannel[inPos + 3] & 0x8) << 1); + subBuf[outPos + i + 48] += (byte)((subchannel[inPos + 4] & 0x8) >> 0); + subBuf[outPos + i + 48] += (byte)((subchannel[inPos + 5] & 0x8) >> 1); + subBuf[outPos + i + 48] += (byte)((subchannel[inPos + 6] & 0x8) >> 2); + subBuf[outPos + i + 48] += (byte)((subchannel[inPos + 7] & 0x8) >> 3); + + // U + subBuf[outPos + i + 60] += (byte)((subchannel[inPos + 0] & 0x4) << 5); + subBuf[outPos + i + 60] += (byte)((subchannel[inPos + 1] & 0x4) << 4); + subBuf[outPos + i + 60] += (byte)((subchannel[inPos + 2] & 0x4) << 3); + subBuf[outPos + i + 60] += (byte)((subchannel[inPos + 3] & 0x4) << 2); + subBuf[outPos + i + 60] += (byte)((subchannel[inPos + 4] & 0x4) << 1); + subBuf[outPos + i + 60] += (byte)((subchannel[inPos + 5] & 0x4) >> 0); + subBuf[outPos + i + 60] += (byte)((subchannel[inPos + 6] & 0x4) >> 1); + subBuf[outPos + i + 60] += (byte)((subchannel[inPos + 7] & 0x4) >> 2); + + // V + subBuf[outPos + i + 72] += (byte)((subchannel[inPos + 0] & 0x2) << 6); + subBuf[outPos + i + 72] += (byte)((subchannel[inPos + 1] & 0x2) << 5); + subBuf[outPos + i + 72] += (byte)((subchannel[inPos + 2] & 0x2) << 4); + subBuf[outPos + i + 72] += (byte)((subchannel[inPos + 3] & 0x2) << 3); + subBuf[outPos + i + 72] += (byte)((subchannel[inPos + 4] & 0x2) << 2); + subBuf[outPos + i + 72] += (byte)((subchannel[inPos + 5] & 0x2) << 1); + subBuf[outPos + i + 72] += (byte)((subchannel[inPos + 6] & 0x2) >> 0); + subBuf[outPos + i + 72] += (byte)((subchannel[inPos + 7] & 0x2) >> 1); + + // W + subBuf[outPos + i + 84] += (byte)((subchannel[inPos + 0] & 0x1) << 7); + subBuf[outPos + i + 84] += (byte)((subchannel[inPos + 1] & 0x1) << 6); + subBuf[outPos + i + 84] += (byte)((subchannel[inPos + 2] & 0x1) << 5); + subBuf[outPos + i + 84] += (byte)((subchannel[inPos + 3] & 0x1) << 4); + subBuf[outPos + i + 84] += (byte)((subchannel[inPos + 4] & 0x1) << 3); + subBuf[outPos + i + 84] += (byte)((subchannel[inPos + 5] & 0x1) << 2); + subBuf[outPos + i + 84] += (byte)((subchannel[inPos + 6] & 0x1) << 1); + subBuf[outPos + i + 84] += (byte)((subchannel[inPos + 7] & 0x1) >> 0); + + inPos += 8; + } + } + + return subBuf; + } + + public static string PrettifyQ(byte[] subBuf, bool bcd, long lba, bool corruptedPause, bool pause, bool rwEmpty) + { + CRC16CCITTContext.Data(subBuf, 10, out byte[] crc); + + bool crcOk = crc[0] == subBuf[10] && crc[1] == subBuf[11]; + long minute = (lba + 150) / 4500; + long second = (lba + 150) % 4500 / 75; + long frame = (lba + 150) % 4500 % 75; + string area; + int control = (subBuf[0] & 0xF0) / 16; + int adr = subBuf[0] & 0x0F; + + string controlInfo = ((control & 0xC) / 4) switch + { + 0 => $"stereo audio {((control & 0x01) == 1 ? "with" : "without")} pre-emphasis", + 1 => $"{((control & 0x01) == 1 ? "incremental" : "uninterrupted")} data", + 2 => $"quadraphonic audio {((control & 0x01) == 1 ? "with" : "without")} pre-emphasis", + _ => $"reserved control value {control & 0x01}" + }; + + string copy = (control & 0x02) > 0 ? "copy permitted" : "copy prohibited"; + + if(bcd) + BcdToBinaryQ(subBuf); + + int qPos = (subBuf[3] * 60 * 75) + (subBuf[4] * 75) + subBuf[5] - 150; + byte pmin = subBuf[7]; + byte psec = subBuf[8]; + + int qStart = (subBuf[7] * 60 * 75) + (subBuf[8] * 75) + subBuf[9] - 150; + int nextPos = (subBuf[3] * 60 * 75) + (subBuf[4] * 75) + subBuf[5] - 150; + byte zero = subBuf[6]; + int maxOut = (subBuf[7] * 60 * 75) + (subBuf[8] * 75) + subBuf[9] - 150; + bool final = subBuf[3] == 0xFF && subBuf[4] == 0xFF && subBuf[5] == 0xFF; + + BinaryToBcdQ(subBuf); + + if(lba < 0) + { + area = "Lead-In"; + + switch(adr) + { + case 1 when subBuf[2] < 0xA0: + return + $"{minute:D2}:{second:D2}:{frame:D2} - LBA {lba,6}: {area} area, {(corruptedPause ? "corrupted pause" : pause ? "pause" : "not pause")}, {controlInfo}, {copy}, Q mode {adr} position: {subBuf[3]:X2}:{subBuf[4]:X2}:{subBuf[5]:X2} (LBA {qPos}), track {subBuf[2]:X} starts at {subBuf[7]:X2}:{subBuf[8]:X2}:{subBuf[9]:X2} (LBA {qStart}), Q CRC 0x{subBuf[10]:X2}{subBuf[11]:X2} ({(crcOk ? "OK" : "BAD")}), R-W {(rwEmpty ? "empty" : "not empty")}"; + case 1 when subBuf[2] == 0xA0: + { + string format = subBuf[8] switch + { + 0x00 => "CD-DA / CD-ROM", + 0x10 => "CD-i", + 0x20 => "CD-ROM XA", + _ => $"unknown {subBuf[0]:X2}" + }; + + return + $"{minute:D2}:{second:D2}:{frame:D2} - LBA {lba,6}: {area} area, {(corruptedPause ? "corrupted pause" : pause ? "pause" : "not pause")}, {controlInfo}, {copy}, Q mode {adr} position: {subBuf[3]:X2}:{subBuf[4]:X2}:{subBuf[5]:X2} (LBA {qPos}), track {subBuf[2]:X} is first program area track in {format} format, Q CRC 0x{subBuf[10]:X2}{subBuf[11]:X2} ({(crcOk ? "OK" : "BAD")}), R-W {(rwEmpty ? "empty" : "not empty")}"; + } + case 1 when subBuf[2] == 0xA1: + return + $"{minute:D2}:{second:D2}:{frame:D2} - LBA {lba,6}: {area} area, {(corruptedPause ? "corrupted pause" : pause ? "pause" : "not pause")}, {controlInfo}, {copy}, Q mode {adr} position: {subBuf[3]:X2}:{subBuf[4]:X2}:{subBuf[5]:X2} (LBA {qPos}), track {subBuf[2]:X} is last program area track, Q CRC 0x{subBuf[10]:X2}{subBuf[11]:X2} ({(crcOk ? "OK" : "BAD")}), R-W {(rwEmpty ? "empty" : "not empty")}"; + case 1: + return subBuf[2] == 0xA2 + ? $"{minute:D2}:{second:D2}:{frame:D2} - LBA {lba,6}: {area} area, {(corruptedPause ? "corrupted pause" : pause ? "pause" : "not pause")}, {controlInfo}, {copy}, Q mode {adr} position: {subBuf[3]:X2}:{subBuf[4]:X2}:{subBuf[5]:X2} (LBA {qPos}), track {subBuf[2]:X} starts at {subBuf[7]:X2}{subBuf[8]:X2}{subBuf[9]:X2} (LBA {qStart}), Q CRC 0x{subBuf[10]:X2}{subBuf[11]:X2} ({(crcOk ? "OK" : "BAD")}), R-W {(rwEmpty ? "empty" : "not empty")}" + : $"{minute:D2}:{second:D2}:{frame:D2} - LBA {lba,6}: {area} area, {(corruptedPause ? "corrupted pause" : pause ? "pause" : "not pause")}, {controlInfo}, {copy}, Q: {subBuf[0]:X2} {subBuf[1]:X2} {subBuf[2]:X2} {subBuf[3]:X2} {subBuf[4]:X2} {subBuf[5]:X2} {subBuf[6]:X2} {subBuf[7]:X2} {subBuf[8]:X2} {subBuf[9]:X2} CRC 0x{subBuf[10]:X2}{subBuf[11]:X2} ({(crcOk ? "OK" : "BAD")}), R-W {(rwEmpty ? "empty" : "not empty")}"; + case 2: + return + $"{minute:D2}:{second:D2}:{frame:D2} - LBA {lba,6}: {area} area, {(corruptedPause ? "corrupted pause" : pause ? "pause" : "not pause")}, {controlInfo}, {copy}, Q mode {adr} MCN: {DecodeMcn(subBuf)} frame {subBuf[9]:X2} CRC 0x{subBuf[10]:X2}{subBuf[11]:X2} ({(crcOk ? "OK" : "BAD")}), R-W {(rwEmpty ? "empty" : "not empty")}"; + } + + if(adr != 5) + return + $"{minute:D2}:{second:D2}:{frame:D2} - LBA {lba,6}: {area} area, {(corruptedPause ? "corrupted pause" : pause ? "pause" : "not pause")}, {controlInfo}, {copy}, Q: {subBuf[0]:X2} {subBuf[1]:X2} {subBuf[2]:X2} {subBuf[3]:X2} {subBuf[4]:X2} {subBuf[5]:X2} {subBuf[6]:X2} {subBuf[7]:X2} {subBuf[8]:X2} {subBuf[9]:X2} CRC 0x{subBuf[10]:X2}{subBuf[11]:X2} ({(crcOk ? "OK" : "BAD")}), R-W {(rwEmpty ? "empty" : "not empty")}"; + + if(subBuf[2] <= 0x40) + { + return + $"{minute:D2}:{second:D2}:{frame:D2} - LBA {lba,6}: {area} area, {(corruptedPause ? "corrupted pause" : pause ? "pause" : "not pause")}, {controlInfo}, {copy}, Q mode {adr} skip interval start time {subBuf[7]:X2}{subBuf[8]:X2}{subBuf[9]:X2}, skip interval stop time {subBuf[3]:X2}{subBuf[4]:X2}{subBuf[5]:X2}, CRC 0x{subBuf[10]:X2}{subBuf[11]:X2} ({(crcOk ? "OK" : "BAD")}), R-W {(rwEmpty ? "empty" : "not empty")}"; + } + + if(subBuf[2] == 0xB0) + { + return final + ? $"{minute:D2}:{second:D2}:{frame:D2} - LBA {lba,6}: {area} area, {(corruptedPause ? "corrupted pause" : pause ? "pause" : "not pause")}, {controlInfo}, {copy}, Q mode {adr} next program area can start at {subBuf[3]:X2}:{subBuf[4]:X2}:{subBuf[5]:X2} (LBA {nextPos}), last-session, {zero} mode 5 pointers, CRC 0x{subBuf[10]:X2}{subBuf[11]:X2} ({(crcOk ? "OK" : "BAD")}), R-W {(rwEmpty ? "empty" : "not empty")}" + : $"{minute:D2}:{second:D2}:{frame:D2} - LBA {lba,6}: {area} area, {(corruptedPause ? "corrupted pause" : pause ? "pause" : "not pause")}, {controlInfo}, {copy}, Q mode {adr} next program area can start at {subBuf[3]:X2}:{subBuf[4]:X2}:{subBuf[5]:X2} (LBA {nextPos}), maximum Lead-out at {subBuf[7]:X2}:{subBuf[8]:X2}:{subBuf[9]:X2} (LBA {maxOut}), {zero} mode 5 pointers, CRC 0x{subBuf[10]:X2}{subBuf[11]:X2} ({(crcOk ? "OK" : "BAD")}), R-W {(rwEmpty ? "empty" : "not empty")}"; + } + + if(subBuf[2] == 0xB1) + { + return + $"{minute:D2}:{second:D2}:{frame:D2} - LBA {lba,6}: {area} area, {(corruptedPause ? "corrupted pause" : pause ? "pause" : "not pause")}, {controlInfo}, {copy}, Q mode {adr}, {pmin} skip interval pointers, {psec} skip track assignments, CRC 0x{subBuf[10]:X2}{subBuf[11]:X2} ({(crcOk ? "OK" : "BAD")}), R-W {(rwEmpty ? "empty" : "not empty")}"; + } + + if(subBuf[2] != 0xB2 && + subBuf[2] != 0xB3 && + subBuf[2] != 0xB4) + return subBuf[2] == 0xC0 + ? $"{minute:D2}:{second:D2}:{frame:D2} - LBA {lba,6}: {area} area, {(corruptedPause ? "corrupted pause" : pause ? "pause" : "not pause")}, {controlInfo}, {copy}, Q mode {adr}, ATIP values {subBuf[3]:X2}, {subBuf[4]:X2}, {subBuf[5]:X2}, first disc Lead-in starts at {subBuf[7]:X2}{subBuf[8]:X2}{subBuf[9]:X2} (LBA {qStart}), CRC 0x{subBuf[10]:X2}{subBuf[11]:X2} ({(crcOk ? "OK" : "BAD")}), R-W {(rwEmpty ? "empty" : "not empty")}" + : $"{minute:D2}:{second:D2}:{frame:D2} - LBA {lba,6}: {area} area, {(corruptedPause ? "corrupted pause" : pause ? "pause" : "not pause")}, {controlInfo}, {copy}, Q: {subBuf[0]:X2} {subBuf[1]:X2} {subBuf[2]:X2} {subBuf[3]:X2} {subBuf[4]:X2} {subBuf[5]:X2} {subBuf[6]:X2} {subBuf[7]:X2} {subBuf[8]:X2} {subBuf[9]:X2} CRC 0x{subBuf[10]:X2}{subBuf[11]:X2} ({(crcOk ? "OK" : "BAD")}), R-W {(rwEmpty ? "empty" : "not empty")}"; + + string skipTracks = $"{subBuf[3]:X2}"; + + if(subBuf[4] > 0) + skipTracks += $", {subBuf[4]:X2}"; + + if(subBuf[5] > 0) + skipTracks += $", {subBuf[4]:X2}"; + + if(subBuf[7] > 0) + skipTracks += $", {subBuf[4]:X2}"; + + if(subBuf[8] > 0) + skipTracks += $", {subBuf[4]:X2}"; + + if(subBuf[9] > 0) + skipTracks += $", {subBuf[4]:X2}"; + + return + $"{minute:D2}:{second:D2}:{frame:D2} - LBA {lba,6}: {area} area, {(corruptedPause ? "corrupted pause" : pause ? "pause" : "not pause")}, {controlInfo}, {copy}, Q mode {adr}, tracks {skipTracks} to be skipped, CRC 0x{subBuf[10]:X2}{subBuf[11]:X2} ({(crcOk ? "OK" : "BAD")}), R-W {(rwEmpty ? "empty" : "not empty")}"; + } + + area = subBuf[1] == 0xAA ? "Lead-out" : "Program"; + + return adr switch + { + 1 => + $"{minute:D2}:{second:D2}:{frame:D2} - LBA {lba,6}: {area} area, {(corruptedPause ? "corrupted pause" : pause ? "pause" : "not pause")}, {controlInfo}, {copy}, Q mode {adr} position: track {subBuf[1]:X} index {subBuf[2]:X} relative position {subBuf[3]:X2}:{subBuf[4]:X2}:{subBuf[5]:X2} (LBA {qPos + 150}), absolute position {subBuf[7]:X2}:{subBuf[8]:X2}:{subBuf[9]:X2} (LBA {qStart}), Q CRC 0x{subBuf[10]:X2}{subBuf[11]:X2} ({(crcOk ? "OK" : "BAD")}), R-W {(rwEmpty ? "empty" : "not empty")}", + 2 => + $"{minute:D2}:{second:D2}:{frame:D2} - LBA {lba,6}: {area} area, {(corruptedPause ? "corrupted pause" : pause ? "pause" : "not pause")}, {controlInfo}, {copy}, Q mode {adr} MCN: {DecodeMcn(subBuf)} frame {subBuf[9]:X2} CRC 0x{subBuf[10]:X2}{subBuf[11]:X2} ({(crcOk ? "OK" : "BAD")}), R-W {(rwEmpty ? "empty" : "not empty")}", + 3 => + $"{minute:D2}:{second:D2}:{frame:D2} - LBA {lba,6}: {area} area, {(corruptedPause ? "corrupted pause" : pause ? "pause" : "not pause")}, {controlInfo}, {copy}, Q mode {adr} ISRC: {DecodeIsrc(subBuf)} frame {subBuf[9]:X2} CRC 0x{subBuf[10]:X2}{subBuf[11]:X2} ({(crcOk ? "OK" : "BAD")}), R-W {(rwEmpty ? "empty" : "not empty")}", + _ => + $"{minute:D2}:{second:D2}:{frame:D2} - LBA {lba,6}: {area} area, {(corruptedPause ? "corrupted pause" : pause ? "pause" : "not pause")}, {controlInfo}, {copy}, Q: {subBuf[0]:X2} {subBuf[1]:X2} {subBuf[2]:X2} {subBuf[3]:X2} {subBuf[4]:X2} {subBuf[5]:X2} {subBuf[6]:X2} {subBuf[7]:X2} {subBuf[8]:X2} {subBuf[9]:X2} CRC 0x{subBuf[10]:X2}{subBuf[11]:X2} ({(crcOk ? "OK" : "BAD")}), R-W {(rwEmpty ? "empty" : "not empty")}" + }; + } + + public static string DecodeIsrc(byte[] q) => + $"{_isrcTable[q[1] / 4]}{_isrcTable[((q[1] & 3) * 16) + (q[2] / 16)]}{_isrcTable[((q[2] & 0xF) * 4) + (q[3] / 64)]}{_isrcTable[q[3] & 0x3F]}{_isrcTable[q[4] / 4]}{q[5]:X2}{q[6]:X2}{q[7]:X2}{q[8] / 16:X1}"; + + public static string DecodeMcn(byte[] q) => + $"{q[1]:X2}{q[2]:X2}{q[3]:X2}{q[4]:X2}{q[5]:X2}{q[6]:X2}{q[7] >> 4:X}"; + + public static byte GetIsrcCode(char c) + { + switch(c) + { + case '0': return 0x00; + case '1': return 0x01; + case '2': return 0x02; + case '3': return 0x03; + case '4': return 0x04; + case '5': return 0x05; + case '6': return 0x06; + case '7': return 0x07; + case '8': return 0x08; + case '9': return 0x09; + case 'A': return 0x11; + case 'B': return 0x12; + case 'C': return 0x13; + case 'D': return 0x14; + case 'E': return 0x15; + case 'F': return 0x16; + case 'G': return 0x17; + case 'H': return 0x18; + case 'I': return 0x19; + case 'J': return 0x1A; + case 'K': return 0x1B; + case 'L': return 0x1C; + case 'M': return 0x1D; + case 'N': return 0x1E; + case 'O': return 0x1F; + case 'P': return 0x20; + case 'Q': return 0x21; + case 'R': return 0x22; + case 'S': return 0x23; + case 'T': return 0x24; + case 'U': return 0x25; + case 'V': return 0x26; + case 'W': return 0x27; + case 'X': return 0x28; + case 'Y': return 0x29; + case 'Z': return 0x2A; + default: return 0x00; + } + } + + public static byte[] Generate(int sector, uint trackSequence, int pregap, int trackStart, byte flags, + byte index) + { + bool isPregap = sector < 0 || sector <= trackStart + pregap; + + if(index == 0) + index = (byte)(isPregap ? 0 : 1); + + byte[] sub = new byte[96]; + + // P + if(isPregap) + { + sub[0] = 0xFF; + sub[1] = 0xFF; + sub[2] = 0xFF; + sub[3] = 0xFF; + sub[4] = 0xFF; + sub[5] = 0xFF; + sub[6] = 0xFF; + sub[7] = 0xFF; + sub[8] = 0xFF; + sub[9] = 0xFF; + sub[10] = 0xFF; + sub[11] = 0xFF; + } + + // Q + byte[] q = new byte[12]; + + q[0] = (byte)((flags << 4) + 1); + q[1] = (byte)trackSequence; + q[2] = index; + + int relative; + + if(isPregap) + relative = pregap + trackStart - sector; + else + relative = sector - trackStart; + + sector += 150; + + int min = relative / 60 / 75; + int sec = (relative / 75) - (min * 60); + int frame = relative - (min * 60 * 75) - (sec * 75); + + int amin = sector / 60 / 75; + int asec = (sector / 75) - (amin * 60); + int aframe = sector - (amin * 60 * 75) - (asec * 75); + + q[3] = (byte)min; + q[4] = (byte)sec; + q[5] = (byte)frame; + + q[7] = (byte)amin; + q[8] = (byte)asec; + q[9] = (byte)aframe; + + q[1] = (byte)(((q[1] / 10) << 4) + (q[1] % 10)); + q[2] = (byte)(((q[2] / 10) << 4) + (q[2] % 10)); + q[3] = (byte)(((q[3] / 10) << 4) + (q[3] % 10)); + q[4] = (byte)(((q[4] / 10) << 4) + (q[4] % 10)); + q[5] = (byte)(((q[5] / 10) << 4) + (q[5] % 10)); + q[6] = (byte)(((q[6] / 10) << 4) + (q[6] % 10)); + q[7] = (byte)(((q[7] / 10) << 4) + (q[7] % 10)); + q[8] = (byte)(((q[8] / 10) << 4) + (q[8] % 10)); + + q[9] = (byte)(((q[9] / 10) << 4) + (q[9] % 10)); + + CRC16CCITTContext.Data(q, 10, out byte[] qCrc); + q[10] = qCrc[0]; + q[11] = qCrc[1]; + + Array.Copy(q, 0, sub, 12, 12); + + return Interleave(sub); + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/CD/TOC.cs b/Aaru.Decoders/CD/TOC.cs new file mode 100644 index 000000000..cfbe2ba64 --- /dev/null +++ b/Aaru.Decoders/CD/TOC.cs @@ -0,0 +1,236 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : TOC.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes CD Table of Contents. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Console; +using Aaru.Helpers; + +namespace Aaru.Decoders.CD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + // ISO/IEC 61104: Compact disc video system - 12 cm CD-V + // ISO/IEC 60908: Audio recording - Compact disc digital audio system + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class TOC + { + public static CDTOC? Decode(byte[] CDTOCResponse) + { + if(CDTOCResponse == null || + CDTOCResponse.Length <= 4) + return null; + + var decoded = new CDTOC + { + DataLength = BigEndianBitConverter.ToUInt16(CDTOCResponse, 0), + FirstTrack = CDTOCResponse[2], + LastTrack = CDTOCResponse[3] + }; + + decoded.TrackDescriptors = new CDTOCTrackDataDescriptor[(decoded.DataLength - 2) / 8]; + + if(decoded.DataLength + 2 != CDTOCResponse.Length) + { + AaruConsole.DebugWriteLine("CD TOC decoder", + "Expected CDTOC size ({0} bytes) is not received size ({1} bytes), not decoding", + decoded.DataLength + 2, CDTOCResponse.Length); + + return null; + } + + for(int i = 0; i < (decoded.DataLength - 2) / 8; i++) + { + decoded.TrackDescriptors[i].Reserved1 = CDTOCResponse[0 + (i * 8) + 4]; + decoded.TrackDescriptors[i].ADR = (byte)((CDTOCResponse[1 + (i * 8) + 4] & 0xF0) >> 4); + decoded.TrackDescriptors[i].CONTROL = (byte)(CDTOCResponse[1 + (i * 8) + 4] & 0x0F); + decoded.TrackDescriptors[i].TrackNumber = CDTOCResponse[2 + (i * 8) + 4]; + decoded.TrackDescriptors[i].Reserved2 = CDTOCResponse[3 + (i * 8) + 4]; + + decoded.TrackDescriptors[i].TrackStartAddress = + BigEndianBitConverter.ToUInt32(CDTOCResponse, 4 + (i * 8) + 4); + } + + return decoded; + } + + public static string Prettify(CDTOC? CDTOCResponse) + { + if(CDTOCResponse == null) + return null; + + CDTOC response = CDTOCResponse.Value; + + var sb = new StringBuilder(); + + sb.AppendFormat("First track number in first complete session: {0}", response.FirstTrack).AppendLine(); + sb.AppendFormat("Last track number in last complete session: {0}", response.LastTrack).AppendLine(); + + foreach(CDTOCTrackDataDescriptor descriptor in response.TrackDescriptors) + { + if(descriptor.TrackNumber == 0xAA) + sb.AppendLine("Track number: Lead-Out"); + else + sb.AppendFormat("Track number: {0}", descriptor.TrackNumber).AppendLine(); + + sb.AppendFormat("Track starts at LBA {0}, or MSF {1:X2}:{2:X2}:{3:X2}", descriptor.TrackStartAddress, + (descriptor.TrackStartAddress & 0x0000FF00) >> 8, + (descriptor.TrackStartAddress & 0x00FF0000) >> 16, + (descriptor.TrackStartAddress & 0xFF000000) >> 24).AppendLine(); + + switch((TocAdr)descriptor.ADR) + { + case TocAdr.NoInformation: + sb.AppendLine("Q subchannel mode not given"); + + break; + case TocAdr.TrackPointer: + sb.AppendLine("Q subchannel stores track pointer"); + + break; + case TocAdr.VideoTrackPointer: + sb.AppendLine("Q subchannel stores video track pointer"); + + break; + case TocAdr.ISRC: + sb.AppendLine("Q subchannel stores ISRC"); + + break; + case TocAdr.MediaCatalogNumber: + sb.AppendLine("Q subchannel stores media catalog number"); + + break; + default: + sb.AppendFormat("Q subchannel mode {0}", descriptor.ADR).AppendLine(); + + break; + } + + if((descriptor.CONTROL & (byte)TocControl.ReservedMask) == (byte)TocControl.ReservedMask) + sb.AppendFormat("Reserved flags 0x{0:X2} set", descriptor.CONTROL).AppendLine(); + else + { + switch((TocControl)(descriptor.CONTROL & 0x0D)) + { + case TocControl.TwoChanNoPreEmph: + sb.AppendLine("Stereo audio track with no pre-emphasis"); + + break; + case TocControl.TwoChanPreEmph: + sb.AppendLine("Stereo audio track with 50/15 μs pre-emphasis"); + + break; + case TocControl.FourChanNoPreEmph: + sb.AppendLine("Quadraphonic audio track with no pre-emphasis"); + + break; + case TocControl.FourChanPreEmph: + sb.AppendLine("Quadraphonic audio track with 50/15 μs pre-emphasis"); + + break; + case TocControl.DataTrack: + sb.AppendLine("Data track, recorded uninterrupted"); + + break; + case TocControl.DataTrackIncremental: + sb.AppendLine("Data track, recorded incrementally"); + + break; + } + + sb.AppendLine((descriptor.CONTROL & (byte)TocControl.CopyPermissionMask) == + (byte)TocControl.CopyPermissionMask ? "Digital copy of track is permitted" + : "Digital copy of track is prohibited"); + + #if DEBUG + if(descriptor.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", descriptor.Reserved1).AppendLine(); + + if(descriptor.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", descriptor.Reserved2).AppendLine(); + #endif + + sb.AppendLine(); + } + } + + return sb.ToString(); + } + + public static string Prettify(byte[] CDTOCResponse) + { + CDTOC? decoded = Decode(CDTOCResponse); + + return Prettify(decoded); + } + + public struct CDTOC + { + /// Total size of returned TOC minus this field + public ushort DataLength; + /// First track number in hex + public byte FirstTrack; + /// Last track number in hex + public byte LastTrack; + /// Track descriptors + public CDTOCTrackDataDescriptor[] TrackDescriptors; + } + + public struct CDTOCTrackDataDescriptor + { + /// Byte 0 Reserved + public byte Reserved1; + /// Byte 1, bits 7 to 4 Type of information in Q subchannel of block where this TOC entry was found + public byte ADR; + /// Byte 1, bits 3 to 0 Track attributes + public byte CONTROL; + /// Byte 2 Track number + public byte TrackNumber; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to 7 The track start address in LBA or in MSF + public uint TrackStartAddress; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/DVD/AACS.cs b/Aaru.Decoders/DVD/AACS.cs new file mode 100644 index 000000000..cabd3ca64 --- /dev/null +++ b/Aaru.Decoders/DVD/AACS.cs @@ -0,0 +1,67 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : AACS.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes DVD AACS structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.Decoders.DVD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + // ECMA 365 + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class AACS + { + public struct HDLeadInCopyright + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to 2052 HD DVD Lead-In Copyright Information + public byte[] CopyrightInformation; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/DVD/ADIP.cs b/Aaru.Decoders/DVD/ADIP.cs new file mode 100644 index 000000000..444481e74 --- /dev/null +++ b/Aaru.Decoders/DVD/ADIP.cs @@ -0,0 +1,67 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ADIP.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes DVD ADress-In-Pregroove. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.Decoders.DVD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + // ECMA 365 + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class ADIP + { + public struct ADIPInformation + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to 259 ADIP, defined in DVD standards + public byte[] ADIP; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/DVD/BCA.cs b/Aaru.Decoders/DVD/BCA.cs new file mode 100644 index 000000000..8153e5149 --- /dev/null +++ b/Aaru.Decoders/DVD/BCA.cs @@ -0,0 +1,67 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : BCA.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes DVD Burst Cutting Area. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.Decoders.DVD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + // ECMA 365 + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class BCA + { + public struct BurstCuttingArea + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to end Burst cutting area contents, 12 to 188 bytes + public byte[] BCA; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/DVD/CPRM.cs b/Aaru.Decoders/DVD/CPRM.cs new file mode 100644 index 000000000..7d377f84d --- /dev/null +++ b/Aaru.Decoders/DVD/CPRM.cs @@ -0,0 +1,79 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CPRM.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes DVD CPRM structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.Decoders.DVD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + // ECMA 365 + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class CPRM + { + public struct DiscMediaIdentifier + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to end Disc Media Identifier for CPRM + public byte[] MediaIdentifier; + } + + public struct DiscMediaKeyBlock + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to end Disc Media Key Block for CPRM + public byte[] MediaKeyBlock; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/DVD/CSS&CPRM.cs b/Aaru.Decoders/DVD/CSS&CPRM.cs new file mode 100644 index 000000000..a234ec3d7 --- /dev/null +++ b/Aaru.Decoders/DVD/CSS&CPRM.cs @@ -0,0 +1,352 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CSS&CPRM.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes DVD CSS & CPRM structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// Copyright © 2020-2023 Rebecca Wallander +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.DVD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + // ECMA 365 + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class CSS_CPRM + { + public static LeadInCopyright? DecodeLeadInCopyright(byte[] response) + { + if(response?.Length != 8) + return null; + + return new LeadInCopyright + { + DataLength = (ushort)((response[0] << 8) + response[1]), + Reserved1 = response[2], + Reserved2 = response[3], + CopyrightType = (CopyrightType)response[4], + RegionInformation = response[5], + Reserved3 = response[6], + Reserved4 = response[7] + }; + } + + public static RegionalPlaybackControlState? DecodeRegionalPlaybackControlState(byte[] response) + { + if(response?.Length != 8) + return null; + + return new RegionalPlaybackControlState + { + DataLength = (ushort)((response[0] << 8) + response[1]), + Reserved1 = response[2], + Reserved2 = response[3], + TypeCode_VendorResetsAvailable_UserControlledChangesAvailable = response[4], + RegionMask = response[5], + RPCScheme = response[6], + Reserved3 = response[7] + }; + } + + public static string PrettifyRegionalPlaybackControlState(RegionalPlaybackControlState? rpc) + { + if(rpc == null) + { + return null; + } + + RegionalPlaybackControlState decoded = rpc.Value; + var sb = new StringBuilder(); + + var typeCode = + (TypeCode)((decoded.TypeCode_VendorResetsAvailable_UserControlledChangesAvailable & 0xc0) >> 6); + + int vendorResets = (decoded.TypeCode_VendorResetsAvailable_UserControlledChangesAvailable & 0x38) >> 3; + + int userControlledChanges = decoded.TypeCode_VendorResetsAvailable_UserControlledChangesAvailable & 0x7; + + switch(typeCode) + { + case TypeCode.None: + sb.AppendLine("No drive region setting."); + + break; + case TypeCode.Set: + sb.AppendLine("Drive region is set."); + + break; + case TypeCode.LastChance: + sb.AppendLine("Drive region is set, with additional restrictions required to make a change."); + + break; + case TypeCode.Perm: + sb.AppendLine("Drive region has been set permanently, but may be reset by the vendor if necessary."); + + break; + } + + sb.AppendLine($"Drive has {vendorResets} vendor resets available."); + sb.AppendLine($"Drive has {userControlledChanges} user controlled changes available."); + + if(decoded.RegionMask == 0xFF) + sb.AppendLine("Drive has no region set."); + else if(decoded.RegionMask == 0x00) + sb.AppendLine("Drive is region free."); + else + { + sb.Append("Drive has the following regions set:"); + + if((decoded.RegionMask & 0x01) != 0x01) + sb.Append(" 1"); + + if((decoded.RegionMask & 0x02) != 0x02) + sb.Append(" 2"); + + if((decoded.RegionMask & 0x04) != 0x04) + sb.Append(" 3"); + + if((decoded.RegionMask & 0x08) != 0x08) + sb.Append(" 4"); + + if((decoded.RegionMask & 0x10) != 0x10) + sb.Append(" 5"); + + if((decoded.RegionMask & 0x20) != 0x20) + sb.Append(" 6"); + + if((decoded.RegionMask & 0x40) != 0x40) + sb.Append(" 7"); + + if((decoded.RegionMask & 0x80) != 0x80) + sb.Append(" 8"); + } + + sb.AppendLine(""); + + switch(decoded.RPCScheme) + { + case 0x00: + sb.AppendLine("The Logical Unit does not enforce Region Playback Controls (RPC)."); + + break; + case 0x01: + sb.AppendLine("The Logical Unit shall adhere to the specification and all requirements of the CSS license agreement concerning RPC."); + + break; + default: + sb.AppendLine("The Logical Unit uses an unknown region enforcement scheme."); + + break; + } + + return sb.ToString(); + } + + public static string PrettifyRegionalPlaybackControlState(byte[] response) => + PrettifyRegionalPlaybackControlState(DecodeRegionalPlaybackControlState(response)); + + public static string PrettifyLeadInCopyright(LeadInCopyright? cmi) + { + if(cmi == null) + return null; + + LeadInCopyright decoded = cmi.Value; + var sb = new StringBuilder(); + + switch(decoded.CopyrightType) + { + case CopyrightType.NoProtection: + sb.AppendLine("Disc has no encryption."); + + break; + case CopyrightType.CSS: + sb.AppendLine("Disc is encrypted using CSS or CPPM."); + + break; + case CopyrightType.CPRM: + sb.AppendLine("Disc is encrypted using CPRM."); + + break; + case CopyrightType.AACS: + sb.AppendLine("Disc is encrypted using AACS."); + + break; + default: + sb.AppendFormat("Disc is encrypted using unknown algorithm with ID {0}.", decoded.CopyrightType); + + break; + } + + if(decoded.CopyrightType == 0) + return sb.ToString(); + + if(decoded.RegionInformation == 0xFF) + sb.AppendLine("Disc cannot be played in any region at all."); + else if(decoded.RegionInformation == 0x00) + sb.AppendLine("Disc can be played in any region."); + else + { + sb.Append("Disc can be played in the following regions:"); + + if((decoded.RegionInformation & 0x01) != 0x01) + sb.Append(" 1"); + + if((decoded.RegionInformation & 0x02) != 0x02) + sb.Append(" 2"); + + if((decoded.RegionInformation & 0x04) != 0x04) + sb.Append(" 3"); + + if((decoded.RegionInformation & 0x08) != 0x08) + sb.Append(" 4"); + + if((decoded.RegionInformation & 0x10) != 0x10) + sb.Append(" 5"); + + if((decoded.RegionInformation & 0x20) != 0x20) + sb.Append(" 6"); + + if((decoded.RegionInformation & 0x40) != 0x40) + sb.Append(" 7"); + + if((decoded.RegionInformation & 0x80) != 0x80) + sb.Append(" 8"); + } + + return sb.ToString(); + } + + public static string PrettifyLeadInCopyright(byte[] response) => + PrettifyLeadInCopyright(DecodeLeadInCopyright(response)); + + public struct LeadInCopyright + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4 Copy protection system type + public CopyrightType CopyrightType; + /// Byte 5 Bitmask of regions where this disc is playable + public byte RegionInformation; + /// Byte 6 Reserved + public byte Reserved3; + /// Byte 7 Reserved + public byte Reserved4; + } + + public struct DiscKey + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to 2052 Disc key for CSS, Album Identifier for CPPM + public byte[] Key; + } + + public struct TitleKey + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4 CPM + public byte CMI; + /// Bytes 5 to 10 Title key for CSS + public byte[] Key; + /// Byte 11 Reserved + public byte Reserved3; + /// Byte 12 Reserved + public byte Reserved4; + } + + public struct AuthenticationSuccessFlag + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4 Reserved + public byte Reserved3; + /// Byte 5 Reserved + public byte Reserved4; + /// Byte 6 Reserved + public byte Reserved5; + /// Byte 7 Reserved and ASF + public byte ASF; + } + + public struct RegionalPlaybackControlState + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4 Type Code and # of Vendor Resets Available and # of User Controlled Changes Available + public byte TypeCode_VendorResetsAvailable_UserControlledChangesAvailable; + /// Byte 5 Region Mask + public byte RegionMask; + /// Byte 6 RPC Scheme + public byte RPCScheme; + /// Byte 7 Reserved + public byte Reserved3; + } + + enum TypeCode + { + None = 0, Set = 1, LastChance = 2, + Perm = 3 + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/DVD/Cartridge.cs b/Aaru.Decoders/DVD/Cartridge.cs new file mode 100644 index 000000000..373e7a481 --- /dev/null +++ b/Aaru.Decoders/DVD/Cartridge.cs @@ -0,0 +1,175 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Cartridge.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes DVD cartridge structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.DVD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + // ECMA 365 + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class Cartridge + { + public static MediumStatus? Decode(byte[] response) + { + if(response?.Length != 8) + return null; + + return new MediumStatus + { + DataLength = (ushort)((response[0] << 8) + response[1]), + Reserved1 = response[2], + Reserved2 = response[3], + Cartridge = (response[4] & 0x80) == 0x80, + OUT = (response[4] & 0x40) == 0x40, + Reserved3 = (byte)((response[4] & 0x30) >> 4), + MSWI = (response[4] & 0x08) == 0x08, + CWP = (response[4] & 0x04) == 0x04, + PWP = (response[4] & 0x02) == 0x02, + Reserved4 = (response[4] & 0x01) == 0x01, + DiscType = response[5], + Reserved5 = response[6], + RAMSWI = response[7] + }; + } + + public static string Prettify(MediumStatus? status) + { + if(status == null) + return null; + + MediumStatus decoded = status.Value; + var sb = new StringBuilder(); + + if(decoded.PWP) + sb.AppendLine("Disc surface is set to write protected status"); + + if(decoded.Cartridge) + { + sb.AppendLine("Disc comes in a cartridge"); + + if(decoded.OUT) + sb.AppendLine("Disc has been extracted from the cartridge"); + + if(decoded.CWP) + sb.AppendLine("Cartridge is set to write protected"); + } + + switch(decoded.DiscType) + { + case 0: + sb.AppendLine("Disc shall not be written without a cartridge"); + + break; + case 0x10: + sb.AppendLine("Disc may be written without a cartridge"); + + break; + default: + sb.AppendFormat("Unknown disc type id {0}", decoded.DiscType).AppendLine(); + + break; + } + + if(!decoded.MSWI) + return sb.ToString(); + + switch(decoded.RAMSWI) + { + case 0: break; + case 1: + sb.AppendLine("Disc is write inhibited because it has been extracted from the cartridge"); + + break; + case 0xFF: + sb.AppendLine("Disc is write inhibited for an unspecified reason"); + + break; + default: + sb.AppendFormat("Disc has unknown reason {0} for write inhibition", decoded.RAMSWI).AppendLine(); + + break; + } + + return sb.ToString(); + } + + public static string Prettify(byte[] response) => Prettify(Decode(response)); + + public struct MediumStatus + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4, bit 7 Medium is in a cartridge + public bool Cartridge; + /// Byte 4, bit 6 Medium has been taken out/inserted in a cartridge + public bool OUT; + /// Byte 4, bits 5 to 4 Reserved + public byte Reserved3; + /// Byte 4, bit 3 Media is write protected by reason stablished in RAMSWI + public bool MSWI; + /// Byte 4, bit 2 Media is write protected by cartridge + public bool CWP; + /// Byte 4, bit 1 Media is persistently write protected + public bool PWP; + /// Byte 4, bit 0 Reserved + public bool Reserved4; + /// Byte 5 Writable status depending on cartridge + public byte DiscType; + /// Byte 6 Reserved + public byte Reserved5; + /// + /// Byte 7 Reason of specific write protection, only defined 0x01 as "bare disc wp", and 0xFF as unspecified. Rest + /// reserved. + /// + public byte RAMSWI; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/DVD/DDS.cs b/Aaru.Decoders/DVD/DDS.cs new file mode 100644 index 000000000..aad0af2a9 --- /dev/null +++ b/Aaru.Decoders/DVD/DDS.cs @@ -0,0 +1,251 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : DDS.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes DVD Disc Definition Structure. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.DVD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + // ECMA 272: 120 mm DVD Rewritable Disk (DVD-RAM) + // ECMA 330: 120 mm (4,7 Gbytes per side) and 80 mm (1,46 Gbytes per side) DVD Rewritable Disk (DVD-RAM) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class DDS + { + public static DiscDefinitionStructure? Decode(byte[] response) + { + if(response?.Length != 2052) + return null; + + var dds = new DiscDefinitionStructure + { + Identifier = (ushort)((response[4] << 8) + response[5]) + }; + + if(dds.Identifier != 0x0A0A) + return null; + + // Common to both DVD-RAM versions + dds.DataLength = (ushort)((response[0] << 8) + response[1]); + dds.Reserved1 = response[2]; + dds.Reserved2 = response[3]; + dds.Reserved3 = response[6]; + dds.InProcess |= (response[7] & 0x80) == 0x80; + dds.UserCertification |= (response[7] & 0x02) == 0x02; + dds.ManufacturerCertification |= (response[7] & 0x01) == 0x01; + + dds.UpdateCount = (uint)((response[8] << 24) + (response[9] << 16) + (response[10] << 8) + response[11]); + + dds.Groups = (ushort)((response[12] << 8) + response[13]); + + // ECMA-272 + if(dds.Groups == 24) + { + dds.PartialCertification |= (response[7] & 0x40) == 0x40; + dds.FormattingOnlyAGroup |= (response[7] & 0x20) == 0x20; + dds.Reserved4 = (byte)((response[7] & 0x1C) >> 2); + dds.Reserved = new byte[6]; + Array.Copy(response, 14, dds.Reserved, 0, 6); + dds.GroupCertificationFlags = new GroupCertificationFlag[24]; + + for(int i = 0; i < 24; i++) + { + dds.GroupCertificationFlags[i].InProcess |= (response[20 + i] & 0x80) == 0x80; + dds.GroupCertificationFlags[i].PartialCertification |= (response[20 + i] & 0x40) == 0x40; + dds.GroupCertificationFlags[i].Reserved1 = (byte)((response[20 + i] & 0x3C) >> 2); + dds.GroupCertificationFlags[i].UserCertification |= (response[20 + i] & 0x02) == 0x02; + dds.GroupCertificationFlags[i].Reserved2 |= (response[20 + i] & 0x01) == 0x01; + } + } + + // ECMA-330 + if(dds.Groups != 1) + return dds; + + { + dds.Reserved4 = (byte)((response[7] & 0x7C) >> 2); + dds.Reserved = new byte[68]; + Array.Copy(response, 16, dds.Reserved, 0, 68); + dds.Zones = (ushort)((response[14] << 8) + response[15]); + dds.SpareAreaFirstPSN = (uint)((response[85] << 16) + (response[86] << 8) + response[87]); + dds.SpareAreaLastPSN = (uint)((response[89] << 16) + (response[90] << 8) + response[91]); + dds.LSN0Location = (uint)((response[93] << 16) + (response[94] << 8) + response[95]); + dds.StartLSNForZone = new uint[dds.Zones]; + + for(int i = 0; i < dds.Zones; i++) + dds.StartLSNForZone[i] = (uint)((response[260 + (i * 4) + 1] << 16) + + (response[260 + (i * 4) + 2] << 8) + response[260 + (i * 4) + 3]); + } + + return dds; + } + + public static string Prettify(DiscDefinitionStructure? dds) + { + if(dds == null) + return null; + + DiscDefinitionStructure decoded = dds.Value; + var sb = new StringBuilder(); + + if(decoded.InProcess) + { + sb.AppendLine("Formatting in progress."); + + if(decoded.Groups == 24) + { + if(decoded.PartialCertification) + sb.AppendLine("Formatting is only using partial certification"); + + if(decoded.FormattingOnlyAGroup) + sb.AppendLine("Only a group is being formatted"); + } + } + + if(decoded.UserCertification) + sb.AppendLine("Disc has been certified by an user"); + + if(decoded.ManufacturerCertification) + sb.AppendLine("Disc has been certified by a manufacturer"); + + sb.AppendFormat("DDS has been updated {0} times", decoded.UpdateCount).AppendLine(); + + if(decoded.Groups == 24) + for(int i = 0; i < decoded.GroupCertificationFlags.Length; i++) + { + if(decoded.GroupCertificationFlags[i].InProcess) + { + sb.AppendFormat("Group {0} is being formatted", i).AppendLine(); + + if(decoded.GroupCertificationFlags[i].PartialCertification) + sb.AppendFormat("Group {0} is being certified partially", i).AppendLine(); + } + + if(decoded.GroupCertificationFlags[i].UserCertification) + sb.AppendFormat("Group {0} has been certified by an user", i).AppendLine(); + } + + if(decoded.Groups != 1) + return sb.ToString(); + + { + sb.AppendFormat("Disc has {0} zones", decoded.Zones).AppendLine(); + + sb.AppendFormat("Primary Spare Area stats at PSN {0:X}h and ends at PSN {1:X}h, inclusively", + decoded.SpareAreaFirstPSN, decoded.SpareAreaLastPSN).AppendLine(); + + sb.AppendFormat("LSN 0 is at PSN {0:X}h", decoded.LSN0Location).AppendLine(); + + for(int i = 0; i < decoded.StartLSNForZone.Length; i++) + sb.AppendFormat("Zone {0} starts at LSN {1}", i, decoded.StartLSNForZone[i]).AppendLine(); + } + + return sb.ToString(); + } + + public static string Prettify(byte[] response) => Prettify(Decode(response)); + + public struct DiscDefinitionStructure + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + + /// Bytes 4 to 5 DDS Identifier = 0x0A0A + public ushort Identifier; + /// Byte 6 Reserved + public byte Reserved3; + /// Byte 7, bit 7 If set, formatting is in process + public bool InProcess; + /// Byte 7, bit 6 If set, formatting is using partial certification Only in ECMA-272 + public bool PartialCertification; + /// Byte 7, bit 5 If set, only a group is being formatted Only in ECMA-272 + public bool FormattingOnlyAGroup; + /// Byte 7, bits 4 to 2 Reserved + public byte Reserved4; + /// Byte 7, bit 1 If set, disk has been certified by a user + public bool UserCertification; + /// Byte 7, bit 0 If set, disk has been certified by a manufacturer + public bool ManufacturerCertification; + /// Bytes 8 to 11 How many times the DDS has been updated + public uint UpdateCount; + /// Bytes 12 to 13 How many groups the disk has 24 for ECMA-272 1 for ECMA-330 + public ushort Groups; + /// Bytes 14 to 15 How many zones the disk has Only in ECMA-330 + public ushort Zones; + /// Bytes 14 to 19 in ECMA-272 Bytes 16 to 83 in ECMA-330 Reserved + public byte[] Reserved; + /// Bytes 20 to 43 Group certification flags + public GroupCertificationFlag[] GroupCertificationFlags; + + /// Bytes 85 to 87 Location of first sector in the Primary Spare Area + public uint SpareAreaFirstPSN; + /// Bytes 89 to 91 Location of first sector in the Primary Spare Area + public uint SpareAreaLastPSN; + /// Bytes 93 to 95 PSN for LSN 0 + public uint LSN0Location; + /// The starting LSN of each zone + public uint[] StartLSNForZone; + } + + public struct GroupCertificationFlag + { + /// Bit 7 If set, formatting of this group is in process + public bool InProcess; + /// Bit 6 If set, formatting is using partial certification + public bool PartialCertification; + /// Bits 5 to 2 Reserved + public byte Reserved1; + /// Bit 1 If set, this group has been certified by user + public bool UserCertification; + /// Bit 0 Reserved + public bool Reserved2; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/DVD/DMI.cs b/Aaru.Decoders/DVD/DMI.cs new file mode 100644 index 000000000..eff6af19f --- /dev/null +++ b/Aaru.Decoders/DVD/DMI.cs @@ -0,0 +1,67 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : DMI.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes DVD Disc Manufacturer Information. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.Decoders.DVD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + // ECMA 365 + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class DMI + { + public struct DiscManufacturingInformation + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to 2052 Disc Manufacturing Information + public byte[] DMI; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/DVD/Enums.cs b/Aaru.Decoders/DVD/Enums.cs new file mode 100644 index 000000000..7e4956cec --- /dev/null +++ b/Aaru.Decoders/DVD/Enums.cs @@ -0,0 +1,182 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Enums.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Contains various DVD enumerations. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.Decoders.DVD +{ + #region Public enumerations + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum DiskCategory : byte + { + /// DVD-ROM. Version 1 is ECMA-267 and ECMA-268. + DVDROM = 0, + /// DVD-RAM. Version 1 is ECMA-272. Version 6 is ECMA-330. + DVDRAM = 1, + /// DVD-R. Version 1 is ECMA-279. Version 5 is ECMA-359. Version 6 is ECMA-382. + DVDR = 2, + /// DVD-RW. Version 2 is ECMA-338. Version 3 is ECMA-384. + DVDRW = 3, + /// HD DVD-ROM + HDDVDROM = 4, + /// HD DVD-RAM + HDDVDRAM = 5, + /// HD DVD-R + HDDVDR = 6, + /// HD DVD-RW + HDDVDRW = 7, + /// UMD. Version 0 is ECMA-365. + UMD = 8, + /// DVD+RW. Version 1 is ECMA-274. Version 2 is ECMA-337. Version 3 is ECMA-371. + DVDPRW = 9, + /// DVD+R. Version 1 is ECMA-349. + DVDPR = 10, + /// DVD+RW DL. Version 1 is ECMA-374. + DVDPRWDL = 13, + /// DVD+R DL. Version 1 is ECMA-364. + DVDPRDL = 14, + /// According to standards this value is reserved. It's used by Nintendo GODs and WODs. + Nintendo = 15 + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum MaximumRateField : byte + { + /// 2.52 Mbps + TwoMbps = 0x00, + /// 5.04 Mbps + FiveMbps = 0x01, + /// 10.08 Mbps + TenMbps = 0x02, + /// 20.16 Mbps + TwentyMbps = 0x03, + /// 30.24 Mbps + ThirtyMbps = 0x04, Unspecified = 0x0F + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum LayerTypeFieldMask : byte + { + Embossed = 0x01, Recordable = 0x02, Rewritable = 0x04, + Reserved = 0x08 + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum LinearDensityField : byte + { + /// 0.267 μm/bit + TwoSix = 0x00, + /// 0.293 μm/bit + TwoNine = 0x01, + /// 0.409 to 0.435 μm/bit + FourZero = 0x02, + /// 0.280 to 0.291 μm/bit + TwoEight = 0x04, + /// 0.153 μm/bit + OneFive = 0x05, + /// 0.130 to 0.140 μm/bit + OneThree = 0x06, + /// 0.353 μm/bit + ThreeFive = 0x08 + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum TrackDensityField : byte + { + /// 0.74 μm/track + Seven = 0x00, + /// 0.80 μm/track + Eight = 0x01, + /// 0.615 μm/track + Six = 0x02, + /// 0.40 μm/track + Four = 0x03, + /// 0.34 μm/track + Three = 0x04 + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum CopyrightType : byte + { + /// There is no copy protection + NoProtection = 0x00, + /// Copy protection is CSS/CPPM + CSS = 0x01, + /// Copy protection is CPRM + CPRM = 0x02, + /// Copy protection is AACS + AACS = 0x10 + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum WPDiscTypes : byte + { + /// Should not write without a cartridge + DoNotWrite = 0x00, + /// Can write without a cartridge + CanWrite = 0x01, Reserved1 = 0x02, Reserved2 = 0x03 + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum DVDSize + { + /// 120 mm + OneTwenty = 0, + /// 80 mm + Eighty = 1 + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum DVDRAMDiscType + { + /// Shall not be recorded without a case + Cased = 0, + /// May be recorded without a case or within one + Uncased = 1 + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum DVDLayerStructure + { + Unspecified = 0, InvertedStack = 1, TwoP = 2, + Reserved = 3 + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum DVDRecordingSpeed + { + None = 0, Two = 0, Four = 0x10, + Six = 0x20, Eight = 0x30, Ten = 0x40, + Twelve = 0x50 + } + #endregion +} \ No newline at end of file diff --git a/Aaru.Decoders/DVD/Layers.cs b/Aaru.Decoders/DVD/Layers.cs new file mode 100644 index 000000000..265b9df88 --- /dev/null +++ b/Aaru.Decoders/DVD/Layers.cs @@ -0,0 +1,139 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Layers.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Records DVD layers structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.Decoders.DVD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + // ECMA 365 + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class Layers + { + public struct LayerCapacity + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4, bit 7 If set, L0 capacity is immutable + public bool InitStatus; + /// Byte 4, bits 6 to 0 Reserved + public byte Reserved3; + /// Byte 5 Reserved + public byte Reserved4; + /// Byte 6 Reserved + public byte Reserved5; + /// Byte 7 Reserved + public byte Reserved6; + /// Byte 8 to 11 L0 Data Area Capacity + public uint Capacity; + } + + public struct MiddleZoneStartAddress + { + /// Bytes 0 to 1 Data length = 10 + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4, bit 7 If set, L0 shifter middle area is immutable + public bool InitStatus; + /// Byte 4, bits 6 to 0 Reserved + public byte Reserved3; + /// Byte 5 Reserved + public byte Reserved4; + /// Byte 6 Reserved + public byte Reserved5; + /// Byte 7 Reserved + public byte Reserved6; + /// Byte 8 to 11 Start LBA of Shifted Middle Area on L0 + public uint ShiftedMiddleAreaStartAddress; + } + + public struct JumpIntervalSize + { + /// Bytes 0 to 1 Data length = 10 + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4 Reserved + public byte Reserved3; + /// Byte 5 Reserved + public byte Reserved4; + /// Byte 6 Reserved + public byte Reserved5; + /// Byte 7 Reserved + public byte Reserved6; + /// Byte 8 to 11 Jump Interval size for the Regular Interval Layer Jump + public uint Size; + } + + public struct ManualLayerJumpAddress + { + /// Bytes 0 to 1 Data length = 10 + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4 Reserved + public byte Reserved3; + /// Byte 5 Reserved + public byte Reserved4; + /// Byte 6 Reserved + public byte Reserved5; + /// Byte 7 Reserved + public byte Reserved6; + /// Byte 8 to 11 LBA for the manual layer jump + public uint LBA; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/DVD/PFI.cs b/Aaru.Decoders/DVD/PFI.cs new file mode 100644 index 000000000..d4cab72da --- /dev/null +++ b/Aaru.Decoders/DVD/PFI.cs @@ -0,0 +1,1563 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : PFI.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Records DVD Physical Format Information. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.CommonTypes; +using Aaru.Helpers; + +namespace Aaru.Decoders.DVD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + // ECMA 267: 120 mm DVD - Read-Only Disk + // ECMA 268: 80 mm DVD - Read-Only Disk + // ECMA 272: 120 mm DVD Rewritable Disk (DVD-RAM) + // ECMA 274: Data Interchange on 120 mm Optical Disk using +RW Format - Capacity: 3,0 Gbytes and 6,0 Gbytes + // ECMA 279: 80 mm (1,23 Gbytes per side) and 120 mm (3,95 Gbytes per side) DVD-Recordable Disk (DVD-R) + // ECMA 330: 120 mm (4,7 Gbytes per side) and 80 mm (1,46 Gbytes per side) DVD Rewritable Disk (DVD-RAM) + // ECMA 337: Data Interchange on 120 mm and 80 mm Optical Disk using +RW Format - Capacity: 4,7 and 1,46 Gbytes per Side + // ECMA 338: 80 mm (1,46 Gbytes per side) and 120 mm (4,70 Gbytes per side) DVD Re-recordable Disk (DVD-RW) + // ECMA 349: Data Interchange on 120 mm and 80 mm Optical Disk using +R Format - Capacity: 4,7 and 1,46 Gbytes per Side + // ECMA 359: 80 mm (1,46 Gbytes per side) and 120 mm (4,70 Gbytes per side) DVD Recordable Disk (DVD-R) + // ECMA 364: Data Interchange on 120 mm and 80 mm Optical Disk using +R DL Format - Capacity 8,55 and 2,66 Gbytes per Side + // ECMA 365: Data Interchange on 60 mm Read-Only ODC - Capacity: 1,8 Gbytes (UMD™) + // ECMA 371: Data Interchange on 120 mm and 80 mm Optical Disk using +RW HS Format - Capacity 4,7 and 1,46 Gbytes per side + // ECMA 374: Data Interchange on 120 mm and 80 mm Optical Disk using +RW DL Format - Capacity 8,55 and 2,66 Gbytes per side + // ECMA 382: 120 mm (8,54 Gbytes per side) and 80 mm (2,66 Gbytes per side) DVD Recordable Disk for Dual Layer (DVD-R for DL) + // ECMA 384: 120 mm (8,54 Gbytes per side) and 80 mm (2,66 Gbytes per side) DVD Re-recordable Disk for Dual Layer (DVD-RW for DL) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class PFI + { + public static PhysicalFormatInformation? Decode(byte[] response, MediaType mediaType) + { + if(response == null) + return null; + + if(response.Length == 2048) + { + byte[] tmp2 = new byte[2052]; + Array.Copy(response, 0, tmp2, 4, 2048); + response = tmp2; + } + + if(response.Length < 2052) + return null; + + var pfi = new PhysicalFormatInformation(); + byte[] tmp; + + pfi.DataLength = (ushort)((response[0] << 8) + response[1]); + pfi.Reserved1 = response[2]; + pfi.Reserved2 = response[3]; + + // Common + pfi.DiskCategory = (DiskCategory)((response[4] & 0xF0) >> 4); + pfi.PartVersion = (byte)(response[4] & 0x0F); + pfi.DiscSize = (DVDSize)((response[5] & 0xF0) >> 4); + pfi.MaximumRate = (MaximumRateField)(response[5] & 0x0F); + pfi.Reserved3 |= (response[6] & 0x80) == 0x80; + pfi.Layers = (byte)((response[6] & 0x60) >> 5); + pfi.TrackPath |= (response[6] & 0x08) == 0x08; + pfi.LayerType = (LayerTypeFieldMask)(response[6] & 0x07); + pfi.LinearDensity = (LinearDensityField)((response[7] & 0xF0) >> 4); + pfi.TrackDensity = (TrackDensityField)(response[7] & 0x0F); + + pfi.DataAreaStartPSN = + (uint)((response[8] << 24) + (response[9] << 16) + (response[10] << 8) + response[11]); + + pfi.DataAreaEndPSN = + (uint)((response[12] << 24) + (response[13] << 16) + (response[14] << 8) + response[15]); + + pfi.Layer0EndPSN = (uint)((response[16] << 24) + (response[17] << 16) + (response[18] << 8) + response[19]); + + pfi.BCA |= (response[20] & 0x80) == 0x80; + + pfi.RecordedBookType = pfi.DiskCategory; + + if(mediaType != MediaType.DVDROM) + { + switch(mediaType) + { + case MediaType.DVDPR: + pfi.DiskCategory = DiskCategory.DVDPR; + + break; + case MediaType.DVDPRDL: + pfi.DiskCategory = DiskCategory.DVDPRDL; + + break; + case MediaType.DVDPRW: + pfi.DiskCategory = DiskCategory.DVDPRW; + + break; + case MediaType.DVDPRWDL: + pfi.DiskCategory = DiskCategory.DVDPRWDL; + + break; + case MediaType.DVDRDL: + pfi.DiskCategory = DiskCategory.DVDR; + + if(pfi.PartVersion < 6) + pfi.PartVersion = 6; + + break; + case MediaType.DVDR: + pfi.DiskCategory = DiskCategory.DVDR; + + if(pfi.PartVersion > 5) + pfi.PartVersion = 5; + + break; + case MediaType.DVDRAM: + pfi.DiskCategory = DiskCategory.DVDRAM; + + break; + case MediaType.DVDRWDL: + pfi.DiskCategory = DiskCategory.DVDRW; + + if(pfi.PartVersion < 15) + pfi.PartVersion = 15; + + break; + case MediaType.DVDRW: + pfi.DiskCategory = DiskCategory.DVDRW; + + if(pfi.PartVersion > 14) + pfi.PartVersion = 14; + + break; + + case MediaType.HDDVDR: + pfi.DiskCategory = DiskCategory.HDDVDR; + + break; + case MediaType.HDDVDRAM: + pfi.DiskCategory = DiskCategory.HDDVDRAM; + + break; + case MediaType.HDDVDROM: + pfi.DiskCategory = DiskCategory.HDDVDROM; + + break; + case MediaType.HDDVDRW: + pfi.DiskCategory = DiskCategory.HDDVDRW; + + break; + case MediaType.GOD: + pfi.DiscSize = DVDSize.Eighty; + pfi.DiskCategory = DiskCategory.Nintendo; + + break; + case MediaType.WOD: + pfi.DiscSize = DVDSize.OneTwenty; + pfi.DiskCategory = DiskCategory.Nintendo; + + break; + case MediaType.UMD: + pfi.DiskCategory = DiskCategory.UMD; + + break; + } + } + + switch(pfi.DiskCategory) + { + // UMD + case DiskCategory.UMD: + pfi.MediaAttribute = (ushort)((response[21] << 8) + response[22]); + + break; + + // DVD-RAM + case DiskCategory.DVDRAM: + pfi.DiscType = (DVDRAMDiscType)response[36]; + + if(pfi.PartVersion == 1) + { + pfi.Velocity = response[52]; + pfi.ReadPower = response[53]; + pfi.PeakPower = response[54]; + pfi.BiasPower = response[55]; + pfi.FirstPulseStart = response[56]; + pfi.FirstPulseEnd = response[57]; + pfi.MultiPulseDuration = response[58]; + pfi.LastPulseStart = response[59]; + pfi.LastPulseEnd = response[60]; + pfi.BiasPowerDuration = response[61]; + pfi.PeakPowerGroove = response[62]; + pfi.BiasPowerGroove = response[63]; + pfi.FirstPulseStartGroove = response[64]; + pfi.FirstPulseEndGroove = response[65]; + pfi.MultiplePulseDurationGroove = response[66]; + pfi.LastPulseStartGroove = response[67]; + pfi.LastPulseEndGroove = response[68]; + pfi.BiasPowerDurationGroove = response[69]; + } + else if(pfi.PartVersion >= 6) + { + pfi.Velocity = response[504]; + pfi.ReadPower = response[505]; + pfi.AdaptativeWritePulseControlFlag |= (response[506] & 0x80) == 0x80; + pfi.PeakPower = response[507]; + pfi.BiasPower1 = response[508]; + pfi.BiasPower2 = response[509]; + pfi.BiasPower3 = response[510]; + pfi.PeakPowerGroove = response[511]; + pfi.BiasPower1Groove = response[512]; + pfi.BiasPower2Groove = response[513]; + pfi.BiasPower3Groove = response[514]; + pfi.FirstPulseEnd = response[515]; + pfi.FirstPulseDuration = response[516]; + pfi.MultiPulseDuration = response[518]; + pfi.LastPulseStart = response[519]; + pfi.BiasPower2Duration = response[520]; + pfi.FirstPulseStart3TSpace3T = response[521]; + pfi.FirstPulseStart4TSpace3T = response[522]; + pfi.FirstPulseStart5TSpace3T = response[523]; + pfi.FirstPulseStartSpace3T = response[524]; + pfi.FirstPulseStart3TSpace4T = response[525]; + pfi.FirstPulseStart4TSpace4T = response[526]; + pfi.FirstPulseStart5TSpace4T = response[527]; + pfi.FirstPulseStartSpace4T = response[528]; + pfi.FirstPulseStart3TSpace5T = response[529]; + pfi.FirstPulseStart4TSpace5T = response[530]; + pfi.FirstPulseStart5TSpace5T = response[531]; + pfi.FirstPulseStartSpace5T = response[532]; + pfi.FirstPulseStart3TSpace = response[533]; + pfi.FirstPulseStart4TSpace = response[534]; + pfi.FirstPulseStart5TSpace = response[535]; + pfi.FirstPulseStartSpace = response[536]; + pfi.FirstPulse3TStartTSpace3T = response[537]; + pfi.FirstPulse4TStartTSpace3T = response[538]; + pfi.FirstPulse5TStartTSpace3T = response[539]; + pfi.FirstPulseStartTSpace3T = response[540]; + pfi.FirstPulse3TStartTSpace4T = response[541]; + pfi.FirstPulse4TStartTSpace4T = response[542]; + pfi.FirstPulse5TStartTSpace4T = response[543]; + pfi.FirstPulseStartTSpace4T = response[544]; + pfi.FirstPulse3TStartTSpace5T = response[545]; + pfi.FirstPulse4TStartTSpace5T = response[546]; + pfi.FirstPulse5TStartTSpace5T = response[547]; + pfi.FirstPulseStartTSpace5T = response[548]; + pfi.FirstPulse3TStartTSpace = response[549]; + pfi.FirstPulse4TStartTSpace = response[550]; + pfi.FirstPulse5TStartTSpace = response[551]; + pfi.FirstPulseStartTSpace = response[552]; + tmp = new byte[48]; + Array.Copy(response, 553, tmp, 0, 48); + pfi.DiskManufacturer = StringHandlers.SpacePaddedToString(tmp); + tmp = new byte[16]; + Array.Copy(response, 601, tmp, 0, 16); + pfi.DiskManufacturerSupplementary = StringHandlers.SpacePaddedToString(tmp); + pfi.WritePowerControlParams = new byte[2]; + pfi.WritePowerControlParams[0] = response[617]; + pfi.WritePowerControlParams[1] = response[618]; + pfi.PowerRatioLandThreshold = response[619]; + pfi.TargetAsymmetry = response[620]; + pfi.TemporaryPeakPower = response[621]; + pfi.TemporaryBiasPower1 = response[622]; + pfi.TemporaryBiasPower2 = response[623]; + pfi.TemporaryBiasPower3 = response[624]; + pfi.PowerRatioGrooveThreshold = response[625]; + pfi.PowerRatioLandThreshold6T = response[626]; + pfi.PowerRatioGrooveThreshold6T = response[627]; + } + + break; + + // DVD-R and DVD-RW + case DiskCategory.DVDR when pfi.PartVersion < 6: + case DiskCategory.DVDRW when pfi.PartVersion < 15: + pfi.CurrentBorderOutSector = + (uint)((response[36] << 24) + (response[37] << 16) + (response[38] << 8) + response[39]); + + pfi.NextBorderInSector = + (uint)((response[40] << 24) + (response[41] << 16) + (response[42] << 8) + response[43]); + + break; + + // DVD+RW + case DiskCategory.DVDPRW: + pfi.RecordingVelocity = response[36]; + pfi.ReadPowerMaxVelocity = response[37]; + pfi.PIndMaxVelocity = response[38]; + pfi.PMaxVelocity = response[39]; + pfi.E1MaxVelocity = response[40]; + pfi.E2MaxVelocity = response[41]; + pfi.YTargetMaxVelocity = response[42]; + pfi.ReadPowerRefVelocity = response[43]; + pfi.PIndRefVelocity = response[44]; + pfi.PRefVelocity = response[45]; + pfi.E1RefVelocity = response[46]; + pfi.E2RefVelocity = response[47]; + pfi.YTargetRefVelocity = response[48]; + pfi.ReadPowerMinVelocity = response[49]; + pfi.PIndMinVelocity = response[50]; + pfi.PMinVelocity = response[51]; + pfi.E1MinVelocity = response[52]; + pfi.E2MinVelocity = response[53]; + pfi.YTargetMinVelocity = response[54]; + + break; + } + + // DVD+R, DVD+RW, DVD+R DL and DVD+RW DL + if(pfi.DiskCategory == DiskCategory.DVDPR || + pfi.DiskCategory == DiskCategory.DVDPRW || + pfi.DiskCategory == DiskCategory.DVDPRDL || + pfi.DiskCategory == DiskCategory.DVDPRWDL) + { + pfi.VCPS |= (response[20] & 0x40) == 0x40; + pfi.ApplicationCode = response[21]; + pfi.ExtendedInformation = response[22]; + tmp = new byte[8]; + Array.Copy(response, 23, tmp, 0, 8); + pfi.DiskManufacturerID = StringHandlers.CToString(tmp); + tmp = new byte[3]; + Array.Copy(response, 31, tmp, 0, 3); + pfi.MediaTypeID = StringHandlers.CToString(tmp); + + pfi.ProductRevision = pfi.DiskCategory == DiskCategory.DVDPRDL ? (byte)(response[34] & 0x3F) + : response[34]; + + pfi.PFIUsedInADIP = response[35]; + } + + switch(pfi.DiskCategory) + { + // DVD+RW + case DiskCategory.DVDPRW when pfi.PartVersion == 2: + pfi.TopFirstPulseDuration = response[55]; + pfi.MultiPulseDuration = response[56]; + pfi.FirstPulseLeadTime = response[57]; + pfi.EraseLeadTimeRefVelocity = response[58]; + pfi.EraseLeadTimeUppVelocity = response[59]; + + break; + + // DVD+R and DVD+R DL + case DiskCategory.DVDPR: + case DiskCategory.DVDPRDL: + pfi.PrimaryVelocity = response[36]; + pfi.UpperVelocity = response[37]; + pfi.Wavelength = response[38]; + pfi.NormalizedPowerDependency = response[39]; + pfi.MaximumPowerAtPrimaryVelocity = response[40]; + pfi.PindAtPrimaryVelocity = response[41]; + pfi.BtargetAtPrimaryVelocity = response[42]; + pfi.MaximumPowerAtUpperVelocity = response[43]; + pfi.PindAtUpperVelocity = response[44]; + pfi.BtargetAtUpperVelocity = response[45]; + pfi.FirstPulseDuration4TPrimaryVelocity = response[46]; + pfi.FirstPulseDuration3TPrimaryVelocity = response[47]; + pfi.MultiPulseDurationPrimaryVelocity = response[48]; + pfi.LastPulseDurationPrimaryVelocity = response[49]; + pfi.FirstPulseLeadTime4TPrimaryVelocity = response[50]; + pfi.FirstPulseLeadTime3TPrimaryVelocity = response[51]; + pfi.FirstPulseLeadingEdgePrimaryVelocity = response[52]; + pfi.FirstPulseDuration4TUpperVelocity = response[53]; + pfi.FirstPulseDuration3TUpperVelocity = response[54]; + pfi.MultiPulseDurationUpperVelocity = response[55]; + pfi.LastPulseDurationUpperVelocity = response[56]; + pfi.FirstPulseLeadTime4TUpperVelocity = response[57]; + pfi.FirstPulseLeadTime3TUpperVelocity = response[58]; + pfi.FirstPulseLeadingEdgeUpperVelocity = response[59]; + + break; + } + + switch(pfi.DiskCategory) + { + // DVD+R DL + case DiskCategory.DVDPRDL: + pfi.LayerStructure = (DVDLayerStructure)((response[34] & 0xC0) >> 6); + + break; + + // DVD+RW DL + case DiskCategory.DVDPRWDL: + pfi.BasicPrimaryVelocity = response[36]; + pfi.MaxReadPowerPrimaryVelocity = response[37]; + pfi.PindPrimaryVelocity = response[38]; + pfi.PPrimaryVelocity = response[39]; + pfi.E1PrimaryVelocity = response[40]; + pfi.E2PrimaryVelocity = response[41]; + pfi.YtargetPrimaryVelocity = response[42]; + pfi.BOptimumPrimaryVelocity = response[43]; + pfi.TFirstPulseDuration = response[46]; + pfi.TMultiPulseDuration = response[47]; + pfi.FirstPulseLeadTimeAnyRun = response[48]; + pfi.FirstPulseLeadTimeRun3T = response[49]; + pfi.LastPulseLeadTimeAnyRun = response[50]; + pfi.LastPulseLeadTime3T = response[51]; + pfi.LastPulseLeadTime4T = response[52]; + pfi.ErasePulseLeadTimeAny = response[53]; + pfi.ErasePulseLeadTime3T = response[54]; + pfi.ErasePulseLeadTime4T = response[55]; + + break; + + // DVD-R DL and DVD-RW DL + case DiskCategory.DVDR when pfi.PartVersion >= 6: + case DiskCategory.DVDRW when pfi.PartVersion >= 15: + pfi.MaxRecordingSpeed = (DVDRecordingSpeed)response[21]; + pfi.MinRecordingSpeed = (DVDRecordingSpeed)response[22]; + pfi.RecordingSpeed1 = (DVDRecordingSpeed)response[23]; + pfi.RecordingSpeed2 = (DVDRecordingSpeed)response[24]; + pfi.RecordingSpeed3 = (DVDRecordingSpeed)response[25]; + pfi.RecordingSpeed4 = (DVDRecordingSpeed)response[26]; + pfi.RecordingSpeed5 = (DVDRecordingSpeed)response[27]; + pfi.RecordingSpeed6 = (DVDRecordingSpeed)response[28]; + pfi.RecordingSpeed7 = (DVDRecordingSpeed)response[29]; + pfi.Class = response[30]; + pfi.ExtendedVersion = response[31]; + + pfi.CurrentBorderOutSector = + (uint)((response[36] << 24) + (response[37] << 16) + (response[38] << 8) + response[39]); + + pfi.NextBorderInSector = + (uint)((response[40] << 24) + (response[41] << 16) + (response[42] << 8) + response[43]); + + pfi.PreRecordedControlDataInv |= (response[44] & 0x01) == 0x01; + pfi.PreRecordedLeadIn |= (response[44] & 0x02) == 0x02; + pfi.PreRecordedLeadOut |= (response[44] & 0x08) == 0x08; + pfi.ARCharLayer1 = (byte)(response[45] & 0x0F); + pfi.TrackPolarityLayer1 = (byte)((response[45] & 0xF0) >> 4); + + break; + } + + return pfi; + } + + public static string Prettify(PhysicalFormatInformation? pfi) + { + if(pfi == null) + return null; + + PhysicalFormatInformation decoded = pfi.Value; + var sb = new StringBuilder(); + + string sizeString; + + switch(decoded.DiscSize) + { + case DVDSize.Eighty: + sizeString = "80mm"; + + break; + case DVDSize.OneTwenty: + sizeString = "120mm"; + + break; + default: + sizeString = $"unknown size identifier {decoded.DiscSize}"; + + break; + } + + string categorySentence = "Disc is a {0} {1} version {2}"; + + switch(decoded.DiskCategory) + { + case DiskCategory.DVDROM: + sb.AppendFormat(categorySentence, sizeString, "DVD-ROM", decoded.PartVersion).AppendLine(); + + switch(decoded.DiscSize) + { + case DVDSize.OneTwenty when decoded.PartVersion == 1: + sb.AppendLine("Disc claims conformation to ECMA-267"); + + break; + case DVDSize.Eighty when decoded.PartVersion == 1: + sb.AppendLine("Disc claims conformation to ECMA-268"); + + break; + } + + break; + case DiskCategory.DVDRAM: + sb.AppendFormat(categorySentence, sizeString, "DVD-RAM", decoded.PartVersion).AppendLine(); + + switch(decoded.PartVersion) + { + case 1: + sb.AppendLine("Disc claims conformation to ECMA-272"); + + break; + case 6: + sb.AppendLine("Disc claims conformation to ECMA-330"); + + break; + } + + break; + case DiskCategory.DVDR: + if(decoded.PartVersion >= 6) + sb.AppendFormat(categorySentence, sizeString, "DVD-R DL", decoded.PartVersion).AppendLine(); + else + sb.AppendFormat(categorySentence, sizeString, "DVD-R", decoded.PartVersion).AppendLine(); + + switch(decoded.PartVersion) + { + case 1: + sb.AppendLine("Disc claims conformation to ECMA-279"); + + break; + case 5: + sb.AppendLine("Disc claims conformation to ECMA-359"); + + break; + case 6: + sb.AppendLine("Disc claims conformation to ECMA-382"); + + break; + } + + break; + case DiskCategory.DVDRW: + if(decoded.PartVersion >= 15) + sb.AppendFormat(categorySentence, sizeString, "DVD-RW DL", decoded.PartVersion).AppendLine(); + else + sb.AppendFormat(categorySentence, sizeString, "DVD-RW", decoded.PartVersion).AppendLine(); + + switch(decoded.PartVersion) + { + case 2: + sb.AppendLine("Disc claims conformation to ECMA-338"); + + break; + case 3: + sb.AppendLine("Disc claims conformation to ECMA-384"); + + break; + } + + break; + case DiskCategory.UMD: + if(decoded.DiscSize == DVDSize.OneTwenty) + sb.AppendFormat(categorySentence, "60mm", "UMD", decoded.PartVersion).AppendLine(); + else + sb.AppendFormat(categorySentence, "invalid size", "UMD", decoded.PartVersion).AppendLine(); + + switch(decoded.PartVersion) + { + case 0: + sb.AppendLine("Disc claims conformation to ECMA-365"); + + break; + } + + break; + case DiskCategory.DVDPRW: + sb.AppendFormat(categorySentence, sizeString, "DVD+RW", decoded.PartVersion).AppendLine(); + + switch(decoded.PartVersion) + { + case 1: + sb.AppendLine("Disc claims conformation to ECMA-274"); + + break; + case 2: + sb.AppendLine("Disc claims conformation to ECMA-337"); + + break; + case 3: + sb.AppendLine("Disc claims conformation to ECMA-371"); + + break; + } + + break; + case DiskCategory.DVDPR: + sb.AppendFormat(categorySentence, sizeString, "DVD+R", decoded.PartVersion).AppendLine(); + + switch(decoded.PartVersion) + { + case 1: + sb.AppendLine("Disc claims conformation to ECMA-349"); + + break; + } + + break; + case DiskCategory.DVDPRWDL: + sb.AppendFormat(categorySentence, sizeString, "DVD+RW DL", decoded.PartVersion).AppendLine(); + + switch(decoded.PartVersion) + { + case 1: + sb.AppendLine("Disc claims conformation to ECMA-374"); + + break; + } + + break; + case DiskCategory.DVDPRDL: + sb.AppendFormat(categorySentence, sizeString, "DVD+R DL", decoded.PartVersion).AppendLine(); + + switch(decoded.PartVersion) + { + case 1: + sb.AppendLine("Disc claims conformation to ECMA-364"); + + break; + } + + break; + case DiskCategory.Nintendo: + if(decoded.PartVersion == 15) + if(decoded.DiscSize == DVDSize.Eighty) + sb.AppendLine("Disc is a Nintendo Gamecube Optical Disc (GOD)"); + else if(decoded.DiscSize == DVDSize.OneTwenty) + sb.AppendLine("Disc is a Nintendo Wii Optical Disc (WOD)"); + else + goto default; + else + goto default; + + break; + case DiskCategory.HDDVDROM: + sb.AppendFormat(categorySentence, sizeString, "HD DVD-ROM", decoded.PartVersion).AppendLine(); + + break; + case DiskCategory.HDDVDRAM: + sb.AppendFormat(categorySentence, sizeString, "HD DVD-RAM", decoded.PartVersion).AppendLine(); + + break; + case DiskCategory.HDDVDR: + sb.AppendFormat(categorySentence, sizeString, "HD DVD-R", decoded.PartVersion).AppendLine(); + + break; + case DiskCategory.HDDVDRW: + sb.AppendFormat(categorySentence, sizeString, "HD DVD-RW", decoded.PartVersion).AppendLine(); + + break; + default: + sb.AppendFormat(categorySentence, sizeString, "unknown disc type", decoded.PartVersion). + AppendLine(); + + break; + } + + if(decoded.RecordedBookType != decoded.DiskCategory) + { + string bookTypeSentence = "Disc book type is {0}"; + + switch(decoded.RecordedBookType) + { + case DiskCategory.DVDROM: + sb.AppendFormat(bookTypeSentence, "DVD-ROM").AppendLine(); + + break; + case DiskCategory.DVDRAM: + sb.AppendFormat(bookTypeSentence, "DVD-RAM").AppendLine(); + + break; + case DiskCategory.DVDR: + if(decoded.PartVersion >= 6) + sb.AppendFormat(bookTypeSentence, "DVD-R DL").AppendLine(); + else + sb.AppendFormat(bookTypeSentence, "DVD-R").AppendLine(); + + break; + case DiskCategory.DVDRW: + if(decoded.PartVersion >= 15) + sb.AppendFormat(bookTypeSentence, "DVD-RW DL").AppendLine(); + else + sb.AppendFormat(bookTypeSentence, "DVD-RW").AppendLine(); + + break; + case DiskCategory.UMD: + sb.AppendFormat(bookTypeSentence, "UMD").AppendLine(); + + break; + case DiskCategory.DVDPRW: + sb.AppendFormat(bookTypeSentence, "DVD+RW").AppendLine(); + + break; + case DiskCategory.DVDPR: + sb.AppendFormat(bookTypeSentence, "DVD+R").AppendLine(); + + break; + case DiskCategory.DVDPRWDL: + sb.AppendFormat(bookTypeSentence, "DVD+RW DL").AppendLine(); + + break; + case DiskCategory.DVDPRDL: + sb.AppendFormat(bookTypeSentence, "DVD+R DL").AppendLine(); + + break; + case DiskCategory.HDDVDROM: + sb.AppendFormat(bookTypeSentence, "HD DVD-ROM").AppendLine(); + + break; + case DiskCategory.HDDVDRAM: + sb.AppendFormat(bookTypeSentence, "HD DVD-RAM").AppendLine(); + + break; + case DiskCategory.HDDVDR: + sb.AppendFormat(bookTypeSentence, "HD DVD-R").AppendLine(); + + break; + case DiskCategory.HDDVDRW: + sb.AppendFormat(bookTypeSentence, "HD DVD-RW").AppendLine(); + + break; + default: + sb.AppendFormat(bookTypeSentence, "unknown").AppendLine(); + + break; + } + } + + switch(decoded.MaximumRate) + { + case MaximumRateField.TwoMbps: + sb.AppendLine("Disc maximum transfer rate is 2,52 Mbit/sec."); + + break; + case MaximumRateField.FiveMbps: + sb.AppendLine("Disc maximum transfer rate is 5,04 Mbit/sec."); + + break; + case MaximumRateField.TenMbps: + sb.AppendLine("Disc maximum transfer rate is 10,08 Mbit/sec."); + + break; + case MaximumRateField.TwentyMbps: + sb.AppendLine("Disc maximum transfer rate is 20,16 Mbit/sec."); + + break; + case MaximumRateField.ThirtyMbps: + sb.AppendLine("Disc maximum transfer rate is 30,24 Mbit/sec."); + + break; + case MaximumRateField.Unspecified: + sb.AppendLine("Disc maximum transfer rate is unspecified."); + + break; + default: + sb.AppendFormat("Disc maximum transfer rate is specified by unknown key {0}", decoded.MaximumRate). + AppendLine(); + + break; + } + + sb.AppendFormat("Disc has {0} layers", decoded.Layers + 1).AppendLine(); + + if(decoded.TrackPath && + decoded.Layers == 1) + sb.AppendLine("Layers are in parallel track path"); + else if(!decoded.TrackPath && + decoded.Layers == 1) + sb.AppendLine("Layers are in opposite track path"); + + switch(decoded.LinearDensity) + { + case LinearDensityField.TwoSix: + sb.AppendLine("Pitch size is 0,267 μm/bit"); + + break; + case LinearDensityField.TwoNine: + sb.AppendLine("Pitch size is 0,147 μm/bit"); + + break; + case LinearDensityField.FourZero: + sb.AppendLine("Pitch size is between 0,409 μm/bit and 0,435 μm/bit"); + + break; + case LinearDensityField.TwoEight: + sb.AppendLine("Pitch size is between 0,140 μm/bit and 0,148 μm/bit"); + + break; + case LinearDensityField.OneFive: + sb.AppendLine("Pitch size is 0,153 μm/bit"); + + break; + case LinearDensityField.OneThree: + sb.AppendLine("Pitch size is between 0,130 μm/bit and 0,140 μm/bit"); + + break; + case LinearDensityField.ThreeFive: + sb.AppendLine("Pitch size is 0,353 μm/bit"); + + break; + default: + sb.AppendFormat("Unknown pitch size key {0}", decoded.LinearDensity).AppendLine(); + + break; + } + + switch(decoded.TrackDensity) + { + case TrackDensityField.Seven: + sb.AppendLine("Track size is 0,74 μm"); + + break; + case TrackDensityField.Eight: + sb.AppendLine("Track size is 0,80 μm"); + + break; + case TrackDensityField.Six: + sb.AppendLine("Track size is 0,615 μm"); + + break; + case TrackDensityField.Four: + sb.AppendLine("Track size is 0,40 μm"); + + break; + case TrackDensityField.Three: + sb.AppendLine("Track size is 0,34 μm"); + + break; + default: + sb.AppendFormat("Unknown track size key {0}", decoded.LinearDensity).AppendLine(); + + break; + } + + if(decoded.DataAreaStartPSN > 0) + if(decoded.DataAreaEndPSN > 0) + { + sb.AppendFormat("Data area starts at PSN {0:X}h", decoded.DataAreaStartPSN).AppendLine(); + sb.AppendFormat("Data area ends at PSN {0:X}h", decoded.DataAreaEndPSN).AppendLine(); + + if(decoded.Layers == 1 && + !decoded.TrackPath) + sb.AppendFormat("Layer 0 ends at PSN {0:X}h", decoded.Layer0EndPSN).AppendLine(); + } + else + sb.AppendLine("Disc is empty"); + else + sb.AppendLine("Disc is empty"); + + if(decoded.BCA) + sb.AppendLine("Disc has a burst cutting area"); + + switch(decoded.DiskCategory) + { + case DiskCategory.UMD: + sb.AppendFormat("Media attribute is {0}", decoded.MediaAttribute).AppendLine(); + + break; + case DiskCategory.DVDRAM: + switch(decoded.DiscType) + { + case DVDRAMDiscType.Cased: + sb.AppendLine("Disc shall be recorded with a case"); + + break; + case DVDRAMDiscType.Uncased: + sb.AppendLine("Disc can be recorded with or without a case"); + + break; + default: + sb.AppendFormat("Unknown DVD-RAM case type key {0}", decoded.DiscType).AppendLine(); + + break; + } + + if(decoded.PartVersion == 6) + { + sb.AppendFormat("Disc manufacturer is {0}", ManufacturerFromDVDRAM(decoded.DiskManufacturer)). + AppendLine(); + + sb.AppendFormat("Disc manufacturer supplementary information is {0}", + decoded.DiskManufacturerSupplementary).AppendLine(); + } + + break; + case DiskCategory.DVDR when decoded.PartVersion < 6: + case DiskCategory.DVDRW when decoded.PartVersion < 15: + sb.AppendFormat("Current Border-Out first sector is PSN {0:X}h", decoded.CurrentBorderOutSector). + AppendLine(); + + sb.AppendFormat("Next Border-In first sector is PSN {0:X}h", decoded.NextBorderInSector). + AppendLine(); + + break; + case DiskCategory.DVDPR: + case DiskCategory.DVDPRW: + case DiskCategory.DVDPRDL: + case DiskCategory.DVDPRWDL: + if(decoded.VCPS) + sb.AppendLine("Disc contains extended information for VCPS"); + + sb.AppendFormat("Disc application code is {0}", decoded.ApplicationCode).AppendLine(); + + sb.AppendFormat("Disc manufacturer is {0}", ManufacturerFromDVDPlusID(decoded.DiskManufacturerID)). + AppendLine(); + + sb.AppendFormat("Disc media type is {0}", decoded.MediaTypeID).AppendLine(); + sb.AppendFormat("Disc product revision is {0}", decoded.ProductRevision).AppendLine(); + + break; + } + + if((decoded.DiskCategory != DiskCategory.DVDR || decoded.PartVersion < 6) && + (decoded.DiskCategory != DiskCategory.DVDRW || decoded.PartVersion < 15)) + return sb.ToString(); + + sb.AppendFormat("Current RMD in extra Border zone starts at PSN {0:X}h", decoded.CurrentRMDExtraBorderPSN). + AppendLine(); + + sb.AppendFormat("PFI in extra Border zone starts at PSN {0:X}h", decoded.PFIExtraBorderPSN).AppendLine(); + + if(!decoded.PreRecordedControlDataInv) + sb.AppendLine("Control Data Zone is pre-recorded"); + + if(decoded.PreRecordedLeadIn) + sb.AppendLine("Lead-In is pre-recorded"); + + if(decoded.PreRecordedLeadOut) + sb.AppendLine("Lead-Out is pre-recorded"); + + return sb.ToString(); + } + + public static string Prettify(byte[] response, MediaType mediaType) => Prettify(Decode(response, mediaType)); + + public static string ManufacturerFromDVDRAM(string manufacturerId) + { + switch(manufacturerId) + { + default: return ManufacturerFromDVDPlusID(manufacturerId); + } + } + + public static string ManufacturerFromDVDPlusID(string manufacturerId) + { + string manufacturer = ""; + + switch(manufacturerId) + { + case "CMC MAG": + manufacturer = "CMC Magnetics Corporation"; + + break; + case "INFOME": + manufacturer = "InfoMedia Inc."; + + break; + case "RITEK": + manufacturer = "Ritek Co."; + + break; + case "RICOHJPN": + manufacturer = "Ricoh Company, Ltd."; + + break; + case "ISSM": + manufacturer = "Info Source Digital Media (Zhongshan) Co., Ltd."; + + break; + case "LD": + manufacturer = "Lead Data Inc."; + + break; + case "MAXELL": + manufacturer = "Hitachi Maxell, Ltd."; + + break; + case "MCC": + manufacturer = "Mitsubishi Kagaku Media Co., LTD."; + + break; + case "PRODISC": + manufacturer = "Prodisc Technology Inc."; + + break; + case "Philips": + case "PHILIPS": + + manufacturer = "Philips Components"; + + break; + case "YUDEN000": + manufacturer = "Taiyo Yuden Company Ltd."; + + break; + case "AML": + manufacturer = "Avic Umedisc HK Ltd."; + + break; + case "DAXON": + manufacturer = "Daxon Technology Inc."; + + break; + case "FTI": + manufacturer = "Falcon Technologies International L.L.C."; + + break; + case "GSC503": + manufacturer = "Gigastore Corporation"; + + break; + case "MBIPG101": + manufacturer = "Moser Baer India Ltd."; + + break; + case "OPTODISC": + manufacturer = "OptoDisc Ltd."; + + break; + case "SONY": + manufacturer = "Sony Corporation"; + + break; + case "TDK": + manufacturer = "TDK Corporation"; + + break; + case "SENTINEL": + manufacturer = "Sentinel B.V."; + + break; + case "BeAll000": + manufacturer = "BeALL Developers, Inc."; + + break; + case "MPOMEDIA": + manufacturer = "MPO Disque Compact"; + + break; + case "IMC JPN": + manufacturer = "Intermedia Co., Ltd."; + + break; + case "INFODISC": + manufacturer = "InfoDisc Technology Co., Ltd."; + + break; + case "WFKA11": + manufacturer = "Wealth Fair Investment Inc."; + + break; + case "MAM": + manufacturer = "Manufacturing Advanced Media Europe"; + + break; + case "VDSPMSAB": + manufacturer = "Interaxia Digital Storage Materials AG"; + + break; + case "KIC00000": + manufacturer = "Advanced Media Corporation"; + + break; + case "MJC": + manufacturer = "Megan Media Holdings Berhad"; + + break; + case "MUST": + manufacturer = "Must Technology Co., Ltd."; + + break; + case "IS02": + manufacturer = "Infosmart Technology Ltd."; + + break; + case "DDDessau": + manufacturer = "Digital Disc Dessau GmbH"; + + break; + case "SKYMEDIA": + manufacturer = "Sky Media Manufacturing S.A."; + + break; + case "MICRON": + manufacturer = "Eastgate Technology Ltd."; + + break; + case "VIVA": + manufacturer = "Viva Optical Disc Manufacturing Ltd."; + + break; + case "EMDPZ3": + manufacturer = "E-TOP Mediatek Inc."; + + break; + case "LGEP16": + manufacturer = "LG Electronics Inc."; + + break; + case "POS": + manufacturer = "POSTECH Corporation"; + + break; + case "Dvsn+160": + manufacturer = "Digital Storage Technology Co., Ltd."; + + break; + case "ODMS": + manufacturer = "VDL Optical Disc Manufacturing Systems"; + + break; + } + + return manufacturer != "" ? $"{manufacturer} (\"{manufacturerId}\")" : $"\"{manufacturerId}\""; + } + + public struct PhysicalFormatInformation + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + + #region PFI common to all + /// Byte 4, bits 7 to 4 Disk category field + public DiskCategory DiskCategory; + /// Byte 4, bits 3 to 0 Media version + public byte PartVersion; + /// Byte 5, bits 7 to 4 120mm if 0, 80mm if 1. If UMD (60mm) 0 also. Reserved rest of values + public DVDSize DiscSize; + /// Byte 5, bits 3 to 0 Maximum data rate + public MaximumRateField MaximumRate; + /// Byte 6, bit 7 Reserved + public bool Reserved3; + /// Byte 6, bits 6 to 5 Number of layers + public byte Layers; + /// Byte 6, bit 4 Track path + public bool TrackPath; + /// Byte 6, bits 3 to 0 Layer type + public LayerTypeFieldMask LayerType; + /// Byte 7, bits 7 to 4 Linear density field + public LinearDensityField LinearDensity; + /// Byte 7, bits 3 to 0 Track density field + public TrackDensityField TrackDensity; + /// Bytes 8 to 11 PSN where Data Area starts + public uint DataAreaStartPSN; + /// Bytes 12 to 15 PSN where Data Area ends + public uint DataAreaEndPSN; + /// Bytes 16 to 19 PSN where Data Area ends in Layer 0 + public uint Layer0EndPSN; + /// + /// Byte 20, bit 7 True if BCA exists. GC/Wii discs do not have this bit set, but there is a BCA, making it + /// unreadable in normal DVD drives + /// + public bool BCA; + /// Byte 20, bits 6 to 0 Reserved + public byte Reserved4; + #endregion PFI common to all + + #region UMD PFI + /// Bytes 21 to 22 UMD only, media attribute, application-defined, part of media specific in rest of discs + public ushort MediaAttribute; + #endregion UMD PFI + + #region DVD-RAM PFI + /// Byte 36 Disc type, respecting case recordability + public DVDRAMDiscType DiscType; + #endregion DVD-RAM PFI + + #region DVD-RAM PFI, Version 0001b + /// Byte 52 Byte 504 in Version 0110b Linear velocity, in tenths of m/s + public byte Velocity; + /// Byte 53 Byte 505 in Version 0110b Read power on disk surface, tenths of mW + public byte ReadPower; + /// Byte 54 Byte 507 in Version 0110b Peak power on disk surface for recording land tracks + public byte PeakPower; + /// Byte 55 Bias power on disk surface for recording land tracks + public byte BiasPower; + /// Byte 56 First pulse starting time for recording on land tracks, ns + public byte FirstPulseStart; + /// Byte 57 Byte 515 in Version 0110b First pulse ending time for recording on land tracks + public byte FirstPulseEnd; + /// Byte 58 Byte 518 in Version 0110b Multiple-pulse duration time for recording on land tracks + public byte MultiplePulseDuration; + /// Byte 59 Byte 519 in Version 0110b Last pulse starting time for recording on land tracks + public byte LastPulseStart; + /// Byte 60 Las pulse ending time for recording on land tracks + public byte LastPulseEnd; + /// Byte 61 Bias power duration for recording on land tracks + public byte BiasPowerDuration; + /// Byte 62 Byte 511 on Version 0110b Peak power for recording on groove tracks + public byte PeakPowerGroove; + /// Byte 63 Bias power for recording on groove tracks + public byte BiasPowerGroove; + /// Byte 64 First pulse starting time on groove tracks + public byte FirstPulseStartGroove; + /// Byte 65 First pulse ending time on groove tracks + public byte FirstPulseEndGroove; + /// Byte 66 Multiple-pulse duration time on groove tracks + public byte MultiplePulseDurationGroove; + /// Byte 67 Last pulse starting time on groove tracks + public byte LastPulseStartGroove; + /// Byte 68 Last pulse ending time on groove tracks + public byte LastPulseEndGroove; + /// Byte 69 Bias power duration for recording on groove tracks + public byte BiasPowerDurationGroove; + #endregion DVD-RAM PFI, Version 0001b + + #region DVD-R PFI, DVD-RW PFI + /// Bytes 36 to 39 Sector number of the first sector of the current Border Out + public uint CurrentBorderOutSector; + /// Bytes 40 to 43 Sector number of the first sector of the next Border In + public uint NextBorderInSector; + #endregion DVD-R PFI, DVD-RW PFI + + #region DVD+RW PFI + /// Byte 36 Linear velocities 0 = CLV from 4,90 m/s to 6,25 m/s 1 = CAV from 3,02 m/s to 7,35 m/s + public byte RecordingVelocity; + /// Byte 37 Maximum read power in milliwatts at maximum velocity mW = 20 * (value - 1) + public byte ReadPowerMaxVelocity; + /// Byte 38 Indicative value of Ptarget in mW at maximum velocity + public byte PIndMaxVelocity; + /// Byte 39 Peak power multiplication factor at maximum velocity + public byte PMaxVelocity; + /// Byte 40 Bias1/write power ration at maximum velocity + public byte E1MaxVelocity; + /// Byte 41 Bias2/write power ration at maximum velocity + public byte E2MaxVelocity; + /// Byte 42 Target value for γ, γtarget at the maximum velocity + public byte YTargetMaxVelocity; + /// Byte 43 Maximum read power in milliwatts at reference velocity (4,90 m/s) mW = 20 * (value - 1) + public byte ReadPowerRefVelocity; + /// Byte 44 Indicative value of Ptarget in mW at reference velocity (4,90 m/s) + public byte PIndRefVelocity; + /// Byte 45 Peak power multiplication factor at reference velocity (4,90 m/s) + public byte PRefVelocity; + /// Byte 46 Bias1/write power ration at reference velocity (4,90 m/s) + public byte E1RefVelocity; + /// Byte 47 Bias2/write power ration at reference velocity (4,90 m/s) + public byte E2RefVelocity; + /// Byte 48 Target value for γ, γtarget at the reference velocity (4,90 m/s) + public byte YTargetRefVelocity; + /// Byte 49 Maximum read power in milliwatts at minimum velocity mW = 20 * (value - 1) + public byte ReadPowerMinVelocity; + /// Byte 50 Indicative value of Ptarget in mW at minimum velocity + public byte PIndMinVelocity; + /// Byte 51 Peak power multiplication factor at minimum velocity + public byte PMinVelocity; + /// Byte 52 Bias1/write power ration at minimum velocity + public byte E1MinVelocity; + /// Byte 53 Bias2/write power ration at minimum velocity + public byte E2MinVelocity; + /// Byte 54 Target value for γ, γtarget at the minimum velocity + public byte YTargetMinVelocity; + #endregion DVD+RW PFI + + #region DVD-RAM PFI, version 0110b + /// Byte 506, bit 7 Mode of adaptative write pulse control + public bool AdaptativeWritePulseControlFlag; + /// Byte 508 Bias power 1 on disk surface for recording land tracks + public byte BiasPower1; + /// Byte 509 Bias power 2 on disk surface for recording land tracks + public byte BiasPower2; + /// Byte 510 Bias power 3 on disk surface for recording land tracks + public byte BiasPower3; + /// Byte 512 Bias power 1 on disk surface for recording groove tracks + public byte BiasPower1Groove; + /// Byte 513 Bias power 2 on disk surface for recording groove tracks + public byte BiasPower2Groove; + /// Byte 514 Bias power 3 on disk surface for recording groove tracks + public byte BiasPower3Groove; + /// Byte 516 First pulse duration + public byte FirstPulseDuration; + /// Byte 520 Bias power 2 duration on land tracks at Velocity 1 + public byte BiasPower2Duration; + /// Byte 521 First pulse start time, at Mark 3T and Leading Space 3T + public byte FirstPulseStart3TSpace3T; + /// Byte 522 First pulse start time, at Mark 4T and Leading Space 3T + public byte FirstPulseStart4TSpace3T; + /// Byte 523 First pulse start time, at Mark 5T and Leading Space 3T + public byte FirstPulseStart5TSpace3T; + /// Byte 524 First pulse start time, at Mark >5T and Leading Space 3T + public byte FirstPulseStartSpace3T; + /// Byte 525 First pulse start time, at Mark 3T and Leading Space 4T + public byte FirstPulseStart3TSpace4T; + /// Byte 526 First pulse start time, at Mark 4T and Leading Space 4T + public byte FirstPulseStart4TSpace4T; + /// Byte 527 First pulse start time, at Mark 5T and Leading Space 4T + public byte FirstPulseStart5TSpace4T; + /// Byte 528 First pulse start time, at Mark >5T and Leading Space 4T + public byte FirstPulseStartSpace4T; + /// Byte 529 First pulse start time, at Mark 3T and Leading Space 5T + public byte FirstPulseStart3TSpace5T; + /// Byte 530 First pulse start time, at Mark 4T and Leading Space 5T + public byte FirstPulseStart4TSpace5T; + /// Byte 531 First pulse start time, at Mark 5T and Leading Space 5T + public byte FirstPulseStart5TSpace5T; + /// Byte 532 First pulse start time, at Mark >5T and Leading Space 5T + public byte FirstPulseStartSpace5T; + /// Byte 533 First pulse start time, at Mark 3T and Leading Space >5T + public byte FirstPulseStart3TSpace; + /// Byte 534 First pulse start time, at Mark 4T and Leading Space >5T + public byte FirstPulseStart4TSpace; + /// Byte 535 First pulse start time, at Mark 5T and Leading Space >5T + public byte FirstPulseStart5TSpace; + /// Byte 536 First pulse start time, at Mark >5T and Leading Space >5T + public byte FirstPulseStartSpace; + /// Byte 537 First pulse start time, at Mark 3T and Trailing Space 3T + public byte FirstPulse3TStartTSpace3T; + /// Byte 538 First pulse start time, at Mark 4T and Trailing Space 3T + public byte FirstPulse4TStartTSpace3T; + /// Byte 539 First pulse start time, at Mark 5T and Trailing Space 3T + public byte FirstPulse5TStartTSpace3T; + /// Byte 540 First pulse start time, at Mark >5T and Trailing Space 3T + public byte FirstPulseStartTSpace3T; + /// Byte 541 First pulse start time, at Mark 3T and Trailing Space 4T + public byte FirstPulse3TStartTSpace4T; + /// Byte 542 First pulse start time, at Mark 4T and Trailing Space 4T + public byte FirstPulse4TStartTSpace4T; + /// Byte 543 First pulse start time, at Mark 5T and Trailing Space 4T + public byte FirstPulse5TStartTSpace4T; + /// Byte 544 First pulse start time, at Mark >5T and Trailing Space 4T + public byte FirstPulseStartTSpace4T; + /// Byte 545 First pulse start time, at Mark 3T and Trailing Space 5T + public byte FirstPulse3TStartTSpace5T; + /// Byte 546 First pulse start time, at Mark 4T and Trailing Space 5T + public byte FirstPulse4TStartTSpace5T; + /// Byte 547 First pulse start time, at Mark 5T and Trailing Space 5T + public byte FirstPulse5TStartTSpace5T; + /// Byte 548 First pulse start time, at Mark >5T and Trailing Space 5T + public byte FirstPulseStartTSpace5T; + /// Byte 549 First pulse start time, at Mark 3T and Trailing Space >5T + public byte FirstPulse3TStartTSpace; + /// Byte 550 First pulse start time, at Mark 4T and Trailing Space >5T + public byte FirstPulse4TStartTSpace; + /// Byte 551 First pulse start time, at Mark 5T and Trailing Space >5T + public byte FirstPulse5TStartTSpace; + /// Byte 552 First pulse start time, at Mark >5T and Trailing Space >5T + public byte FirstPulseStartTSpace; + /// Bytes 553 to 600 Disk manufacturer's name, space-padded + public string DiskManufacturer; + /// Bytes 601 to 616 Disk manufacturer's supplementary information + public string DiskManufacturerSupplementary; + /// Bytes 617 to 627 Write power control parameters + public byte[] WritePowerControlParams; + /// Byte 619 Ratio of peak power for land tracks to threshold peak power for land tracks + public byte PowerRatioLandThreshold; + /// Byte 620 Target asymmetry + public byte TargetAsymmetry; + /// Byte 621 Temporary peak power + public byte TemporaryPeakPower; + /// Byte 622 Temporary bias power 1 + public byte TemporaryBiasPower1; + /// Byte 623 Temporary bias power 2 + public byte TemporaryBiasPower2; + /// Byte 624 Temporary bias power 3 + public byte TemporaryBiasPower3; + /// Byte 625 Ratio of peak power for groove tracks to threshold peak power for groove tracks + public byte PowerRatioGrooveThreshold; + /// Byte 626 Ratio of peak power for land tracks to threshold 6T peak power for land tracks + public byte PowerRatioLandThreshold6T; + /// Byte 627 Ratio of peak power for groove tracks to threshold 6T peak power for groove tracks + public byte PowerRatioGrooveThreshold6T; + #endregion DVD-RAM PFI, version 0110b + + #region DVD+RW PFI, DVD+R PFI, DVD+R DL PFI and DVD+RW DL PFI + /// Byte 20, bit 6 If set indicates data zone contains extended information for VCPS + public bool VCPS; + /// Byte 21 Indicates restricted usage disk + public byte ApplicationCode; + /// Byte 22 Bitmap of extended information block presence + public byte ExtendedInformation; + /// Bytes 23 to 30 Disk manufacturer ID, null-padded + public string DiskManufacturerID; + /// Bytes 31 to 33 Media type ID, null-padded + public string MediaTypeID; + /// Byte 34 Product revision number + public byte ProductRevision; + /// Byte 35 Indicates how many bytes, up to 63, are used in ADIP's PFI + public byte PFIUsedInADIP; + #endregion DVD+RW PFI, DVD+R PFI, DVD+R DL PFI and DVD+RW DL PFI + + #region DVD+RW PFI, version 0010b + /// Byte 55 Ttop first pulse duration + public byte TopFirstPulseDuration; + /// Byte 56 Tmp multi pulse duration + public byte MultiPulseDuration; + /// Byte 57 dTtop first pulse lead time + public byte FirstPulseLeadTime; + /// Byte 58 dTera erase lead time at reference velocity + public byte EraseLeadTimeRefVelocity; + /// Byte 59 dTera erase lead time at upper velocity + public byte EraseLeadTimeUppVelocity; + #endregion DVD+RW PFI, version 0010b + + #region DVD+R PFI version 0001b and DVD+R DL PFI version 0001b + /// Byte 36 Primary recording velocity for the basic write strategy + public byte PrimaryVelocity; + /// Byte 37 Upper recording velocity for the basic write strategy + public byte UpperVelocity; + /// Byte 38 Wavelength λIND + public byte Wavelength; + /// Byte 39 Normalized write power dependency on wavelength (dP/dλ)/(PIND/λIND) + public byte NormalizedPowerDependency; + /// Byte 40 Maximum read power at primary velocity + public byte MaximumPowerAtPrimaryVelocity; + /// Byte 41 Pind at primary velocity + public byte PindAtPrimaryVelocity; + /// Byte 42 βtarget at primary velocity + public byte BtargetAtPrimaryVelocity; + /// Byte 43 Maximum read power at upper velocity + public byte MaximumPowerAtUpperVelocity; + /// Byte 44 Pind at primary velocity + public byte PindAtUpperVelocity; + /// Byte 45 βtarget at upper velocity + public byte BtargetAtUpperVelocity; + /// Byte 46 Ttop (≥4T) first pulse duration for cm∗ ≥4T at Primary velocity + public byte FirstPulseDuration4TPrimaryVelocity; + /// Byte 47 Ttop (=3T) first pulse duration for cm∗ =3T at Primary velocity + public byte FirstPulseDuration3TPrimaryVelocity; + /// Byte 48 Tmp multi pulse duration at Primary velocity + public byte MultiPulseDurationPrimaryVelocity; + /// Byte 49 Tlp last pulse duration at Primary velocity + public byte LastPulseDurationPrimaryVelocity; + /// Byte 50 dTtop (≥4T) first pulse lead time for cm∗ ≥4T at Primary velocity + public byte FirstPulseLeadTime4TPrimaryVelocity; + /// Byte 51 dTtop (=3T) first pulse lead time for cm∗ =3T at Primary velocity + public byte FirstPulseLeadTime3TPrimaryVelocity; + /// Byte 52 dTle first pulse leading edge shift for ps∗ =3T at Primary velocity + public byte FirstPulseLeadingEdgePrimaryVelocity; + /// Byte 53 Ttop (≥4T) first pulse duration for cm∗ ≥4T at Upper velocity + public byte FirstPulseDuration4TUpperVelocity; + /// Byte 54 Ttop (=3T) first pulse duration for cm∗ =3T at Upper velocity + public byte FirstPulseDuration3TUpperVelocity; + /// Byte 55 Tmp multi pulse duration at Upper velocity + public byte MultiPulseDurationUpperVelocity; + /// Byte 56 Tlp last pulse duration at Upper velocity + public byte LastPulseDurationUpperVelocity; + /// Byte 57 dTtop (≥4T) first pulse lead time for cm∗ ≥4T at Upper velocity + public byte FirstPulseLeadTime4TUpperVelocity; + /// Byte 58 dTtop (=3T) first pulse lead time for cm∗ =3T at Upper velocity + public byte FirstPulseLeadTime3TUpperVelocity; + /// Byte 59 dTle first pulse leading edge shift for ps∗ =3T at Upper velocity + public byte FirstPulseLeadingEdgeUpperVelocity; + #endregion DVD+R PFI version 0001b and DVD+R DL PFI version 0001b + + #region DVD+R DL PFI version 0001b + /// Byte 34, bits 7 to 6 + public DVDLayerStructure LayerStructure; + #endregion DVD+R DL PFI version 0001b + + #region DVD+RW DL PFI + /// Byte 36 Primary recording velocity for the basic write strategy + public byte BasicPrimaryVelocity; + /// Byte 37 Maximum read power at Primary velocity + public byte MaxReadPowerPrimaryVelocity; + /// Byte 38 PIND at Primary velocity + public byte PindPrimaryVelocity; + /// Byte 39 ρ at Primary velocity + public byte PPrimaryVelocity; + /// Byte 40 ε1 at Primary velocity + public byte E1PrimaryVelocity; + /// Byte 41 ε2 at Primary velocity + public byte E2PrimaryVelocity; + /// Byte 42 γtarget at Primary velocity + public byte YtargetPrimaryVelocity; + /// Byte 43 β optimum at Primary velocity + public byte BOptimumPrimaryVelocity; + /// Byte 46 Ttop first pulse duration + public byte TFirstPulseDuration; + /// Byte 47 Tmp multi pulse duration + public byte TMultiPulseDuration; + /// Byte 48 dTtop first pulse lead/lag time for any runlength ≥ 4T + public byte FirstPulseLeadTimeAnyRun; + /// Byte 49 dTtop,3 first pulse lead/lag time for runlengths = 3T + public byte FirstPulseLeadTimeRun3T; + /// Byte 50 dTlp last pulse lead/lag time for any runlength ≥ 5T + public byte LastPulseLeadTimeAnyRun; + /// Byte 51 dTlp,3 last pulse lead/lag time for runlengths = 3T + public byte LastPulseLeadTime3T; + /// Byte 52 dTlp,4 last pulse lead/lag time for runlengths = 4T + public byte LastPulseLeadTime4T; + /// Byte 53 dTera erase lead/lag time when preceding mark length ≥ 5T + public byte ErasePulseLeadTimeAny; + /// Byte 54 dTera,3 erase lead/lag time when preceding mark length = 3T + public byte ErasePulseLeadTime3T; + /// Byte 55 dTera,4 erase lead/lag time when preceding mark length = 4T + public byte ErasePulseLeadTime4T; + #endregion DVD+RW DL PFI + + #region DVD-R DL PFI and DVD-RW DL PFI + /// Byte 21 Maximum recording speed + public DVDRecordingSpeed MaxRecordingSpeed; + /// Byte 22 Minimum recording speed + public DVDRecordingSpeed MinRecordingSpeed; + /// Byte 23 Another recording speed + public DVDRecordingSpeed RecordingSpeed1; + /// Byte 24 Another recording speed + public DVDRecordingSpeed RecordingSpeed2; + /// Byte 25 Another recording speed + public DVDRecordingSpeed RecordingSpeed3; + /// Byte 26 Another recording speed + public DVDRecordingSpeed RecordingSpeed4; + /// Byte 27 Another recording speed + public DVDRecordingSpeed RecordingSpeed5; + /// Byte 28 Another recording speed + public DVDRecordingSpeed RecordingSpeed6; + /// Byte 29 Another recording speed + public DVDRecordingSpeed RecordingSpeed7; + /// Byte 30 Class + public byte Class; + /// Byte 31 Extended version. 0x30 = ECMA-382, 0x20 = ECMA-384 + public byte ExtendedVersion; + /// Byte 36 Start sector number of current RMD in Extra Border Zone + public uint CurrentRMDExtraBorderPSN; + /// Byte 40 Start sector number of Physical Format Information blocks in Extra Border Zone + public uint PFIExtraBorderPSN; + /// Byte 44, bit 0 If NOT set, Control Data Zone is pre-recorded + public bool PreRecordedControlDataInv; + /// Byte 44 bit 1 Lead-in Zone is pre-recorded + public bool PreRecordedLeadIn; + /// Byte 44 bit 3 Lead-out Zone is pre-recorded + public bool PreRecordedLeadOut; + /// Byte 45 bits 0 to 3 AR characteristic of LPP on Layer 1 + public byte ARCharLayer1; + /// Byte 45 bits 4 to 7 Tracking polarity on Layer 1 + public byte TrackPolarityLayer1; + #endregion DVD-R DL PFI and DVD-RW DL PFI + + public DiskCategory RecordedBookType; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/DVD/PRI.cs b/Aaru.Decoders/DVD/PRI.cs new file mode 100644 index 000000000..d25a3b1f8 --- /dev/null +++ b/Aaru.Decoders/DVD/PRI.cs @@ -0,0 +1,625 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : PRI.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes DVD pre-recorded information. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Helpers; + +namespace Aaru.Decoders.DVD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + // ECMA 365 + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class PRI + { + public static PreRecordedInformation? Decode(byte[] response) + { + if(response == null) + return null; + + if(response.Length < 67) + return null; + + var pri = new PreRecordedInformation(); + byte[] tmp; + + pri.DataLength = (ushort)((response[0] << 8) + response[1]); + pri.Reserved1 = response[2]; + pri.Reserved2 = response[3]; + + pri.FieldId1 = response[4]; + pri.FieldId2 = response[12]; + pri.FieldId3 = response[20]; + pri.FieldId4 = response[28]; + pri.FieldId5 = response[36]; + + if(pri.FieldId1 != 1 || + pri.FieldId2 != 2 || + pri.FieldId3 != 3 || + pri.FieldId4 != 4 || + pri.FieldId5 != 5) + return null; + + pri.DiscApplicationCode = response[5]; + pri.DiscPhysicalCode = response[6]; + pri.LastAddressOfDataRecordableArea = (uint)((response[7] << 16) + (response[8] << 8) + response[9]); + pri.PartVersion = (byte)(response[10] >> 4); + pri.ExtensionCode = (byte)(response[10] & 0xF); + pri.Reserved3 = response[11]; + pri.OPCSuggestedCode = response[13]; + pri.WaveLengthCode = response[14]; + + pri.WriteStrategyCode = + (uint)((response[15] << 24) + (response[16] << 16) + (response[17] << 8) + response[18]); + + pri.Reserved4 = response[19]; + pri.ManufacturerId1 = new byte[6]; + pri.Reserved5 = response[27]; + pri.ManufacturerId2 = new byte[6]; + pri.Reserved6 = response[35]; + pri.ManufacturerId3 = new byte[6]; + pri.Reserved7 = response[43]; + pri.Reserved8 = new byte[response.Length - 44]; + + Array.Copy(response, 21, pri.ManufacturerId1, 0, 6); + Array.Copy(response, 29, pri.ManufacturerId2, 0, 6); + Array.Copy(response, 37, pri.ManufacturerId3, 0, 6); + Array.Copy(response, 44, pri.Reserved8, 0, pri.Reserved8.Length); + + tmp = new byte[18]; + + Array.Copy(response, 21, tmp, 0, 6); + Array.Copy(response, 29, tmp, 6, 6); + + // If RW or has part version or has extension code, 3rd manufacturer ID is a write strategy code + if((pri.DiscPhysicalCode & 0x2) > 0 || + pri.PartVersion > 0 || + pri.ExtensionCode > 0) + pri.WriteStrategyCode2 = + (uint)((response[37] << 24) + (response[38] << 16) + (response[39] << 8) + response[40]); + else + Array.Copy(response, 37, tmp, 12, 6); + + pri.ManufacturerId = StringHandlers.CToString(tmp, Encoding.ASCII).Trim(); + + return pri; + } + + public static string Prettify(PreRecordedInformation? pri) + { + if(pri == null) + return null; + + PreRecordedInformation decoded = pri.Value; + var sb = new StringBuilder(); + + if((decoded.DiscApplicationCode & 0x40) > 0) + { + sb.AppendLine("Disc for unrestricted use."); + + if((decoded.DiscApplicationCode & 0x3F) > 0) + sb.AppendFormat("Invalid purpose field with value {0}", decoded.DiscApplicationCode & 0x3F). + AppendLine(); + else + sb.AppendLine("Consumer purpose disc for use in consumer purpose drives"); + } + else + { + sb.AppendLine("Disc for restricted use."); + + if((decoded.DiscApplicationCode & 0x3F) > 0) + sb.AppendFormat("Disc for use in special drives according with purpose value {0}", + decoded.DiscApplicationCode & 0x3F).AppendLine(); + else + sb.AppendLine("General purpose disc for use in general purpose drives"); + } + + sb.AppendLine((decoded.DiscPhysicalCode & 0x80) > 0 ? "Disc track pitch is 0,74 μm" + : "Unknown track pitch"); + + sb.AppendLine((decoded.DiscPhysicalCode & 0x40) > 0 ? "Reference velocity is 3,49 m/s" + : "Unknown reference velocity"); + + sb.AppendLine((decoded.DiscPhysicalCode & 0x20) > 0 ? "Disc has 80mm diameter" : "Disc has 120mm diameter"); + + sb.AppendLine((decoded.DiscPhysicalCode & 0x10) > 0 ? "Disc reflectivity is between 18% and 30%" + : "Disc reflectivity is between 45% and 85%"); + + sb.AppendLine((decoded.DiscPhysicalCode & 0x04) > 0 ? "Dye is organic" : "Dye is phase change"); + + sb.AppendLine((decoded.DiscPhysicalCode & 0x02) > 0 ? "Disc is RW (rewritable)" : "Disc is R (recordable)"); + + sb.AppendLine((decoded.DiscPhysicalCode & 0x01) > 0 ? "Wavelength is 650nm" : "Unknown wavelength"); + + sb.AppendFormat("Last writable ECC block address: 0x{0:X6}", decoded.LastAddressOfDataRecordableArea). + AppendLine(); + + if(decoded.PartVersion > 0) + sb.AppendFormat("Part version {0}", decoded.PartVersion).AppendLine(); + + bool rw = (decoded.DiscPhysicalCode & 0x02) > 0; + + if(rw) + { + if((decoded.OPCSuggestedCode & 0xF) > 0) + { + double recordingPower = 0; + + switch(decoded.OPCSuggestedCode & 0xF) + { + case 1: + recordingPower = 7.0; + + break; + case 2: + recordingPower = 7.5; + + break; + case 3: + recordingPower = 8.0; + + break; + case 4: + recordingPower = 8.5; + + break; + case 5: + recordingPower = 9.0; + + break; + case 6: + recordingPower = 9.5; + + break; + case 7: + recordingPower = 10.0; + + break; + case 8: + recordingPower = 10.5; + + break; + case 9: + recordingPower = 11.0; + + break; + case 10: + recordingPower = 11.5; + + break; + case 11: + recordingPower = 12.0; + + break; + case 12: + recordingPower = 12.5; + + break; + case 13: + recordingPower = 13.0; + + break; + case 14: + recordingPower = 13.5; + + break; + case 15: + recordingPower = 14.0; + + break; + } + + sb.AppendFormat("Recommended recording power is {0} mW", recordingPower).AppendLine(); + } + else + { + sb.AppendLine("Recording power is not specified"); + } + + if((decoded.WaveLengthCode & 0xF) > 0) + { + double erasingPower = 0; + + switch(decoded.WaveLengthCode & 0xF) + { + case 1: + erasingPower = 0.38; + + break; + case 2: + erasingPower = 0.40; + + break; + case 3: + erasingPower = 0.42; + + break; + case 4: + erasingPower = 0.44; + + break; + case 5: + erasingPower = 0.46; + + break; + case 6: + erasingPower = 0.48; + + break; + case 7: + erasingPower = 0.50; + + break; + case 8: + erasingPower = 0.52; + + break; + case 9: + erasingPower = 0.54; + + break; + case 10: + erasingPower = 0.56; + + break; + case 11: + erasingPower = 0.58; + + break; + case 12: + erasingPower = 0.60; + + break; + case 13: + erasingPower = 0.62; + + break; + case 14: + erasingPower = 0.64; + + break; + case 15: + erasingPower = 0.66; + + break; + } + + sb.AppendFormat("Recommended erasing power ratio is {0} ε", erasingPower).AppendLine(); + } + else + { + sb.AppendLine("Erasing power ratio is not specified"); + } + } + else + { + if((decoded.OPCSuggestedCode & 0xF) > 0) + { + double recordingPower = 0; + + switch(decoded.OPCSuggestedCode & 0xF) + { + case 1: + recordingPower = 6.0; + + break; + case 2: + recordingPower = 6.5; + + break; + case 3: + recordingPower = 7.0; + + break; + case 4: + recordingPower = 7.5; + + break; + case 5: + recordingPower = 8.0; + + break; + case 6: + recordingPower = 8.5; + + break; + case 7: + recordingPower = 9.0; + + break; + case 8: + recordingPower = 9.5; + + break; + case 9: + recordingPower = 10.0; + + break; + case 10: + recordingPower = 10.5; + + break; + case 11: + recordingPower = 11.0; + + break; + case 12: + recordingPower = 11.5; + + break; + case 13: + recordingPower = 12.0; + + break; + } + + sb.AppendFormat("Recommended recording power is {0} mW", recordingPower).AppendLine(); + } + + if(decoded.WaveLengthCode > 0) + { + int wavelength = 0; + + switch(decoded.WaveLengthCode) + { + case 1: + wavelength = 645; + + break; + case 2: + wavelength = 646; + + break; + case 3: + wavelength = 647; + + break; + case 4: + wavelength = 648; + + break; + case 5: + wavelength = 649; + + break; + case 6: + wavelength = 650; + + break; + case 7: + wavelength = 651; + + break; + case 8: + wavelength = 652; + + break; + case 9: + wavelength = 653; + + break; + case 10: + wavelength = 654; + + break; + case 11: + wavelength = 655; + + break; + case 12: + wavelength = 656; + + break; + case 13: + wavelength = 657; + + break; + case 14: + wavelength = 658; + + break; + case 15: + wavelength = 659; + + break; + case 16: + wavelength = 660; + + break; + } + + sb.AppendFormat("Recommended recording power is {0} mW", wavelength).AppendLine(); + } + } + + sb.AppendFormat("Disc manufacturer is {0}", ManufacturerFromPrePit(decoded.ManufacturerId)).AppendLine(); + + return sb.ToString(); + } + + public static string Prettify(byte[] response) => Prettify(Decode(response)); + + public static string ManufacturerFromPrePit(string manufacturerId) + { + string manufacturer = ""; + + // Bad thing is that it also includes a media code... + if(manufacturerId.StartsWith("RITEK", StringComparison.Ordinal)) + manufacturer = "Ritek Co."; + else if(manufacturerId.StartsWith("CMC", StringComparison.Ordinal)) + manufacturer = "CMC Magnetics Corporation"; + else if(manufacturerId.StartsWith("Dvsn-", StringComparison.Ordinal)) + manufacturer = "Digital Storage Technology Co., Ltd."; + else if(manufacturerId.StartsWith("GSC", StringComparison.Ordinal)) + manufacturer = "Gigastore Corporation"; + else if(manufacturerId.StartsWith("INFOMEDIA", StringComparison.Ordinal)) + manufacturer = "InfoMedia Inc."; + else if(manufacturerId.StartsWith("ISSM", StringComparison.Ordinal)) + manufacturer = "Info Source Digital Media (Zhongshan) Co., Ltd."; + else if(manufacturerId.StartsWith("LEADDATA", StringComparison.Ordinal)) + manufacturer = "Lead Data Inc."; + else if(manufacturerId.StartsWith("MCC", StringComparison.Ordinal) || + manufacturerId.StartsWith("MKM", StringComparison.Ordinal)) + manufacturer = "Mitsubishi Kagaku Media Co., LTD."; + else if(manufacturerId.StartsWith("MUST", StringComparison.Ordinal)) + manufacturer = "Must Technology Co., Ltd."; + else if(manufacturerId.StartsWith("MXL", StringComparison.Ordinal)) + manufacturer = "Hitachi Maxell, Ltd."; + else if(manufacturerId.StartsWith("PRINCO", StringComparison.Ordinal)) + manufacturer = "Princo Corporation"; + else if(manufacturerId.StartsWith("Prodisc", StringComparison.Ordinal)) + manufacturer = "Prodisc Technology Inc."; + else if(manufacturerId.StartsWith("SONY", StringComparison.Ordinal) || + manufacturerId.StartsWith("80SONY", StringComparison.Ordinal)) + manufacturer = "Sony Corporation"; + else if(manufacturerId.StartsWith("TCLDS", StringComparison.Ordinal)) + manufacturer = "TCL Technology"; + else if(manufacturerId.StartsWith("TMI", StringComparison.Ordinal)) + manufacturer = "ThaiMedia Co., Ltd. "; + else if(manufacturerId.StartsWith("TY", StringComparison.Ordinal)) + manufacturer = "Taiyo Yuden Company Ltd."; + else if(manufacturerId.StartsWith("UME", StringComparison.Ordinal)) + manufacturer = "Avic Umedisc HK Ltd."; + else if(manufacturerId.StartsWith("DAXON", StringComparison.Ordinal)) + manufacturer = "Daxon Technology Inc."; + else if(manufacturerId.StartsWith("FTI", StringComparison.Ordinal)) + manufacturer = "Falcon Technologies International L.L.C."; + else if(manufacturerId.StartsWith("FUJIFILM", StringComparison.Ordinal)) + manufacturer = "Fuji Photo Film, Co., Ltd."; + else if(manufacturerId.StartsWith("MBI", StringComparison.Ordinal)) + manufacturer = "Moser Baer India Ltd."; + else if(manufacturerId.StartsWith("TT", StringComparison.Ordinal) || + manufacturerId.StartsWith("TDK", StringComparison.Ordinal)) + manufacturer = "TDK Corporation"; + else if(manufacturerId.StartsWith("JVC", StringComparison.Ordinal)) + manufacturer = "Victor Advanced media Co., Ltd."; + else if(manufacturerId.StartsWith("MEI", StringComparison.Ordinal)) + manufacturer = "Matsushita Electric Industrial Co., Ltd."; + else if(manufacturerId.StartsWith("OPTODISC", StringComparison.Ordinal)) + manufacturer = "OptoDisc Ltd."; + else if(manufacturerId.StartsWith("KIC", StringComparison.Ordinal)) + manufacturer = "Advance Media Corporation"; + else if(manufacturerId.StartsWith("IMC", StringComparison.Ordinal)) + manufacturer = "Intermedia Co., Ltd."; + else if(manufacturerId.StartsWith("LGE", StringComparison.Ordinal)) + manufacturer = "LG Electronics Inc."; + else if(manufacturerId.StartsWith("KDT", StringComparison.Ordinal)) + manufacturer = "King Disc Technology Corporation"; + else if(manufacturerId.StartsWith("POS", StringComparison.Ordinal)) + manufacturer = "POSTECH Corporation"; + else if(manufacturerId.StartsWith("VDSPMSAB", StringComparison.Ordinal)) + manufacturer = "Interaxia Digital Storage Materials AG"; + else if(manufacturerId.StartsWith("VANGUARD", StringComparison.Ordinal)) + manufacturer = "Vanguard Disc Inc."; + else if(manufacturerId.StartsWith("MJC", StringComparison.Ordinal)) + manufacturer = "Megan Media Holdings Berhad"; + else if(manufacturerId.StartsWith("DKM", StringComparison.Ordinal) || + manufacturerId.StartsWith("EDMA", StringComparison.Ordinal)) + manufacturer = "E-TOP Mediatek Inc."; + else if(manufacturerId.StartsWith("BeAll", StringComparison.Ordinal)) + manufacturer = "BeALL Developers, Inc."; + + return manufacturer != "" ? $"{manufacturer} (\"{manufacturerId}\")" : $"\"{manufacturerId}\""; + } + + public struct PreRecordedInformation + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4 == 1 + public byte FieldId1; + /// Byte 5 disc application code + public byte DiscApplicationCode; + /// Byte 6 disc physical code + public byte DiscPhysicalCode; + /// Bytes 7 to 9 last address of data recordable area + public uint LastAddressOfDataRecordableArea; + /// Byte 10, bits 7 to 4 part version + public byte PartVersion; + /// Byte 10, bits 3 to 0 extension code + public byte ExtensionCode; + /// Byte 11 reserved + public byte Reserved3; + /// Byte 12 == 2 + public byte FieldId2; + /// Byte 13 OPC suggested code + public byte OPCSuggestedCode; + /// Byte 14 wavelength code or second part of OPC suggested code + public byte WaveLengthCode; + /// Bytes 15 to 18 write strategy code + public uint WriteStrategyCode; + /// Byte 19 reserved + public byte Reserved4; + /// Byte 20 == 3 + public byte FieldId3; + /// Bytes 21 to 26 first part of manufacturer ID + public byte[] ManufacturerId1; + /// Byte 27 + public byte Reserved5; + /// Byte 28 == 4 + public byte FieldId4; + /// Bytes 29 to 34 second part of manufacturer ID + public byte[] ManufacturerId2; + /// Byte 35 reserved + public byte Reserved6; + /// Byte 36 == 5 + public byte FieldId5; + /// Bytes 37 to 42, third part of manufacturer code or write strategy code for RW and R later versions + public byte[] ManufacturerId3; + /// Byte 43 reserved + public byte Reserved7; + /// Bytes 44 to 68 reserved + public byte[] Reserved8; + + public string ManufacturerId; + public uint WriteStrategyCode2; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/DVD/RMD.cs b/Aaru.Decoders/DVD/RMD.cs new file mode 100644 index 000000000..108f4f066 --- /dev/null +++ b/Aaru.Decoders/DVD/RMD.cs @@ -0,0 +1,85 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : RMD.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes DVD RMD. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.Decoders.DVD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + // ECMA 365 + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class RMD + { + public struct LastBorderOutRMD + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to end RMD in last recorded Border-out + public byte[] RMD; + } + + public struct HDMediumStatus + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4, bits 7 to 1 Reserved + public byte Reserved3; + /// Byte 4, bit 0 Test Zone has been extended + public bool ExtendedTestZone; + /// Byte 5 Number of remaining RMDs in RDZ + public byte RemainingRMDs; + /// Bytes 6 to 7 Number of remaining RMDs in current RMZ + public ushort CurrentRemainingRMDs; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/DVD/Spare.cs b/Aaru.Decoders/DVD/Spare.cs new file mode 100644 index 000000000..d8dc6134c --- /dev/null +++ b/Aaru.Decoders/DVD/Spare.cs @@ -0,0 +1,109 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Spare.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes DVD spare area information. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.DVD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class Spare + { + public static SpareAreaInformation? Decode(byte[] response) + { + if(response?.Length != 16) + return null; + + return new SpareAreaInformation + { + DataLength = (ushort)((response[0] << 8) + response[1]), + Reserved1 = response[2], + Reserved2 = response[3], + UnusedPrimaryBlocks = + (uint)((response[4] << 24) + (response[5] << 16) + (response[6] << 8) + response[7]), + UnusedSupplementaryBlocks = + (uint)((response[8] << 24) + (response[9] << 16) + (response[10] << 8) + response[11]), + AllocatedSupplementaryBlocks = + (uint)((response[12] << 24) + (response[13] << 16) + (response[14] << 8) + response[15]) + }; + } + + public static string Prettify(SpareAreaInformation? sai) + { + if(sai == null) + return null; + + SpareAreaInformation decoded = sai.Value; + var sb = new StringBuilder(); + + sb.AppendFormat("{0} unused primary spare blocks", decoded.UnusedPrimaryBlocks).AppendLine(); + sb.AppendFormat("{0} unused supplementary spare blocks", decoded.UnusedSupplementaryBlocks).AppendLine(); + + sb.AppendFormat("{0} allocated supplementary spare blocks", decoded.AllocatedSupplementaryBlocks). + AppendLine(); + + return sb.ToString(); + } + + public static string Prettify(byte[] response) => Prettify(Decode(response)); + + public struct SpareAreaInformation + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to 7 Data length + public uint UnusedPrimaryBlocks; + /// Bytes 8 to 11 Data length + public uint UnusedSupplementaryBlocks; + /// Bytes 12 to 15 Data length + public uint AllocatedSupplementaryBlocks; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/DVD/UDI.cs b/Aaru.Decoders/DVD/UDI.cs new file mode 100644 index 000000000..01ca066d0 --- /dev/null +++ b/Aaru.Decoders/DVD/UDI.cs @@ -0,0 +1,83 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : UDI.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes DVD unique disc identifier. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.Decoders.DVD +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + // ECMA 365 + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class UDI + { + public struct UniqueDiscIdentifier + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4 Reserved + public byte Reserved3; + /// Byte 5 Reserved + public byte Reserved4; + /// Bytes 6 to 7 Random number + public ushort RandomNumber; + /// Byte 8 to 11 Year + public uint Year; + /// Byte 12 to 13 Month + public ushort Month; + /// Byte 14 to 15 Day + public ushort Day; + /// Byte 16 to 17 Hour + public ushort Hour; + /// Byte 18 to 19 Minute + public ushort Minute; + /// Byte 20 to 21 Second + public ushort Second; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/Floppy/Amiga.cs b/Aaru.Decoders/Floppy/Amiga.cs new file mode 100644 index 000000000..ee9f9166a --- /dev/null +++ b/Aaru.Decoders/Floppy/Amiga.cs @@ -0,0 +1,70 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Amiga.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes Commodore Amiga floppy structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; + +namespace Aaru.Decoders.Floppy +{ + /// Methods and structures for Commodore Amiga decoding + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class Amiga + { + public struct Sector + { + /// Set to 0x00 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] zero; + /// Set to 0xA1 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] sync; + /// Set to 0xFF + public byte amiga; + /// Track number + public byte track; + /// Sector number + public byte sector; + /// Remaining sectors til end of writing + public byte remaining; + /// OS dependent tag + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] label; + /// Checksum from to + public uint headerChecksum; + /// Checksum from + public uint dataChecksum; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)] + public byte[] data; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/Floppy/Apple2.cs b/Aaru.Decoders/Floppy/Apple2.cs new file mode 100644 index 000000000..2c54bc96f --- /dev/null +++ b/Aaru.Decoders/Floppy/Apple2.cs @@ -0,0 +1,665 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Apple2.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes Apple ][ floppy structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Aaru.Console; + +namespace Aaru.Decoders.Floppy +{ + /// Methods and structures for Apple ][ floppy decoding + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class Apple2 + { + static readonly byte[] ReadTable5and3 = + { + // 00h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // 10h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // 20h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // 30h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // 40h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // 50h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // 60h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // 70h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // 80h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // 90h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // A0h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x01, 0x02, 0x03, + + // B0h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x05, 0x06, 0xFF, 0xFF, 0x07, 0x08, 0xFF, 0x09, 0x0A, 0x0B, + + // C0h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // D0h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0C, 0x0D, 0xFF, 0xFF, 0x0E, 0x0F, 0xFF, 0x10, 0x11, 0x12, + + // E0h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x13, 0x14, 0xFF, 0x15, 0x16, 0x17, + + // F0h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x18, 0x19, 0x1A, 0xFF, 0xFF, 0x1B, 0x1C, 0xFF, 0x1D, 0x1E, 0x1F + }; + + static readonly byte[] ReadTable6and2 = + { + // 00h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // 10h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // 20h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // 30h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // 40h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // 50h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // 60h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // 70h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // 80h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + + // 90h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x02, 0x03, 0xFF, 0x04, 0x05, 0x06, + + // A0h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x08, 0xFF, 0xFF, 0xFF, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + + // B0h + 0xFF, 0xFF, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0xFF, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, + + // C0h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1B, 0xFF, 0x1C, 0x1D, 0x1E, + + // D0h + 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0x20, 0x21, 0xFF, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + + // E0h + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x29, 0x2A, 0x2B, 0xFF, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, + + // F0h + 0xFF, 0xFF, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0xFF, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F + }; + + /// Decodes the 5and3 encoded data + /// 5and3 encoded data. + public static byte[] Decode5and3(byte[] data) + { + if(data == null || + data.Length != 410) + return null; + + byte[] buffer = new byte[data.Length]; + byte carry = 0; + + for(int i = 0; i < data.Length; i++) + { + carry ^= ReadTable5and3[data[i]]; + buffer[i] = carry; + } + + byte[] output = new byte[256]; + + for(int i = 0; i < 51; i++) + { + byte b1 = buffer[(51 * 3) - i]; + byte b2 = buffer[(51 * 2) - i]; + byte b3 = buffer[51 - i]; + byte b4 = (byte)((((b1 & 2) << 1) | (b2 & 2) | ((b3 & 2) >> 1)) & 0xFF); + byte b5 = (byte)((((b1 & 1) << 2) | ((b2 & 1) << 1) | (b3 & 1)) & 0xFF); + output[250 - (5 * i)] = (byte)(((buffer[i + (51 * 3) + 1] << 3) | ((b1 >> 2) & 0x7)) & 0xFF); + output[251 - (5 * i)] = (byte)(((buffer[i + (51 * 4) + 1] << 3) | ((b2 >> 2) & 0x7)) & 0xFF); + output[252 - (5 * i)] = (byte)(((buffer[i + (51 * 5) + 1] << 3) | ((b3 >> 2) & 0x7)) & 0xFF); + output[253 - (5 * i)] = (byte)(((buffer[i + (51 * 6) + 1] << 3) | b4) & 0xFF); + output[254 - (5 * i)] = (byte)(((buffer[i + (51 * 7) + 1] << 3) | b5) & 0xFF); + } + + output[255] = (byte)(((buffer[409] << 3) | (buffer[0] & 0x7)) & 0xFF); + + return output; + } + + /// Decodes the 6and2 encoded data + /// 6and2 encoded data. + public static byte[] Decode6and2(byte[] data) + { + if(data == null || + data.Length != 342) + return null; + + byte[] buffer = new byte[data.Length]; + byte carry = 0; + + for(int i = 0; i < data.Length; i++) + { + carry ^= ReadTable6and2[data[i]]; + buffer[i] = carry; + } + + byte[] output = new byte[256]; + + for(uint i = 0; i < 256; i++) + { + output[i] = (byte)((buffer[86 + i] << 2) & 0xFF); + + if(i < 86) + { + output[i] |= (byte)(((buffer[i] & 1) << 1) & 0xFF); + output[i] |= (byte)(((buffer[i] & 2) >> 1) & 0xFF); + } + else if(i < 86 * 2) + { + output[i] |= (byte)(((buffer[i - 86] & 4) >> 1) & 0xFF); + output[i] |= (byte)(((buffer[i - 86] & 8) >> 3) & 0xFF); + } + else + { + output[i] |= (byte)(((buffer[i - (86 * 2)] & 0x10) >> 3) & 0xFF); + output[i] |= (byte)(((buffer[i - (86 * 2)] & 0x20) >> 5) & 0xFF); + } + } + + return output; + } + + public static byte[] DecodeSector(RawSector sector) + { + if(sector.addressField.prologue[0] != 0xD5 || + sector.addressField.prologue[1] != 0xAA) + return null; + + // Pre DOS 3.3 + if(sector.addressField.prologue[2] == 0xB5) + return Decode5and3(sector.dataField.data); + + // DOS 3.3 + return sector.addressField.prologue[2] == 0x96 ? Decode6and2(sector.dataField.data) : null; + + // Unknown + + // Not Apple ][ GCR? + } + + public static RawSector MarshalSector(byte[] data, int offset = 0) => MarshalSector(data, out _, offset); + + public static RawSector MarshalSector(byte[] data, out int endOffset, int offset = 0) + { + endOffset = offset; + + // Not an Apple ][ GCR sector + if(data == null || + data.Length < 363) + return null; + + int position = offset; + + try + { + while(position < data.Length) + { + // Prologue found + if(data[position] == 0xD5 && + data[position + 1] == 0xAA) + { + AaruConsole.DebugWriteLine("Apple ][ GCR Decoder", "Prologue found at {0}", position); + + // Epilogue not in correct position + if(data[position + 11] != 0xDE || + data[position + 12] != 0xAA) + return null; + + var sector = new RawSector + { + addressField = new RawAddressField + { + prologue = new[] + { + data[position], data[position + 1], data[position + 2] + }, + volume = new[] + { + data[position + 3], data[position + 4] + }, + track = new[] + { + data[position + 5], data[position + 6] + }, + sector = new[] + { + data[position + 7], data[position + 8] + }, + checksum = new[] + { + data[position + 9], data[position + 10] + }, + epilogue = new[] + { + data[position + 11], data[position + 12], data[position + 13] + } + } + }; + + AaruConsole.DebugWriteLine("Apple ][ GCR Decoder", "Volume {0}", + (((sector.addressField.volume[0] & 0x55) << 1) | + (sector.addressField.volume[1] & 0x55)) & 0xFF); + + AaruConsole.DebugWriteLine("Apple ][ GCR Decoder", "Track {0}", + (((sector.addressField.track[0] & 0x55) << 1) | + (sector.addressField.track[1] & 0x55)) & 0xFF); + + AaruConsole.DebugWriteLine("Apple ][ GCR Decoder", "Sector {0}", + (((sector.addressField.sector[0] & 0x55) << 1) | + (sector.addressField.sector[1] & 0x55)) & 0xFF); + + AaruConsole.DebugWriteLine("Apple ][ GCR Decoder", "Checksum {0}", + (((sector.addressField.checksum[0] & 0x55) << 1) | + (sector.addressField.checksum[1] & 0x55)) & 0xFF); + + AaruConsole.DebugWriteLine("Apple ][ GCR Decoder", "Epilogue {0:X2}{1:X2}{2:X2}", + sector.addressField.epilogue[0], sector.addressField.epilogue[1], + sector.addressField.epilogue[2]); + + position += 14; + int syncCount = 0; + bool onSync = false; + var gaps = new MemoryStream(); + + while(data[position] == 0xFF) + { + gaps.WriteByte(data[position]); + syncCount++; + onSync = syncCount >= 5; + position++; + } + + // Lost sync + if(!onSync) + return null; + + // Prologue not found + if(data[position] != 0xD5 || + data[position + 1] != 0xAA) + return null; + + sector.innerGap = gaps.ToArray(); + sector.dataField = new RawDataField(); + + AaruConsole.DebugWriteLine("Apple ][ GCR Decoder", "Inner gap has {0} bytes", + sector.innerGap.Length); + + AaruConsole.DebugWriteLine("Apple ][ GCR Decoder", "Prologue found at {0}", position); + sector.dataField.prologue = new byte[3]; + sector.dataField.prologue[0] = data[position]; + sector.dataField.prologue[1] = data[position + 1]; + sector.dataField.prologue[2] = data[position + 2]; + position += 3; + + gaps = new MemoryStream(); + + // Read data until epilogue is found + while(data[position + 1] != 0xDE || + data[position + 2] != 0xAA) + { + gaps.WriteByte(data[position]); + position++; + + // No space left for epilogue + if(position + 4 > data.Length) + return null; + } + + sector.dataField.data = gaps.ToArray(); + + AaruConsole.DebugWriteLine("Apple ][ GCR Decoder", "Data has {0} bytes", + sector.dataField.data.Length); + + sector.dataField.checksum = data[position]; + sector.dataField.epilogue = new byte[3]; + sector.dataField.epilogue[0] = data[position + 1]; + sector.dataField.epilogue[1] = data[position + 2]; + sector.dataField.epilogue[2] = data[position + 3]; + + position += 4; + gaps = new MemoryStream(); + + // Read gap, if any + while(position < data.Length && + data[position] == 0xFF) + { + gaps.WriteByte(data[position]); + position++; + } + + // Reduces last sector gap so doesn't eat next tracks's gap + if(gaps.Length > 5) + { + gaps.SetLength(gaps.Length / 2); + position -= (int)gaps.Length; + } + + sector.gap = gaps.ToArray(); + + // Return current position to be able to read separate sectors + endOffset = position; + AaruConsole.DebugWriteLine("Apple ][ GCR Decoder", "Got {0} bytes of gap", sector.gap.Length); + AaruConsole.DebugWriteLine("Apple ][ GCR Decoder", "Finished sector at {0}", position); + + return sector; + } + + if(data[position] == 0xFF) + position++; + + // Found data that is not sync or a prologue + else + return null; + } + } + catch(IndexOutOfRangeException) + { + return null; + } + + return null; + } + + public static byte[] MarshalAddressField(RawAddressField addressField) + { + if(addressField == null) + return null; + + var raw = new MemoryStream(); + raw.Write(addressField.prologue, 0, addressField.prologue.Length); + raw.Write(addressField.volume, 0, addressField.volume.Length); + raw.Write(addressField.track, 0, addressField.track.Length); + raw.Write(addressField.sector, 0, addressField.sector.Length); + raw.Write(addressField.checksum, 0, addressField.checksum.Length); + raw.Write(addressField.epilogue, 0, addressField.epilogue.Length); + + return raw.ToArray(); + } + + public static byte[] MarshalSector(RawSector sector) + { + if(sector == null) + return null; + + var raw = new MemoryStream(); + raw.Write(sector.addressField.prologue, 0, sector.addressField.prologue.Length); + raw.Write(sector.addressField.volume, 0, sector.addressField.volume.Length); + raw.Write(sector.addressField.track, 0, sector.addressField.track.Length); + raw.Write(sector.addressField.sector, 0, sector.addressField.sector.Length); + raw.Write(sector.addressField.checksum, 0, sector.addressField.checksum.Length); + raw.Write(sector.addressField.epilogue, 0, sector.addressField.epilogue.Length); + raw.Write(sector.innerGap, 0, sector.innerGap.Length); + raw.Write(sector.dataField.prologue, 0, sector.dataField.prologue.Length); + raw.Write(sector.dataField.data, 0, sector.dataField.data.Length); + raw.WriteByte(sector.dataField.checksum); + raw.Write(sector.dataField.epilogue, 0, sector.dataField.epilogue.Length); + raw.Write(sector.gap, 0, sector.gap.Length); + + return raw.ToArray(); + } + + public static RawTrack MarshalTrack(byte[] data, int offset = 0) => MarshalTrack(data, out _, offset); + + public static RawTrack MarshalTrack(byte[] data, out int endOffset, int offset = 0) + { + int position = offset; + bool firstSector = true; + bool onSync = false; + var gaps = new MemoryStream(); + int count = 0; + List sectors = new List(); + byte[] trackNumber = new byte[2]; + endOffset = offset; + + while(position < data.Length && + data[position] == 0xFF) + { + gaps.WriteByte(data[position]); + count++; + position++; + onSync = count >= 5; + } + + if(position >= data.Length) + return null; + + if(!onSync) + return null; + + while(position < data.Length) + { + int oldPosition = position; + RawSector sector = MarshalSector(data, out position, position); + + if(sector == null) + break; + + if(firstSector) + { + trackNumber[0] = sector.addressField.track[0]; + trackNumber[1] = sector.addressField.track[1]; + firstSector = false; + } + + if(sector.addressField.track[0] != trackNumber[0] || + sector.addressField.track[1] != trackNumber[1]) + { + position = oldPosition; + + break; + } + + AaruConsole.DebugWriteLine("Apple ][ GCR Decoder", "Adding sector {0} of track {1}", + (((sector.addressField.sector[0] & 0x55) << 1) | + (sector.addressField.sector[1] & 0x55)) & 0xFF, + (((sector.addressField.track[0] & 0x55) << 1) | + (sector.addressField.track[1] & 0x55)) & 0xFF); + + sectors.Add(sector); + } + + if(sectors.Count == 0) + return null; + + var track = new RawTrack + { + gap = gaps.ToArray(), + sectors = sectors.ToArray() + }; + + endOffset = position; + + return track; + } + + public static byte[] MarshalTrack(RawTrack track) + { + if(track == null) + return null; + + var raw = new MemoryStream(); + raw.Write(track.gap, 0, track.gap.Length); + + foreach(byte[] rawSector in track.sectors.Select(MarshalSector)) + raw.Write(rawSector, 0, rawSector.Length); + + return raw.ToArray(); + } + + public static List MarshalDisk(byte[] data, int offset = 0) => MarshalDisk(data, out _, offset); + + public static List MarshalDisk(byte[] data, out int endOffset, int offset = 0) + { + endOffset = offset; + List tracks = new List(); + int position = offset; + + RawTrack track = MarshalTrack(data, out position, position); + + while(track != null) + { + tracks.Add(track); + track = MarshalTrack(data, out position, position); + } + + if(tracks.Count == 0) + return null; + + endOffset = position; + + return tracks; + } + + public static byte[] MarshalDisk(List disk) => MarshalDisk(disk.ToArray()); + + public static byte[] MarshalDisk(RawTrack[] disk) + { + if(disk == null) + return null; + + var raw = new MemoryStream(); + + foreach(byte[] rawTrack in disk.Select(MarshalTrack)) + raw.Write(rawTrack, 0, rawTrack.Length); + + return raw.ToArray(); + } + + public static bool IsApple2GCR(byte[] data) + { + RawSector sector = MarshalSector(data, out int position); + + return sector != null && position != 0; + } + + /// GCR-encoded Apple ][ GCR floppy track + public class RawTrack + { + /// Track preamble, set to self-sync 0xFF, between 40 and 95 bytes + public byte[] gap; + public RawSector[] sectors; + } + + /// GCR-encoded Apple ][ GCR floppy sector + public class RawSector + { + /// Address field + public RawAddressField addressField; + /// Data field + public RawDataField dataField; + /// Track preamble, set to self-sync 0xFF, between 14 and 24 bytes + public byte[] gap; + /// Track preamble, set to self-sync 0xFF, between 5 and 10 bytes + public byte[] innerGap; + } + + /// GCR-encoded Apple ][ GCR floppy sector address field + public class RawAddressField + { + /// + /// decodedChecksum = decodedVolume ^ decodedTrack ^ decodedSector checksum[0] = (decodedChecksum >> 1) | 0xAA + /// checksum[1] = decodedChecksum | 0xAA + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] checksum; + /// Always 0xDE, 0xAA, 0xEB + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] epilogue; + /// Always 0xD5, 0xAA, 0x96 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] prologue; + /// Sector number encoded as: sector[0] = (decodedSector >> 1) | 0xAA sector[1] = decodedSector | 0xAA + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] sector; + /// Track number encoded as: track[0] = (decodedTrack >> 1) | 0xAA track[1] = decodedTrack | 0xAA + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] track; + /// Volume number encoded as: volume[0] = (decodedVolume >> 1) | 0xAA volume[1] = decodedVolume | 0xAA + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] volume; + } + + /// GCR-encoded Apple ][ GCR floppy sector data field + public class RawDataField + { + public byte checksum; + /// Encoded data bytes. 410 bytes for 5to3 (aka DOS 3.2) format 342 bytes for 6to2 (aka DOS 3.3) format + public byte[] data; + /// Always 0xDE, 0xAA, 0xEB + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] epilogue; + /// Always 0xD5, 0xAA, 0xAD + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] prologue; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/Floppy/AppleSony.cs b/Aaru.Decoders/Floppy/AppleSony.cs new file mode 100644 index 000000000..27261756f --- /dev/null +++ b/Aaru.Decoders/Floppy/AppleSony.cs @@ -0,0 +1,513 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : AppleSony.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes Apple/Sony floppy structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; + +namespace Aaru.Decoders.Floppy +{ + // Information from: + // Inside Macintosh, Volume II, ISBN 0-201-17732-3 + + /// Methods and structures for Apple Sony GCR floppy decoding + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class AppleSony + { + public static byte[] DecodeSector(RawSector sector) + { + if(sector.addressField.prologue[0] != 0xD5 || + sector.addressField.prologue[1] != 0xAA || + sector.addressField.prologue[2] != 0x96) + return null; + + byte[] bf1 = new byte[175]; + byte[] bf2 = new byte[175]; + byte[] bf3 = new byte[175]; + byte[] nib_data = sector.dataField.data; + var ms = new MemoryStream(); + + int j = 0; + byte w3 = 0; + + for(int i = 0; i <= 174; i++) + { + byte w4 = nib_data[j++]; + byte w1 = nib_data[j++]; + byte w2 = nib_data[j++]; + + if(i != 174) + w3 = nib_data[j++]; + + bf1[i] = (byte)(((w1 & 0x3F) | ((w4 << 2) & 0xC0)) & 0x0F); + bf2[i] = (byte)(((w2 & 0x3F) | ((w4 << 4) & 0xC0)) & 0x0F); + bf3[i] = (byte)(((w3 & 0x3F) | ((w4 << 6) & 0xC0)) & 0x0F); + } + + j = 0; + uint ck1 = 0; + uint ck2 = 0; + uint ck3 = 0; + + while(true) + { + ck1 = (ck1 & 0xFF) << 1; + + if((ck1 & 0x0100) > 0) + ck1++; + + byte carry = (byte)((bf1[j] ^ ck1) & 0xFF); + ck3 += carry; + + if((ck1 & 0x0100) > 0) + { + ck3++; + ck1 &= 0xFF; + } + + ms.WriteByte(carry); + + carry = (byte)((bf2[j] ^ ck3) & 0xFF); + ck2 += carry; + + if(ck3 > 0xFF) + { + ck2++; + ck3 &= 0xFF; + } + + ms.WriteByte(carry); + + if(ms.Length == 524) + break; + + carry = (byte)((bf3[j] ^ ck2) & 0xFF); + ck1 += carry; + + if(ck2 > 0xFF) + { + ck1++; + ck2 &= 0xFF; + } + + ms.WriteByte(carry); + j++; + } + + return ms.ToArray(); + + // Not Apple Sony GCR? + } + + public static RawSector MarshalSector(byte[] data, int offset = 0) => MarshalSector(data, out _, offset); + + public static RawSector MarshalSector(byte[] data, out int endOffset, int offset = 0) + { + endOffset = offset; + + // Not an Apple ][ GCR sector + if(data == null || + data.Length < 363) + return null; + + int position = offset; + + try + { + while(position < data.Length) + { + // Prologue found + if(data[position] == 0xD5 && + data[position + 1] == 0xAA && + data[position + 2] == 0x96) + { + // Epilogue not in correct position + if(data[position + 8] != 0xDE || + data[position + 9] != 0xAA) + return null; + + var sector = new RawSector + { + addressField = new RawAddressField + { + prologue = new[] + { + data[position], data[position + 1], data[position + 2] + }, + track = data[position + 3], + sector = data[position + 4], + side = data[position + 5], + format = (AppleEncodedFormat)data[position + 6], + checksum = data[position + 7], + epilogue = new[] + { + data[position + 8], data[position + 9] + } + } + }; + + position += 10; + int syncCount = 0; + bool onSync = false; + var gaps = new MemoryStream(); + + while(data[position] == 0xFF) + { + gaps.WriteByte(data[position]); + syncCount++; + onSync = syncCount >= 5; + position++; + } + + // Lost sync + if(!onSync) + return null; + + // Prologue not found + if(data[position] != 0xDE || + data[position + 1] != 0xAA || + data[position + 2] != 0xAD) + return null; + + sector.innerGap = gaps.ToArray(); + + sector.dataField = new RawDataField + { + prologue = new[] + { + data[position], data[position + 1], data[position + 2] + }, + spare = data[position + 3] + }; + + position += 4; + + gaps = new MemoryStream(); + + // Read data until epilogue is found + while(data[position + 4] != 0xD5 || + data[position + 5] != 0xAA) + { + gaps.WriteByte(data[position]); + position++; + + // No space left for epilogue + if(position + 7 > data.Length) + return null; + } + + sector.dataField.data = gaps.ToArray(); + sector.dataField.checksum = new byte[4]; + sector.dataField.checksum[0] = data[position]; + sector.dataField.checksum[1] = data[position + 2]; + sector.dataField.checksum[2] = data[position + 3]; + sector.dataField.checksum[3] = data[position + 4]; + sector.dataField.epilogue = new byte[2]; + sector.dataField.epilogue[0] = data[position + 5]; + sector.dataField.epilogue[1] = data[position + 6]; + + position += 7; + gaps = new MemoryStream(); + + // Read gap, if any + while(position < data.Length && + data[position] == 0xFF) + { + gaps.WriteByte(data[position]); + position++; + } + + // Reduces last sector gap so doesn't eat next tracks's gap + if(gaps.Length > 5) + { + gaps.SetLength(gaps.Length / 2); + position -= (int)gaps.Length; + } + + sector.gap = gaps.ToArray(); + + // Return current position to be able to read separate sectors + endOffset = position; + + return sector; + } + + if(data[position] == 0xFF) + position++; + + // Found data that is not sync or a prologue + else + return null; + } + } + catch(IndexOutOfRangeException) + { + return null; + } + + return null; + } + + public static byte[] MarshalAddressField(RawAddressField addressField) + { + if(addressField == null) + return null; + + var raw = new MemoryStream(); + raw.Write(addressField.prologue, 0, addressField.prologue.Length); + raw.WriteByte(addressField.track); + raw.WriteByte(addressField.sector); + raw.WriteByte(addressField.side); + raw.WriteByte((byte)addressField.format); + raw.WriteByte(addressField.checksum); + + return raw.ToArray(); + } + + public static byte[] MarshalSector(RawSector sector) + { + if(sector == null) + return null; + + var raw = new MemoryStream(); + raw.Write(sector.addressField.prologue, 0, sector.addressField.prologue.Length); + raw.WriteByte(sector.addressField.track); + raw.WriteByte(sector.addressField.sector); + raw.WriteByte(sector.addressField.side); + raw.WriteByte((byte)sector.addressField.format); + raw.WriteByte(sector.addressField.checksum); + raw.Write(sector.innerGap, 0, sector.innerGap.Length); + raw.Write(sector.dataField.prologue, 0, sector.dataField.prologue.Length); + raw.WriteByte(sector.dataField.spare); + raw.Write(sector.dataField.data, 0, sector.dataField.data.Length); + raw.Write(sector.dataField.checksum, 0, sector.dataField.checksum.Length); + raw.Write(sector.dataField.epilogue, 0, sector.dataField.epilogue.Length); + raw.Write(sector.gap, 0, sector.gap.Length); + + return raw.ToArray(); + } + + public static RawTrack MarshalTrack(byte[] data, int offset = 0) => MarshalTrack(data, out _, offset); + + public static RawTrack MarshalTrack(byte[] data, out int endOffset, int offset = 0) + { + int position = offset; + bool firstSector = true; + bool onSync = false; + var gaps = new MemoryStream(); + int count = 0; + List sectors = new List(); + byte trackNumber = 0; + byte sideNumber = 0; + endOffset = offset; + + while(position < data.Length && + data[position] == 0xFF) + { + gaps.WriteByte(data[position]); + count++; + position++; + onSync = count >= 5; + } + + if(position >= data.Length) + return null; + + if(!onSync) + return null; + + while(position < data.Length) + { + int oldPosition = position; + RawSector sector = MarshalSector(data, out position, position); + + if(sector == null) + break; + + if(firstSector) + { + trackNumber = sector.addressField.track; + sideNumber = sector.addressField.side; + firstSector = false; + } + + if(sector.addressField.track != trackNumber || + sector.addressField.side != sideNumber) + { + position = oldPosition; + + break; + } + + sectors.Add(sector); + } + + if(sectors.Count == 0) + return null; + + var track = new RawTrack + { + gap = gaps.ToArray(), + sectors = sectors.ToArray() + }; + + endOffset = position; + + return track; + } + + public static byte[] MarshalTrack(RawTrack track) + { + if(track == null) + return null; + + var raw = new MemoryStream(); + raw.Write(track.gap, 0, track.gap.Length); + + foreach(byte[] rawSector in track.sectors.Select(MarshalSector)) + raw.Write(rawSector, 0, rawSector.Length); + + return raw.ToArray(); + } + + public static List MarshalDisk(byte[] data, int offset = 0) => MarshalDisk(data, out _, offset); + + public static List MarshalDisk(byte[] data, out int endOffset, int offset = 0) + { + endOffset = offset; + List tracks = new List(); + int position = offset; + + RawTrack track = MarshalTrack(data, out position, position); + + while(track != null) + { + tracks.Add(track); + track = MarshalTrack(data, out position, position); + } + + if(tracks.Count == 0) + return null; + + endOffset = position; + + return tracks; + } + + public static byte[] MarshalDisk(List disk) => MarshalDisk(disk.ToArray()); + + public static byte[] MarshalDisk(RawTrack[] disk) + { + if(disk == null) + return null; + + var raw = new MemoryStream(); + + foreach(byte[] rawTrack in disk.Select(MarshalTrack)) + raw.Write(rawTrack, 0, rawTrack.Length); + + return raw.ToArray(); + } + + public static bool IsAppleSonyGCR(byte[] data) + { + RawSector sector = MarshalSector(data, out int position); + + return sector != null && position != 0; + } + + /// GCR-encoded Apple Sony GCR floppy track + public class RawTrack + { + /// Track preamble, set to self-sync 0xFF, 36 bytes + public byte[] gap; + public RawSector[] sectors; + } + + /// GCR-encoded Apple Sony GCR floppy sector + public class RawSector + { + /// Address field + public RawAddressField addressField; + /// Data field + public RawDataField dataField; + /// Track preamble, set to self-sync 0xFF, unknown size + public byte[] gap; + /// Track preamble, set to self-sync 0xFF, 6 bytes + public byte[] innerGap; + } + + /// GCR-encoded Apple Sony GCR floppy sector address field + public class RawAddressField + { + /// Checksum + public byte checksum; + /// Always 0xDE, 0xAA + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] epilogue; + /// Disk format + public AppleEncodedFormat format; + /// Always 0xD5, 0xAA, 0x96 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] prologue; + /// Encoded sector number + public byte sector; + /// Encoded side number + public byte side; + /// Encoded (decodedTrack & 0x3F) + public byte track; + } + + /// GCR-encoded Apple ][ GCR floppy sector data field + public class RawDataField + { + /// Checksum + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] checksum; + /// Encoded data bytes. + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 698)] + public byte[] data; + /// Always 0xDE, 0xAA + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] epilogue; + /// Always 0xD5, 0xAA, 0xAD + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] prologue; + /// Spare, usually + public byte spare; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/Floppy/Commodore.cs b/Aaru.Decoders/Floppy/Commodore.cs new file mode 100644 index 000000000..e040810e8 --- /dev/null +++ b/Aaru.Decoders/Floppy/Commodore.cs @@ -0,0 +1,74 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Commodore.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes Commodore (pre-Amiga) floppy structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; + +namespace Aaru.Decoders.Floppy +{ + /// Methods and structures for Commodore GCR floppy decoding + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class Commodore + { + /// Decoded Commodore GCR sector header + public struct SectorHeader + { + /// Always 0x08 + public byte id; + /// XOR of following fields + public byte checksum; + /// Sector number + public byte sector; + /// Track number + public byte track; + /// Format ID, unknown meaning + public ushort format; + /// Filled with 0x0F + public ushort fill; + } + + /// Decoded Commodore GCR sector data + public struct SectorData + { + /// Always 0x07 + public byte id; + /// User data + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] + public byte data; + /// XOR of + public byte checksum; + /// Filled with 0x0F + public ushort fill; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/Floppy/Enums.cs b/Aaru.Decoders/Floppy/Enums.cs new file mode 100644 index 000000000..b693c0e26 --- /dev/null +++ b/Aaru.Decoders/Floppy/Enums.cs @@ -0,0 +1,78 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Enums.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Contains various floppy enumerations. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.Decoders.Floppy +{ + /// In-sector code for sector size + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum IBMSectorSizeCode : byte + { + /// 128 bytes/sector + EighthKilo = 0, + /// 256 bytes/sector + QuarterKilo = 1, + /// 512 bytes/sector + HalfKilo = 2, + /// 1024 bytes/sector + Kilo = 3, + /// 2048 bytes/sector + TwiceKilo = 4, + /// 4096 bytes/sector + FriceKilo = 5, + /// 8192 bytes/sector + TwiceFriceKilo = 6, + /// 16384 bytes/sector + FricelyFriceKilo = 7 + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum IBMIdType : byte + { + IndexMark = 0xFC, AddressMark = 0xFE, DataMark = 0xFB, + DeletedDataMark = 0xF8 + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum AppleEncodedFormat : byte + { + /// Disk is an Apple II 3.5" disk + AppleII = 0x96, + /// Disk is an Apple Lisa 3.5" disk + Lisa = 0x97, + /// Disk is an Apple Macintosh single-sided 3.5" disk + MacSingleSide = 0x9A, + /// Disk is an Apple Macintosh double-sided 3.5" disk + MacDoubleSide = 0xD9 + } +} \ No newline at end of file diff --git a/Aaru.Decoders/Floppy/ISO.cs b/Aaru.Decoders/Floppy/ISO.cs new file mode 100644 index 000000000..76306d800 --- /dev/null +++ b/Aaru.Decoders/Floppy/ISO.cs @@ -0,0 +1,121 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ISO.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes ISO/ECMA floppy structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; + +namespace Aaru.Decoders.Floppy +{ + // Information from: + // National Semiconductor PC87332VLJ datasheet + // SMsC FDC37C78 datasheet + // Intel 82078 datasheet + // Intel 82077AA datasheet + // Toshiba TC8566AF datasheet + // Fujitsu MB8876A datasheet + // ECMA-147 + // ECMA-100 + + /// Methods and structures for ISO floppy decoding (also used by Atari ST and others) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class ISO + { + /// ISO floppy track, also used by Atari ST and others + public struct Track + { + /// Start of track, 32 bytes set to 0x4E + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] + public byte[] innerGap; + /// Track sectors + public Sector[] sectors; + /// Undefined size + public byte[] gap; + } + + /// Raw demodulated format for IBM System 34 floppies + public struct Sector + { + /// Sector address mark + public AddressMark addressMark; + /// 22 bytes set to 0x4E, set to 0x22 on Commodore 1581 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 22)] + public byte[] innerGap; + /// Sector data block + public DataBlock dataBlock; + /// Variable bytes set to 0x4E, ECMA defines 54 + public byte[] outerGap; + } + + /// Sector address mark for IBM System 34 floppies, contains sync word + public struct AddressMark + { + /// 12 bytes set to 0 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] zero; + /// 3 bytes set to 0xA1 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] aone; + /// Set to + public IBMIdType type; + /// Track number + public byte track; + /// Side number + public byte side; + /// Sector number + public byte sector; + /// + /// + /// + public IBMSectorSizeCode sectorSize; + /// CRC16 from to end of + public ushort crc; + } + + /// Sector data block for IBM System 34 floppies + public struct DataBlock + { + /// 12 bytes set to 0 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] zero; + /// 3 bytes set to 0xA1 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] aone; + /// Set to or to + public IBMIdType type; + /// User data + public byte[] data; + /// CRC16 from to end of + public ushort crc; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/Floppy/Perpendicular.cs b/Aaru.Decoders/Floppy/Perpendicular.cs new file mode 100644 index 000000000..43e457864 --- /dev/null +++ b/Aaru.Decoders/Floppy/Perpendicular.cs @@ -0,0 +1,139 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Perpendicular.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes perpendicular recording floppy structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; + +namespace Aaru.Decoders.Floppy +{ + // Information from: + // National Semiconductor PC87332VLJ datasheet + // SMsC FDC37C78 datasheet + // Intel 82078 datasheet + // Intel 82077AA datasheet + // Toshiba TC8566AF datasheet + // Fujitsu MB8876A datasheet + // ECMA-147 + // ECMA-100 + + /// Methods and structures for perpendicular MFM floppy decoding + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class Perpendicular + { + /// Perpendicular floppy track + public struct Track + { + /// Start of track + public TrackPreamble trackStart; + /// Track sectors + public Sector[] sectors; + /// Undefined size + public byte[] gap; + } + + /// Raw demodulated format for perpendicular floppies + public struct Sector + { + /// Sector address mark + public AddressMark addressMark; + /// 41 bytes set to 0x4E + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 41)] + public byte[] innerGap; + /// Sector data block + public DataBlock dataBlock; + /// Variable-sized inter-sector gap, ECMA defines 83 bytes + public byte[] outerGap; + } + + /// Start of IBM PC MFM floppy track Used by IBM PC, Apple Macintosh (high-density only), and a lot others + public struct TrackPreamble + { + /// Gap from index pulse, 80 bytes set to 0x4E + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)] + public byte[] gap; + /// 12 bytes set to 0x00 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] zero; + /// 3 bytes set to 0xC2 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] ctwo; + /// Set to + public IBMIdType type; + /// Gap until first sector, 50 bytes to 0x4E + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)] + public byte[] gap1; + } + + /// Sector address mark for IBM System 34 floppies, contains sync word + public struct AddressMark + { + /// 12 bytes set to 0 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] zero; + /// 3 bytes set to 0xA1 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] aone; + /// Set to + public IBMIdType type; + /// Track number + public byte track; + /// Side number + public byte side; + /// Sector number + public byte sector; + /// + /// + /// + public IBMSectorSizeCode sectorSize; + /// CRC16 from to end of + public ushort crc; + } + + /// Sector data block for IBM System 34 floppies + public struct DataBlock + { + /// 12 bytes set to 0 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] zero; + /// 3 bytes set to 0xA1 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] aone; + /// Set to or to + public IBMIdType type; + /// User data + public byte[] data; + /// CRC16 from to end of + public ushort crc; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/Floppy/System34.cs b/Aaru.Decoders/Floppy/System34.cs new file mode 100644 index 000000000..cf20f6a8f --- /dev/null +++ b/Aaru.Decoders/Floppy/System34.cs @@ -0,0 +1,139 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : System34.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes IBM System 34 floppy structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; + +namespace Aaru.Decoders.Floppy +{ + // Information from: + // National Semiconductor PC87332VLJ datasheet + // SMsC FDC37C78 datasheet + // Intel 82078 datasheet + // Intel 82077AA datasheet + // Toshiba TC8566AF datasheet + // Fujitsu MB8876A datasheet + // ECMA-147 + // ECMA-100 + + /// Methods and structures for IBM System 34 floppy decoding + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class System34 + { + /// Track format for IBM System 34 floppy Used by IBM PC, Apple Macintosh (high-density only), and a lot others + public struct Track + { + /// Start of track + public TrackPreamble trackStart; + /// Track sectors + public Sector[] sectors; + /// Undefined size + public byte[] gap; + } + + /// Start of IBM PC MFM floppy track Used by IBM PC, Apple Macintosh (high-density only), and a lot others + public struct TrackPreamble + { + /// Gap from index pulse, 80 bytes set to 0x4E + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)] + public byte[] gap; + /// 12 bytes set to 0x00 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] zero; + /// 3 bytes set to 0xC2 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] ctwo; + /// Set to + public IBMIdType type; + /// Gap until first sector, 50 bytes to 0x4E + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)] + public byte[] gap1; + } + + /// Raw demodulated format for IBM System 34 floppies + public struct Sector + { + /// Sector address mark + public AddressMark addressMark; + /// 22 bytes set to 0x4E, set to 0x22 on Commodore 1581 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 22)] + public byte[] innerGap; + /// Sector data block + public DataBlock dataBlock; + /// Variable bytes set to 0x4E, ECMA defines 54 + public byte[] outerGap; + } + + /// Sector address mark for IBM System 34 floppies, contains sync word + public struct AddressMark + { + /// 12 bytes set to 0 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] zero; + /// 3 bytes set to 0xA1 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] aone; + /// Set to + public IBMIdType type; + /// Track number + public byte track; + /// Side number + public byte side; + /// Sector number + public byte sector; + /// + /// + /// + public IBMSectorSizeCode sectorSize; + /// CRC16 from to end of + public ushort crc; + } + + /// Sector data block for IBM System 34 floppies + public struct DataBlock + { + /// 12 bytes set to 0 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] zero; + /// 3 bytes set to 0xA1 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] aone; + /// Set to or to + public IBMIdType type; + /// User data + public byte[] data; + /// CRC16 from to end of + public ushort crc; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/Floppy/System3740.cs b/Aaru.Decoders/Floppy/System3740.cs new file mode 100644 index 000000000..b10d39893 --- /dev/null +++ b/Aaru.Decoders/Floppy/System3740.cs @@ -0,0 +1,130 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : System3740.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes IBM System 3740 floppy structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; + +namespace Aaru.Decoders.Floppy +{ + // Information from: + // National Semiconductor PC87332VLJ datasheet + // SMsC FDC37C78 datasheet + // Intel 82078 datasheet + // Intel 82077AA datasheet + // Toshiba TC8566AF datasheet + // Fujitsu MB8876A datasheet + // ECMA-147 + // ECMA-100 + + /// Methods and structures for IBM System 3740 floppy decoding + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class System3740 + { + /// Track format for IBM System 3740 floppy + public struct Track + { + /// Start of track + public TrackPreamble trackStart; + /// Track sectors + public Sector[] sectors; + /// Undefined size + public byte[] gap; + } + + /// Start of IBM PC FM floppy track + public struct TrackPreamble + { + /// Gap from index pulse, 80 bytes set to 0xFF + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)] + public byte[] gap; + /// 6 bytes set to 0x00 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + public byte[] zero; + /// Set to + public IBMIdType type; + /// Gap until first sector, 26 bytes to 0xFF + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] + public byte[] gap1; + } + + /// Raw demodulated format for IBM System 3740 floppies + public struct Sector + { + /// Sector address mark + public AddressMark addressMark; + /// 11 bytes set to 0xFF + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] + public byte[] innerGap; + /// Sector data block + public DataBlock dataBlock; + /// Variable bytes set to 0xFF + public byte[] outerGap; + } + + /// Sector address mark for IBM System 3740 floppies, contains sync word + public struct AddressMark + { + /// 6 bytes set to 0 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + public byte[] zero; + /// Set to + public IBMIdType type; + /// Track number + public byte track; + /// Side number + public byte side; + /// Sector number + public byte sector; + /// + /// + /// + public IBMSectorSizeCode sectorSize; + /// CRC16 from to end of + public ushort crc; + } + + /// Sector data block for IBM System 3740 floppies + public struct DataBlock + { + /// 12 bytes set to 0 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] zero; + /// Set to or to + public IBMIdType type; + /// User data + public byte[] data; + /// CRC16 from to end of + public ushort crc; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/LisaTag.cs b/Aaru.Decoders/LisaTag.cs new file mode 100644 index 000000000..ee9e73ed8 --- /dev/null +++ b/Aaru.Decoders/LisaTag.cs @@ -0,0 +1,506 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : LisaTag.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes Apple Lisa tags. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using Aaru.Helpers; + +namespace Aaru.Decoders +{ + /// Represents a Lisa Office 7/7 sector tag + [SuppressMessage("ReSharper", "MemberCanBeInternal"), SuppressMessage("ReSharper", "NotAccessedField.Global"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), + SuppressMessage("ReSharper", "StructMemberCanBeMadeReadOnly")] + public static class LisaTag + { + /// Decodes tag from a 3.5" Sony micro-floppy + /// Byte array containing raw tag data + /// Decoded tag in Sony's format + public static SonyTag? DecodeSonyTag(byte[] tag) + { + if(tag == null || + tag.Length != 12) + return null; + + var snTag = new SonyTag + { + Version = BigEndianBitConverter.ToUInt16(tag, 0), + Kind = (byte)((tag[2] & 0xC0) >> 6), + Reserved = (byte)(tag[2] & 0x3F), + Volume = tag[3], + FileId = BigEndianBitConverter.ToInt16(tag, 4), + RelPage = BigEndianBitConverter.ToUInt16(tag, 6), + NextBlock = (ushort)(BigEndianBitConverter.ToUInt16(tag, 8) & 0x7FF), + PrevBlock = (ushort)(BigEndianBitConverter.ToUInt16(tag, 10) & 0x7FF) + }; + + snTag.IsLast = snTag.NextBlock == 0x7FF; + snTag.IsFirst = snTag.PrevBlock == 0x7FF; + + return snTag; + } + + /// Decodes tag from a Profile + /// Byte array containing raw tag data + /// Decoded tag in Profile's format + public static ProfileTag? DecodeProfileTag(byte[] tag) + { + if(tag == null || + tag.Length != 20) + return null; + + var phTag = new ProfileTag(); + + byte[] tmp = new byte[4]; + + phTag.Version = BigEndianBitConverter.ToUInt16(tag, 0); + phTag.Kind = (byte)((tag[2] & 0xC0) >> 6); + phTag.Reserved = (byte)(tag[2] & 0x3F); + phTag.Volume = tag[3]; + phTag.FileId = BigEndianBitConverter.ToInt16(tag, 4); + phTag.ValidChk |= (tag[6] & 0x80) == 0x80; + phTag.UsedBytes = (ushort)(BigEndianBitConverter.ToUInt16(tag, 6) & 0x7FFF); + + tmp[0] = 0x00; + tmp[1] = tag[8]; + tmp[2] = tag[9]; + tmp[3] = tag[10]; + phTag.AbsPage = BigEndianBitConverter.ToUInt32(tmp, 0); + + phTag.Checksum = tag[11]; + phTag.RelPage = BigEndianBitConverter.ToUInt16(tag, 12); + + tmp[0] = 0x00; + tmp[1] = tag[14]; + tmp[2] = tag[15]; + tmp[3] = tag[16]; + phTag.NextBlock = BigEndianBitConverter.ToUInt32(tmp, 0); + + tmp[0] = 0x00; + tmp[1] = tag[17]; + tmp[2] = tag[18]; + tmp[3] = tag[19]; + phTag.PrevBlock = BigEndianBitConverter.ToUInt32(tmp, 0); + + phTag.IsLast = phTag.NextBlock == 0xFFFFFF; + phTag.IsFirst = phTag.PrevBlock == 0xFFFFFF; + + return phTag; + } + + /// Decodes tag from a Priam + /// Byte array containing raw tag data + /// Decoded tag in Priam's format + public static PriamTag? DecodePriamTag(byte[] tag) + { + if(tag == null || + tag.Length != 24) + return null; + + var pmTag = new PriamTag(); + + byte[] tmp = new byte[4]; + + pmTag.Version = BigEndianBitConverter.ToUInt16(tag, 0); + pmTag.Kind = (byte)((tag[2] & 0xC0) >> 6); + pmTag.Reserved = (byte)(tag[2] & 0x3F); + pmTag.Volume = tag[3]; + pmTag.FileId = BigEndianBitConverter.ToInt16(tag, 4); + pmTag.ValidChk |= (tag[6] & 0x80) == 0x80; + pmTag.UsedBytes = (ushort)(BigEndianBitConverter.ToUInt16(tag, 6) & 0x7FFF); + + tmp[0] = 0x00; + tmp[1] = tag[8]; + tmp[2] = tag[9]; + tmp[3] = tag[10]; + pmTag.AbsPage = BigEndianBitConverter.ToUInt32(tmp, 0); + + pmTag.Checksum = tag[11]; + pmTag.RelPage = BigEndianBitConverter.ToUInt16(tag, 12); + + tmp[0] = 0x00; + tmp[1] = tag[14]; + tmp[2] = tag[15]; + tmp[3] = tag[16]; + pmTag.NextBlock = BigEndianBitConverter.ToUInt32(tmp, 0); + + tmp[0] = 0x00; + tmp[1] = tag[17]; + tmp[2] = tag[18]; + tmp[3] = tag[19]; + pmTag.PrevBlock = BigEndianBitConverter.ToUInt32(tmp, 0); + + pmTag.DiskSize = BigEndianBitConverter.ToUInt32(tag, 20); + + pmTag.IsLast = pmTag.NextBlock == 0xFFFFFF; + pmTag.IsFirst = pmTag.PrevBlock == 0xFFFFFF; + + return pmTag; + } + + /// Decodes tag from any known format + /// Byte array containing raw tag data + /// Decoded tag in Priam's format + public static PriamTag? DecodeTag(byte[] tag) + { + if(tag == null) + return null; + + PriamTag pmTag; + + switch(tag.Length) + { + case 12: + SonyTag? snTag = DecodeSonyTag(tag); + + if(snTag == null) + return null; + + pmTag = new PriamTag(); + pmTag.AbsPage = 0; + pmTag.Checksum = 0; + pmTag.DiskSize = 0; + pmTag.FileId = snTag.Value.FileId; + pmTag.Kind = snTag.Value.Kind; + pmTag.NextBlock = snTag.Value.NextBlock; + pmTag.PrevBlock = snTag.Value.PrevBlock; + pmTag.RelPage = snTag.Value.RelPage; + pmTag.Reserved = snTag.Value.Reserved; + pmTag.UsedBytes = 0; + pmTag.ValidChk = false; + pmTag.Version = snTag.Value.Version; + pmTag.Volume = snTag.Value.Volume; + pmTag.IsFirst = snTag.Value.IsFirst; + pmTag.IsLast = snTag.Value.IsLast; + + return pmTag; + case 20: + ProfileTag? phTag = DecodeProfileTag(tag); + + if(phTag == null) + return null; + + pmTag = new PriamTag(); + pmTag.AbsPage = phTag.Value.AbsPage; + pmTag.Checksum = phTag.Value.Checksum; + pmTag.DiskSize = 0; + pmTag.FileId = phTag.Value.FileId; + pmTag.Kind = phTag.Value.Kind; + pmTag.NextBlock = phTag.Value.NextBlock; + pmTag.PrevBlock = phTag.Value.PrevBlock; + pmTag.RelPage = phTag.Value.RelPage; + pmTag.Reserved = phTag.Value.Reserved; + pmTag.UsedBytes = phTag.Value.UsedBytes; + pmTag.ValidChk = phTag.Value.ValidChk; + pmTag.Version = phTag.Value.Version; + pmTag.Volume = phTag.Value.Volume; + pmTag.IsFirst = phTag.Value.IsFirst; + pmTag.IsLast = phTag.Value.IsLast; + + return pmTag; + case 24: return DecodePriamTag(tag); + default: return null; + } + } + + /// LisaOS tag as stored on Apple Profile and FileWare disks (20 bytes) + public struct ProfileTag + { + /// 0x00, Lisa OS version number + public ushort Version; + /// 0x02 bits 7 to 6, kind of info in this block + public byte Kind; + /// 0x02 bits 5 to 0, reserved + public byte Reserved; + /// 0x03, disk volume number + public byte Volume; + /// 0x04, file ID + public short FileId; + /// 0x06 bit 7, checksum valid? + public bool ValidChk; + /// 0x06 bits 6 to 0, used bytes in block + public ushort UsedBytes; + /// 0x08, 3 bytes, absolute page number + public uint AbsPage; + /// 0x0B, checksum of data + public byte Checksum; + /// 0x0C, relative page number + public ushort RelPage; + /// 0x0E, 3 bytes, next block, 0xFFFFFF if it's last block + public uint NextBlock; + /// 0x11, 3 bytes, previous block, 0xFFFFFF if it's first block + public uint PrevBlock; + + /// On-memory value for easy first block search. + public bool IsFirst; + /// On-memory value for easy last block search. + public bool IsLast; + + /// Converts this tag to Priam DataTower format + public PriamTag ToPriam() => new PriamTag + { + AbsPage = AbsPage, + Checksum = Checksum, + FileId = FileId, + IsFirst = IsFirst, + IsLast = IsLast, + Kind = Kind, + NextBlock = IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF, + PrevBlock = IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF, + RelPage = RelPage, + UsedBytes = UsedBytes, + ValidChk = ValidChk, + Version = Version, + Volume = Volume + }; + + /// Converts this tag to Sony format + public SonyTag ToSony() => new SonyTag + { + FileId = FileId, + IsFirst = IsFirst, + IsLast = IsLast, + Kind = Kind, + NextBlock = (ushort)NextBlock, + PrevBlock = (ushort)PrevBlock, + RelPage = RelPage, + Version = Version, + Volume = Volume + }; + + /// Gets a byte array representation of this tag + public byte[] GetBytes() + { + byte[] tagBytes = new byte[20]; + + byte[] tmp = BigEndianBitConverter.GetBytes(Version); + Array.Copy(tmp, 0, tagBytes, 0, 2); + tagBytes[2] = (byte)(Kind << 6); + tagBytes[3] = Volume; + tmp = BigEndianBitConverter.GetBytes(FileId); + Array.Copy(tmp, 0, tagBytes, 4, 2); + tmp = BigEndianBitConverter.GetBytes((ushort)(UsedBytes & 0x7FFF)); + Array.Copy(tmp, 0, tagBytes, 6, 2); + + if(ValidChk) + tagBytes[6] += 0x80; + + tmp = BigEndianBitConverter.GetBytes(AbsPage); + Array.Copy(tmp, 1, tagBytes, 8, 3); + tagBytes[11] = Checksum; + tmp = BigEndianBitConverter.GetBytes(RelPage); + Array.Copy(tmp, 0, tagBytes, 12, 2); + tmp = BigEndianBitConverter.GetBytes(IsLast ? 0xFFFFFF : NextBlock); + Array.Copy(tmp, 1, tagBytes, 14, 3); + tmp = BigEndianBitConverter.GetBytes(IsFirst ? 0xFFFFFF : PrevBlock); + Array.Copy(tmp, 1, tagBytes, 17, 3); + + return tagBytes; + } + } + + /// LisaOS tag as stored on Priam DataTower disks (24 bytes) + public struct PriamTag + { + /// 0x00, Lisa OS version number + public ushort Version; + /// 0x02 bits 7 to 6, kind of info in this block + public byte Kind; + /// 0x02 bits 5 to 0, reserved + public byte Reserved; + /// 0x03, disk volume number + public byte Volume; + /// 0x04, file ID + public short FileId; + /// 0x06 bit 7, checksum valid? + public bool ValidChk; + /// 0x06 bits 6 to 0, used bytes in block + public ushort UsedBytes; + /// 0x08, 3 bytes, absolute page number + public uint AbsPage; + /// 0x0B, checksum of data + public byte Checksum; + /// 0x0C, relative page number + public ushort RelPage; + /// 0x0E, 3 bytes, next block, 0xFFFFFF if it's last block + public uint NextBlock; + /// 0x11, 3 bytes, previous block, 0xFFFFFF if it's first block + public uint PrevBlock; + /// 0x14, disk size + public uint DiskSize; + + /// On-memory value for easy first block search. + public bool IsFirst; + /// On-memory value for easy last block search. + public bool IsLast; + + /// Converts this tag to Apple Profile format + public ProfileTag ToProfile() => new ProfileTag + { + AbsPage = AbsPage, + Checksum = Checksum, + FileId = FileId, + IsFirst = IsFirst, + IsLast = IsLast, + Kind = Kind, + NextBlock = IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF, + PrevBlock = IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF, + RelPage = RelPage, + UsedBytes = UsedBytes, + ValidChk = ValidChk, + Version = Version, + Volume = Volume + }; + + /// Converts this tag to Sony format + public SonyTag ToSony() => new SonyTag + { + FileId = FileId, + IsFirst = IsFirst, + IsLast = IsLast, + Kind = Kind, + NextBlock = (ushort)(IsLast ? 0x7FF : NextBlock & 0x7FF), + PrevBlock = (ushort)(IsFirst ? 0x7FF : PrevBlock & 0x7FF), + RelPage = RelPage, + Version = Version, + Volume = Volume + }; + + /// Gets a byte array representation of this tag + public byte[] GetBytes() + { + byte[] tagBytes = new byte[24]; + + byte[] tmp = BigEndianBitConverter.GetBytes(Version); + Array.Copy(tmp, 0, tagBytes, 0, 2); + tagBytes[2] = (byte)(Kind << 6); + tagBytes[3] = Volume; + tmp = BigEndianBitConverter.GetBytes(FileId); + Array.Copy(tmp, 0, tagBytes, 4, 2); + tmp = BigEndianBitConverter.GetBytes((ushort)(UsedBytes & 0x7FFF)); + Array.Copy(tmp, 0, tagBytes, 6, 2); + + if(ValidChk) + tagBytes[6] += 0x80; + + tmp = BigEndianBitConverter.GetBytes(AbsPage); + Array.Copy(tmp, 1, tagBytes, 8, 3); + tagBytes[11] = Checksum; + tmp = BigEndianBitConverter.GetBytes(RelPage); + Array.Copy(tmp, 0, tagBytes, 12, 2); + tmp = BigEndianBitConverter.GetBytes(IsLast ? 0xFFFFFF : NextBlock); + Array.Copy(tmp, 1, tagBytes, 14, 3); + tmp = BigEndianBitConverter.GetBytes(IsFirst ? 0xFFFFFF : PrevBlock); + Array.Copy(tmp, 1, tagBytes, 17, 3); + tmp = BigEndianBitConverter.GetBytes(DiskSize); + Array.Copy(tmp, 0, tagBytes, 20, 4); + + return tagBytes; + } + } + + /// LisaOS tag as stored on Apple Sony disks (12 bytes) + public struct SonyTag + { + /// 0x00, Lisa OS version number + public ushort Version; + /// 0x02 bits 7 to 6, kind of info in this block + public byte Kind; + /// 0x02 bits 5 to 0, reserved + public byte Reserved; + /// 0x03, disk volume number + public byte Volume; + /// 0x04, file ID + public short FileId; + /// 0x06, relative page number + public ushort RelPage; + /// 0x08, 3 bytes, next block, 0x7FF if it's last block, 0x8000 set if block is valid + public ushort NextBlock; + /// 0x0A, 3 bytes, previous block, 0x7FF if it's first block + public ushort PrevBlock; + + /// On-memory value for easy first block search. + public bool IsFirst; + /// On-memory value for easy last block search. + public bool IsLast; + + /// Converts this tag to Apple Profile format + public ProfileTag ToProfile() => new ProfileTag + { + FileId = FileId, + IsFirst = IsFirst, + IsLast = IsLast, + Kind = Kind, + NextBlock = (uint)(IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF), + PrevBlock = (uint)(IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF), + RelPage = RelPage, + Version = Version, + Volume = Volume + }; + + /// Converts this tag to Priam DataTower format + public PriamTag ToPriam() => new PriamTag + { + FileId = FileId, + IsFirst = IsFirst, + IsLast = IsLast, + Kind = Kind, + NextBlock = (uint)(IsLast ? 0xFFFFFF : NextBlock & 0xFFFFFF), + PrevBlock = (uint)(IsFirst ? 0xFFFFFF : PrevBlock & 0xFFFFFF), + RelPage = RelPage, + Version = Version, + Volume = Volume + }; + + /// Gets a byte array representation of this tag + public byte[] GetBytes() + { + byte[] tagBytes = new byte[12]; + + byte[] tmp = BigEndianBitConverter.GetBytes(Version); + Array.Copy(tmp, 0, tagBytes, 0, 2); + tagBytes[2] = (byte)(Kind << 6); + tagBytes[3] = Volume; + tmp = BigEndianBitConverter.GetBytes(FileId); + Array.Copy(tmp, 0, tagBytes, 4, 2); + tmp = BigEndianBitConverter.GetBytes(RelPage); + Array.Copy(tmp, 0, tagBytes, 6, 2); + tmp = BigEndianBitConverter.GetBytes(IsLast ? 0x7FF : NextBlock); + Array.Copy(tmp, 1, tagBytes, 8, 2); + tmp = BigEndianBitConverter.GetBytes(IsFirst ? 0x7FF : PrevBlock); + Array.Copy(tmp, 1, tagBytes, 10, 2); + + return tagBytes; + } + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/MMC/CID.cs b/Aaru.Decoders/MMC/CID.cs new file mode 100644 index 000000000..5fa02abc3 --- /dev/null +++ b/Aaru.Decoders/MMC/CID.cs @@ -0,0 +1,214 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CID.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes MultiMediaCard CID. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Helpers; + +namespace Aaru.Decoders.MMC +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "UnassignedField.Global")] + public class CID + { + public byte ApplicationID; + public byte CRC; + public byte DeviceType; + public byte Manufacturer; + public byte ManufacturingDate; + public string ProductName; + public byte ProductRevision; + public uint ProductSerialNumber; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Decoders + { + public static CID DecodeCID(uint[] response) + { + if(response?.Length != 4) + return null; + + byte[] data = new byte[16]; + + byte[] tmp = BitConverter.GetBytes(response[0]); + Array.Copy(tmp, 0, data, 0, 4); + tmp = BitConverter.GetBytes(response[1]); + Array.Copy(tmp, 0, data, 4, 4); + tmp = BitConverter.GetBytes(response[2]); + Array.Copy(tmp, 0, data, 8, 4); + tmp = BitConverter.GetBytes(response[3]); + Array.Copy(tmp, 0, data, 12, 4); + + return DecodeCID(data); + } + + public static CID DecodeCID(byte[] response) + { + if(response?.Length != 16) + return null; + + var cid = new CID + { + Manufacturer = response[0], + DeviceType = (byte)(response[1] & 0x03), + ProductRevision = response[9], + ProductSerialNumber = Swapping.Swap(BitConverter.ToUInt32(response, 10)), + ManufacturingDate = response[14], + CRC = (byte)((response[15] & 0xFE) >> 1) + }; + + byte[] tmp = new byte[6]; + Array.Copy(response, 3, tmp, 0, 6); + cid.ProductName = StringHandlers.CToString(tmp); + + return cid; + } + + public static string PrettifyCID(CID cid) + { + if(cid == null) + return null; + + var sb = new StringBuilder(); + + sb.AppendLine("MultiMediaCard Device Identification Register:"); + sb.AppendFormat("\tManufacturer: {0}", VendorString.Prettify(cid.Manufacturer)).AppendLine(); + + switch(cid.DeviceType) + { + case 0: + sb.AppendLine("\tRemovable device"); + + break; + case 1: + sb.AppendLine("\tBGA device"); + + break; + case 2: + sb.AppendLine("\tPOP device"); + + break; + } + + sb.AppendFormat("\tApplication ID: {0}", cid.ApplicationID).AppendLine(); + sb.AppendFormat("\tProduct name: {0}", cid.ProductName).AppendLine(); + + sb.AppendFormat("\tProduct revision: {0:X2}.{1:X2}", (cid.ProductRevision & 0xF0) >> 4, + cid.ProductRevision & 0x0F).AppendLine(); + + sb.AppendFormat("\tProduct serial number: {0}", cid.ProductSerialNumber).AppendLine(); + string year = ""; + + switch(cid.ManufacturingDate & 0x0F) + { + case 0: + year = "1997 or 2013"; + + break; + case 1: + year = "1998 or 2014"; + + break; + case 2: + year = "1999 or 2015"; + + break; + case 3: + year = "2000 or 2016"; + + break; + case 4: + year = "2001 or 2017"; + + break; + case 5: + year = "2002 or 2018"; + + break; + case 6: + year = "2003 or 2019"; + + break; + case 7: + year = "2004 or 2020"; + + break; + case 8: + year = "2005 or 2021"; + + break; + case 9: + year = "2006 or 2022"; + + break; + case 10: + year = "2007 or 2023"; + + break; + case 11: + year = "2008 or 2024"; + + break; + case 12: + year = "2009 or 2025"; + + break; + case 13: + year = "2010"; + + break; + case 14: + year = "2011"; + + break; + case 15: + year = "2012"; + + break; + } + + sb.AppendFormat("\tDevice manufactured month {0} of {1}", (cid.ManufacturingDate & 0xF0) >> 4, year). + AppendLine(); + + sb.AppendFormat("\tCID CRC: 0x{0:X2}", cid.CRC).AppendLine(); + + return sb.ToString(); + } + + public static string PrettifyCID(uint[] response) => PrettifyCID(DecodeCID(response)); + + public static string PrettifyCID(byte[] response) => PrettifyCID(DecodeCID(response)); + } +} \ No newline at end of file diff --git a/Aaru.Decoders/MMC/CSD.cs b/Aaru.Decoders/MMC/CSD.cs new file mode 100644 index 000000000..7713f2e75 --- /dev/null +++ b/Aaru.Decoders/MMC/CSD.cs @@ -0,0 +1,684 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CSD.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes MultiMediaCard CSD. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.MMC +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public class CSD + { + public ushort Classes; + public bool ContentProtection; + public bool Copy; + public byte CRC; + public byte DefaultECC; + public bool DSRImplemented; + public byte ECC; + public byte EraseGroupSize; + public byte EraseGroupSizeMultiplier; + public byte FileFormat; + public bool FileFormatGroup; + public byte NSAC; + public bool PermanentWriteProtect; + public byte ReadBlockLength; + public byte ReadCurrentAtVddMax; + public byte ReadCurrentAtVddMin; + public bool ReadMisalignment; + public bool ReadsPartialBlocks; + public ushort Size; + public byte SizeMultiplier; + public byte Speed; + public byte Structure; + public byte TAAC; + public bool TemporaryWriteProtect; + public byte Version; + public byte WriteBlockLength; + public byte WriteCurrentAtVddMax; + public byte WriteCurrentAtVddMin; + public bool WriteMisalignment; + public bool WriteProtectGroupEnable; + public byte WriteProtectGroupSize; + public bool WritesPartialBlocks; + public byte WriteSpeedFactor; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Decoders + { + public static CSD DecodeCSD(uint[] response) + { + if(response?.Length != 4) + return null; + + byte[] data = new byte[16]; + + byte[] tmp = BitConverter.GetBytes(response[0]); + Array.Copy(tmp, 0, data, 0, 4); + tmp = BitConverter.GetBytes(response[1]); + Array.Copy(tmp, 0, data, 4, 4); + tmp = BitConverter.GetBytes(response[2]); + Array.Copy(tmp, 0, data, 8, 4); + tmp = BitConverter.GetBytes(response[3]); + Array.Copy(tmp, 0, data, 12, 4); + + return DecodeCSD(data); + } + + public static CSD DecodeCSD(byte[] response) + { + if(response?.Length != 16) + return null; + + return new CSD + { + Structure = (byte)((response[0] & 0xC0) >> 6), + Version = (byte)((response[0] & 0x3C) >> 2), + TAAC = response[1], + NSAC = response[2], + Speed = response[3], + Classes = (ushort)((response[4] << 4) + ((response[5] & 0xF0) >> 4)), + ReadBlockLength = (byte)(response[5] & 0x0F), + ReadsPartialBlocks = (response[6] & 0x80) == 0x80, + WriteMisalignment = (response[6] & 0x40) == 0x40, + ReadMisalignment = (response[6] & 0x20) == 0x20, + DSRImplemented = (response[6] & 0x10) == 0x10, + Size = (ushort)(((response[6] & 0x03) << 10) + (response[7] << 2) + ((response[8] & 0xC0) >> 6)), + ReadCurrentAtVddMin = (byte)((response[8] & 0x38) >> 3), + ReadCurrentAtVddMax = (byte)(response[8] & 0x07), + WriteCurrentAtVddMin = (byte)((response[9] & 0xE0) >> 5), + WriteCurrentAtVddMax = (byte)((response[9] & 0x1C) >> 2), + SizeMultiplier = (byte)(((response[9] & 0x03) << 1) + ((response[10] & 0x80) >> 7)), + EraseGroupSize = (byte)((response[10] & 0x7C) >> 2), + EraseGroupSizeMultiplier = (byte)(((response[10] & 0x03) << 3) + ((response[11] & 0xE0) >> 5)), + WriteProtectGroupSize = (byte)(response[11] & 0x1F), + WriteProtectGroupEnable = (response[12] & 0x80) == 0x80, + DefaultECC = (byte)((response[12] & 0x60) >> 5), + WriteSpeedFactor = (byte)((response[12] & 0x1C) >> 2), + WriteBlockLength = (byte)(((response[12] & 0x03) << 2) + ((response[13] & 0xC0) >> 6)), + WritesPartialBlocks = (response[13] & 0x20) == 0x20, + ContentProtection = (response[13] & 0x01) == 0x01, + FileFormatGroup = (response[14] & 0x80) == 0x80, + Copy = (response[14] & 0x40) == 0x40, + PermanentWriteProtect = (response[14] & 0x20) == 0x20, + TemporaryWriteProtect = (response[14] & 0x10) == 0x10, + FileFormat = (byte)((response[14] & 0x0C) >> 2), + ECC = (byte)(response[14] & 0x03), + CRC = (byte)((response[15] & 0xFE) >> 1) + }; + } + + public static string PrettifyCSD(CSD csd) + { + if(csd == null) + return null; + + double unitFactor = 0; + double multiplier = 0; + string unit = ""; + + var sb = new StringBuilder(); + sb.AppendLine("MultiMediaCard Device Specific Data Register:"); + + switch(csd.Structure) + { + case 0: + sb.AppendLine("\tRegister version 1.0"); + + break; + case 1: + sb.AppendLine("\tRegister version 1.1"); + + break; + case 2: + sb.AppendLine("\tRegister version 1.2"); + + break; + case 3: + sb.AppendLine("\tRegister version is defined in Extended Device Specific Data Register"); + + break; + } + + switch(csd.TAAC & 0x07) + { + case 0: + unit = "ns"; + unitFactor = 1; + + break; + case 1: + unit = "ns"; + unitFactor = 10; + + break; + case 2: + unit = "ns"; + unitFactor = 100; + + break; + case 3: + unit = "μs"; + unitFactor = 1; + + break; + case 4: + unit = "μs"; + unitFactor = 10; + + break; + case 5: + unit = "μs"; + unitFactor = 100; + + break; + case 6: + unit = "ms"; + unitFactor = 1; + + break; + case 7: + unit = "ms"; + unitFactor = 10; + + break; + } + + switch((csd.TAAC & 0x78) >> 3) + { + case 0: + multiplier = 0; + + break; + case 1: + multiplier = 1; + + break; + case 2: + multiplier = 1.2; + + break; + case 3: + multiplier = 1.3; + + break; + case 4: + multiplier = 1.5; + + break; + case 5: + multiplier = 2; + + break; + case 6: + multiplier = 2.5; + + break; + case 7: + multiplier = 3; + + break; + case 8: + multiplier = 3.5; + + break; + case 9: + multiplier = 4; + + break; + case 10: + multiplier = 4.5; + + break; + case 11: + multiplier = 5; + + break; + case 12: + multiplier = 5.5; + + break; + case 13: + multiplier = 6; + + break; + case 14: + multiplier = 7; + + break; + case 15: + multiplier = 8; + + break; + } + + double result = unitFactor * multiplier; + sb.AppendFormat("\tAsynchronous data access time is {0}{1}", result, unit).AppendLine(); + + sb.AppendFormat("\tClock dependent part of data access is {0} clock cycles", csd.NSAC * 100).AppendLine(); + + unit = "MHz"; + + switch(csd.Speed & 0x07) + { + case 0: + unitFactor = 0.1; + + break; + case 1: + unitFactor = 1; + + break; + case 2: + unitFactor = 10; + + break; + case 3: + unitFactor = 100; + + break; + default: + unit = "unknown"; + unitFactor = 0; + + break; + } + + switch((csd.Speed & 0x78) >> 3) + { + case 0: + multiplier = 0; + + break; + case 1: + multiplier = 1; + + break; + case 2: + multiplier = 1.2; + + break; + case 3: + multiplier = 1.3; + + break; + case 4: + multiplier = 1.5; + + break; + case 5: + multiplier = 2; + + break; + case 6: + multiplier = 2.6; + + break; + case 7: + multiplier = 3; + + break; + case 8: + multiplier = 3.5; + + break; + case 9: + multiplier = 4; + + break; + case 10: + multiplier = 4.5; + + break; + case 11: + multiplier = 5.2; + + break; + case 12: + multiplier = 5.5; + + break; + case 13: + multiplier = 6; + + break; + case 14: + multiplier = 7; + + break; + case 15: + multiplier = 8; + + break; + } + + result = unitFactor * multiplier; + sb.AppendFormat("\tDevice's clock frequency: {0}{1}", result, unit).AppendLine(); + + unit = ""; + + for(int cl = 0, mask = 1; cl <= 11; cl++, mask <<= 1) + if((csd.Classes & mask) == mask) + unit += $" {cl}"; + + sb.AppendFormat("\tDevice support command classes {0}", unit).AppendLine(); + + if(csd.ReadBlockLength == 15) + sb.AppendLine("\tRead block length size is defined in extended CSD"); + else + sb.AppendFormat("\tRead block length is {0} bytes", Math.Pow(2, csd.ReadBlockLength)).AppendLine(); + + if(csd.ReadsPartialBlocks) + sb.AppendLine("\tDevice allows reading partial blocks"); + + if(csd.WriteMisalignment) + sb.AppendLine("\tWrite commands can cross physical block boundaries"); + + if(csd.ReadMisalignment) + sb.AppendLine("\tRead commands can cross physical block boundaries"); + + if(csd.DSRImplemented) + sb.AppendLine("\tDevice implements configurable driver stage"); + + if(csd.Size == 0xFFF) + sb.AppendLine("\tDevice may be bigger than 2GiB and have its real size defined in the extended CSD"); + + result = (csd.Size + 1) * Math.Pow(2, csd.SizeMultiplier + 2); + sb.AppendFormat("\tDevice has {0} blocks", (int)result).AppendLine(); + + result = (csd.Size + 1) * Math.Pow(2, csd.SizeMultiplier + 2) * Math.Pow(2, csd.ReadBlockLength); + + if(result > 1073741824) + sb.AppendFormat("\tDevice has {0} GiB", result / 1073741824.0).AppendLine(); + else if(result > 1048576) + sb.AppendFormat("\tDevice has {0} MiB", result / 1048576.0).AppendLine(); + else if(result > 1024) + sb.AppendFormat("\tDevice has {0} KiB", result / 1024.0).AppendLine(); + else + sb.AppendFormat("\tDevice has {0} bytes", result).AppendLine(); + + switch(csd.ReadCurrentAtVddMin & 0x07) + { + case 0: + sb.AppendLine("\tDevice uses a maximum of 0.5mA for reading at minimum voltage"); + + break; + case 1: + sb.AppendLine("\tDevice uses a maximum of 1mA for reading at minimum voltage"); + + break; + case 2: + sb.AppendLine("\tDevice uses a maximum of 5mA for reading at minimum voltage"); + + break; + case 3: + sb.AppendLine("\tDevice uses a maximum of 10mA for reading at minimum voltage"); + + break; + case 4: + sb.AppendLine("\tDevice uses a maximum of 25mA for reading at minimum voltage"); + + break; + case 5: + sb.AppendLine("\tDevice uses a maximum of 35mA for reading at minimum voltage"); + + break; + case 6: + sb.AppendLine("\tDevice uses a maximum of 60mA for reading at minimum voltage"); + + break; + case 7: + sb.AppendLine("\tDevice uses a maximum of 100mA for reading at minimum voltage"); + + break; + } + + switch(csd.ReadCurrentAtVddMax & 0x07) + { + case 0: + sb.AppendLine("\tDevice uses a maximum of 1mA for reading at maximum voltage"); + + break; + case 1: + sb.AppendLine("\tDevice uses a maximum of 5mA for reading at maximum voltage"); + + break; + case 2: + sb.AppendLine("\tDevice uses a maximum of 10mA for reading at maximum voltage"); + + break; + case 3: + sb.AppendLine("\tDevice uses a maximum of 25mA for reading at maximum voltage"); + + break; + case 4: + sb.AppendLine("\tDevice uses a maximum of 35mA for reading at maximum voltage"); + + break; + case 5: + sb.AppendLine("\tDevice uses a maximum of 45mA for reading at maximum voltage"); + + break; + case 6: + sb.AppendLine("\tDevice uses a maximum of 80mA for reading at maximum voltage"); + + break; + case 7: + sb.AppendLine("\tDevice uses a maximum of 200mA for reading at maximum voltage"); + + break; + } + + switch(csd.WriteCurrentAtVddMin & 0x07) + { + case 0: + sb.AppendLine("\tDevice uses a maximum of 0.5mA for writing at minimum voltage"); + + break; + case 1: + sb.AppendLine("\tDevice uses a maximum of 1mA for writing at minimum voltage"); + + break; + case 2: + sb.AppendLine("\tDevice uses a maximum of 5mA for writing at minimum voltage"); + + break; + case 3: + sb.AppendLine("\tDevice uses a maximum of 10mA for writing at minimum voltage"); + + break; + case 4: + sb.AppendLine("\tDevice uses a maximum of 25mA for writing at minimum voltage"); + + break; + case 5: + sb.AppendLine("\tDevice uses a maximum of 35mA for writing at minimum voltage"); + + break; + case 6: + sb.AppendLine("\tDevice uses a maximum of 60mA for writing at minimum voltage"); + + break; + case 7: + sb.AppendLine("\tDevice uses a maximum of 100mA for writing at minimum voltage"); + + break; + } + + switch(csd.WriteCurrentAtVddMax & 0x07) + { + case 0: + sb.AppendLine("\tDevice uses a maximum of 1mA for writing at maximum voltage"); + + break; + case 1: + sb.AppendLine("\tDevice uses a maximum of 5mA for writing at maximum voltage"); + + break; + case 2: + sb.AppendLine("\tDevice uses a maximum of 10mA for writing at maximum voltage"); + + break; + case 3: + sb.AppendLine("\tDevice uses a maximum of 25mA for writing at maximum voltage"); + + break; + case 4: + sb.AppendLine("\tDevice uses a maximum of 35mA for writing at maximum voltage"); + + break; + case 5: + sb.AppendLine("\tDevice uses a maximum of 45mA for writing at maximum voltage"); + + break; + case 6: + sb.AppendLine("\tDevice uses a maximum of 80mA for writing at maximum voltage"); + + break; + case 7: + sb.AppendLine("\tDevice uses a maximum of 200mA for writing at maximum voltage"); + + break; + } + + // TODO: Check specification + unitFactor = Convert.ToDouble(csd.EraseGroupSize); + multiplier = Convert.ToDouble(csd.EraseGroupSizeMultiplier); + result = (unitFactor + 1) * (multiplier + 1); + sb.AppendFormat("\tDevice can erase a minimum of {0} blocks at a time", (int)result).AppendLine(); + + if(csd.WriteProtectGroupEnable) + { + sb.AppendLine("\tDevice can write protect regions"); + + // TODO: Check specification + // unitFactor = Convert.ToDouble(csd.WriteProtectGroupSize); + + sb.AppendFormat("\tDevice can write protect a minimum of {0} blocks at a time", (int)(result + 1)). + AppendLine(); + } + else + sb.AppendLine("\tDevice can't write protect regions"); + + switch(csd.DefaultECC) + { + case 0: + sb.AppendLine("\tDevice uses no ECC by default"); + + break; + case 1: + sb.AppendLine("\tDevice uses BCH(542, 512) ECC by default"); + + break; + case 2: + sb.AppendFormat("\tDevice uses unknown ECC code {0} by default", csd.DefaultECC).AppendLine(); + + break; + } + + sb.AppendFormat("\tWriting is {0} times slower than reading", Math.Pow(2, csd.WriteSpeedFactor)). + AppendLine(); + + if(csd.WriteBlockLength == 15) + sb.AppendLine("\tWrite block length size is defined in extended CSD"); + else + sb.AppendFormat("\tWrite block length is {0} bytes", Math.Pow(2, csd.WriteBlockLength)).AppendLine(); + + if(csd.WritesPartialBlocks) + sb.AppendLine("\tDevice allows writing partial blocks"); + + if(csd.ContentProtection) + sb.AppendLine("\tDevice supports content protection"); + + if(!csd.Copy) + sb.AppendLine("\tDevice contents are original"); + + if(csd.PermanentWriteProtect) + sb.AppendLine("\tDevice is permanently write protected"); + + if(csd.TemporaryWriteProtect) + sb.AppendLine("\tDevice is temporarily write protected"); + + if(!csd.FileFormatGroup) + switch(csd.FileFormat) + { + case 0: + sb.AppendLine("\tDevice is formatted like a hard disk"); + + break; + case 1: + sb.AppendLine("\tDevice is formatted like a floppy disk using Microsoft FAT"); + + break; + case 2: + sb.AppendLine("\tDevice uses Universal File Format"); + + break; + default: + sb.AppendFormat("\tDevice uses unknown file format code {0}", csd.FileFormat).AppendLine(); + + break; + } + else + sb.AppendFormat("\tDevice uses unknown file format code {0} and file format group 1", csd.FileFormat). + AppendLine(); + + switch(csd.ECC) + { + case 0: + sb.AppendLine("\tDevice currently uses no ECC"); + + break; + case 1: + sb.AppendLine("\tDevice currently uses BCH(542, 512) ECC by default"); + + break; + case 2: + sb.AppendFormat("\tDevice currently uses unknown ECC code {0}", csd.DefaultECC).AppendLine(); + + break; + } + + sb.AppendFormat("\tCSD CRC: 0x{0:X2}", csd.CRC).AppendLine(); + + return sb.ToString(); + } + + public static string PrettifyCSD(uint[] response) => PrettifyCSD(DecodeCSD(response)); + + public static string PrettifyCSD(byte[] response) => PrettifyCSD(DecodeCSD(response)); + } +} \ No newline at end of file diff --git a/Aaru.Decoders/MMC/ExtendedCSD.cs b/Aaru.Decoders/MMC/ExtendedCSD.cs new file mode 100644 index 000000000..ad6220334 --- /dev/null +++ b/Aaru.Decoders/MMC/ExtendedCSD.cs @@ -0,0 +1,1228 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ExtendedCSD.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes MultiMediaCard extended CSD. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; +using System.Text; + +namespace Aaru.Decoders.MMC +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "UnassignedField.Global"), + StructLayout(LayoutKind.Sequential, Pack = 1)] + public class ExtendedCSD + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)] + public byte[] Reserved0; + public byte CommandQueueModeEnable; + public byte SecureRemovalType; + public byte ProductStateAwarenessEnablement; + public uint MaxPreLoadingDataSize; + public uint PreLoadingDataSize; + public byte FFUStatus; + public ushort Reserved1; + public byte ModeOperationCodes; + public byte ModeConfig; + public byte BarrierControl; + public byte CacheFlushing; + public byte CacheControl; + public byte PowerOffNotification; + public byte PackedCommandFailureIndex; + public byte PackedCommandStatus; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)] + public byte[] ContextConfiguration; + public ushort ExtendedPartitionsAttribute; + public ushort ExceptionEventsStatus; + public ushort ExceptionEventsControl; + public byte DyncapNeeded; + public byte Class6CommandsControl; + public byte InitializationTimeoutAfterEmulationChange; + public byte SectorSize; + public byte SectorSizeEmulation; + public byte NativeSectorSize; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] + public byte[] VendorSpecific; + public ushort Reserved2; + public byte SupportsProgramCxDInDDR; + public byte PeriodicWakeUp; + public byte PackageCaseTemperatureControl; + public byte ProductionStateAwareness; + public byte BadBlockManagementMode; + public byte Reserved3; + public uint EnhancedUserDataStartAddress; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] EnhancedUserDataAreaSize; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] GeneralPurposePartitionSize; + public byte PartitioningSetting; + public byte PartitionsAttribute; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] MaxEnhancedAreaSize; + public PartitioningSupport PartitioningSupport; + public byte HPIManagement; + public byte HWResetFunction; + public byte EnableBackgroundOperationsHandshake; + public byte ManuallyStartBackgroundOperations; + public byte StartSanitizeOperation; + public byte WriteReliabilityParameterRegister; + public byte WriteReliabilitySettingRegister; + public byte RPMBSize; + public byte FirmwareConfiguration; + public byte Reserved4; + public UserAreaWriteProtectionRegister UserAreaWriteProtectionRegister; + public byte Reserved5; + public BootAreaWriteProtectionRegister BootAreaWriteProtectionRegister; + public byte BootWriteProtectionStatus; + public HighCapacityEraseGroupDefinition HighCapacityEraseGroupDefinition; + public byte Reserved6; + public byte BootBusConditions; + public BootConfigProtection BootConfigProtection; + public byte PartitionConfiguration; + public byte Reserved7; + public byte ErasedMemoryContent; + public byte Reserved8; + public byte BusWidth; + public byte StrobeSupport; + public byte HighSpeedInterfaceTiming; + public byte Reserved9; + public byte PowerClass; + public byte Reserved10; + public byte CommandSetRevision; + public byte Reserved11; + public byte CommandSet; + public byte Revision; + public byte Reserved12; + public byte Structure; + public byte Reserved13; + public DeviceType DeviceType; + public DriverStrength DriverStrength; + public byte OutOfInterruptBusyTiming; + public byte PartitionSwitchingTime; + public byte PowerClass52_195; + public byte PowerClass26_195; + public byte PowerClass52; + public byte PowerClass26; + public byte Reserved14; + public byte MinimumReadPerformance26_4; + public byte MinimumWritePerformance26_4; + public byte MinimumReadPerformance26; + public byte MinimumWritePerformance26; + public byte MinimumReadPerformance52; + public byte MinimumWritePerformance52; + public SecureWriteProtectInformation SecureWriteProtectInformation; + public uint SectorCount; + public byte SleepNotificationTimeout; + public byte SleepAwakeTimeout; + public byte ProductionStateAwarenessTimeout; + public byte SleepCurrentVccQ; + public byte SleepCurrentVcc; + public byte HighCapacityWriteProtectGroupSize; + public byte ReliableWriteSectorCount; + public byte HighCapacityEraseTimeout; + public byte HighCapacityEraseUnitSize; + public byte AccessSize; + public byte BootPartitionSize; + public byte Reserved15; + public BootInformation BootInformation; + public byte SecureTRIMMultiplier; + public byte SecureEraseMultiplier; + public SecureFeatureSupport SecureFeatureSupport; + public byte TRIMMultiplier; + public byte Reserved16; + public byte MinimumReadPerformanceDDR52; + public byte MinimumWritePerformanceDDR52; + public byte PowerClassDDR200_130; + public byte PowerClassDDR200_195; + public byte PowerClassDDR52_195; + public byte PowerClassDDR52; + public CacheFlushingPolicy CacheFlushingPolicy; + public byte InitializationTimeAfterPartition; + public uint CorrectlyProgrammedSectors; + public byte BackgroundOperationsStatus; + public byte PowerOffNotificationTimeout; + public byte GenericCMD6Timeout; + public uint CacheSize; + public byte PowerClassDDR200; + public ulong FirmwareVersion; + public ushort DeviceVersion; + public byte OptimalTrimUnitSize; + public byte OptimalWriteSize; + public byte OptimalReadSize; + public byte PreEOLInformation; + public byte DeviceLifeEstimationTypeA; + public byte DeviceLifeEstimationTypeB; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] + public byte[] VendorHealthReport; + public uint NumberOfFWSectorsCorrectlyProgrammed; + public byte Reserved17; + public byte CMDQueuingDepth; + public CMDQueuingSupport CMDQueuingSupport; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 177)] + public byte[] Reserved18; + public byte BarrierSupport; + public uint FFUArgument; + public byte OperationCodesTimeout; + public FFUFeatures FFUFeatures; + public SupportedModes SupportedModes; + public ExtendedPartitionsSupport ExtendedPartitionsSupport; + public byte LargeUnitSize; + public byte ContextManagementCaps; + public byte TagResourcesSize; + public byte TagUnitSize; + public DataTagSupport DataTagSupport; + public byte MaxPackedWriteCommands; + public byte MaxPackedReadCommands; + public BackgroundOperationsSupport BackgroundOperationsSupport; + public HPIFeatures HPIFeatures; + public DeviceSupportedCommandSets SupportedCommandSets; + public byte ExtendedSecurityCommandsError; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + public byte[] Reserved19; + } + + [Flags] + public enum DeviceSupportedCommandSets : byte + { + Standard = 1 << 0 + } + + [Flags] + public enum HPIFeatures : byte + { + Supported = 1 << 0, CMD12 = 1 << 1 + } + + [Flags] + public enum BackgroundOperationsSupport : byte + { + Supported = 1 << 0 + } + + [Flags] + public enum DataTagSupport : byte + { + Supported = 1 << 0 + } + + [Flags] + public enum ExtendedPartitionsSupport : byte + { + SystemCode = 1 << 0, NonPersistent = 1 << 1 + } + + [Flags] + public enum SupportedModes : byte + { + FFU = 1 << 0, VendorSpecific = 1 << 1 + } + + [Flags] + public enum FFUFeatures : byte + { + SupportedModeOperationCodes = 1 << 0 + } + + [Flags] + public enum CMDQueuingSupport : byte + { + Supported = 1 << 0 + } + + [Flags] + public enum CacheFlushingPolicy : byte + { + FIFO = 1 << 0 + } + + [Flags] + public enum SecureFeatureSupport : byte + { + Purge = 1 << 0, Defective = 1 << 2, Trim = 1 << 4, + Sanitize = 1 << 6 + } + + [Flags] + public enum BootInformation : byte + { + Alternative = 1 << 0, DDR = 1 << 1, HighSpeed = 1 << 2 + } + + [Flags] + public enum SecureWriteProtectInformation : byte + { + Supported = 1 << 0, Enabled = 1 << 1 + } + + [Flags] + public enum DriverStrength : byte + { + Type0 = 1 << 0, Type1 = 1 << 1, Type2 = 1 << 2, + Type3 = 1 << 3, Type4 = 1 << 4 + } + + [Flags] + public enum DeviceType : byte + { + HS_26 = 1 << 0, HS_52 = 1 << 1, HS_DDR_52 = 1 << 2, + HS_DDR_52_LV = 1 << 3, HS200_18 = 1 << 4, HS200_12 = 1 << 5, + HS400_18 = 1 << 6, HS400_12 = 1 << 7 + } + + [Flags] + public enum BootConfigProtection : byte + { + PowerCycle = 1 << 0, Permanent = 1 << 4 + } + + [Flags] + public enum HighCapacityEraseGroupDefinition : byte + { + Enabled = 1 << 0 + } + + [Flags] + public enum BootAreaWriteProtectionRegister : byte + { + PowerOn = 1 << 0, PowerOnArea2 = 1 << 1, Permanent = 1 << 2, + PermanentArea2 = 1 << 3, PermanentDisable = 1 << 4, PowerOnDisable = 1 << 6, + Selected = 1 << 7 + } + + [Flags] + public enum UserAreaWriteProtectionRegister : byte + { + ApplyPowerOn = 1 << 0, ApplyPermanent = 1 << 2, DisablePowerOn = 1 << 3, + DisablePermanent = 1 << 4, DisableWriteProtect = 1 << 6, DisablePassword = 1 << 7 + } + + [Flags] + public enum PartitioningSupport : byte + { + Supported = 1 << 0, Enhanced = 1 << 1, Extended = 1 << 2 + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Decoders + { + public static ExtendedCSD DecodeExtendedCSD(byte[] response) + { + if(response?.Length != 512) + return null; + + var handle = GCHandle.Alloc(response, GCHandleType.Pinned); + var csd = (ExtendedCSD)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(ExtendedCSD)); + handle.Free(); + + return csd; + } + + public static string PrettifyExtendedCSD(ExtendedCSD csd) + { + if(csd == null) + return null; + + var sb = new StringBuilder(); + sb.AppendLine("MultiMediaCard Extended Device Specific Data Register:"); + + double unit; + + if(csd.ExtendedSecurityCommandsError != 0) + sb.AppendFormat("\tLast extended security error was {0}", csd.ExtendedSecurityCommandsError). + AppendLine(); + + if(csd.SupportedCommandSets.HasFlag(DeviceSupportedCommandSets.Standard)) + sb.AppendLine("\tDevice supports standard MMC command set"); + + if(((int)csd.SupportedCommandSets & 0xFE) != 0) + sb.AppendFormat("\tDevice supports unknown command sets 0x{0:X2}", (int)csd.SupportedCommandSets); + + if(csd.HPIFeatures.HasFlag(HPIFeatures.Supported)) + sb.AppendLine(csd.HPIFeatures.HasFlag(HPIFeatures.CMD12) ? "\tDevice implements HPI using CMD12" + : "\tDevice implements HPI using CMD13"); + + if(csd.BackgroundOperationsSupport.HasFlag(BackgroundOperationsSupport.Supported)) + sb.AppendLine("\tDevice supports background operations"); + + sb.AppendFormat("\tDevice supports a maximum of {0} packed reads and {1} packed writes", + csd.MaxPackedReadCommands, csd.MaxPackedWriteCommands).AppendLine(); + + if(csd.DataTagSupport.HasFlag(DataTagSupport.Supported)) + { + sb.AppendLine("\tDevice supports Data Tag"); + sb.AppendFormat("\tTags must be in units of {0} sectors", Math.Pow(2, csd.TagUnitSize)).AppendLine(); + sb.AppendFormat("\tTag resources size is {0}.", csd.TagResourcesSize).AppendLine(); + } + + if(csd.ContextManagementCaps != 0) + { + sb.AppendFormat("\tMax context ID is {0}.", csd.ContextManagementCaps & 0xF).AppendLine(); + + sb.AppendFormat("\tLarge unit maximum multiplier is {0}.", + ((csd.ContextManagementCaps & 0x70) >> 4) + 1).AppendLine(); + } + + sb.AppendFormat("\tLarge unit size is {0} MiB", csd.LargeUnitSize + 1).AppendLine(); + + if(csd.ExtendedPartitionsSupport.HasFlag(ExtendedPartitionsSupport.NonPersistent)) + sb.AppendLine("\tDevice supports non-persistent extended partitions"); + + if(csd.ExtendedPartitionsSupport.HasFlag(ExtendedPartitionsSupport.SystemCode)) + sb.AppendLine("\tDevice supports system code extended partitions"); + + if(csd.SupportedModes.HasFlag(SupportedModes.FFU)) + { + sb.AppendLine("\tDevice supports FFU"); + + if(csd.FFUFeatures.HasFlag(FFUFeatures.SupportedModeOperationCodes)) + { + // todo public byte ModeOperationCodes + + if(csd.OperationCodesTimeout > 0) + { + unit = Math.Pow(2, csd.OperationCodesTimeout) * 100; + + if(unit > 1000000) + sb. + AppendFormat("\t\tMaximum timeout for switch command when setting a value to the mode operation codes field is {0:D2}s", + unit / 1000000).AppendLine(); + else if(unit > 1000) + sb. + AppendFormat("\tMaximum timeout for switch command when setting a value to the mode operation codes field is {0:D2}ms", + unit / 1000).AppendLine(); + else + sb. + AppendFormat("\tMaximum timeout for switch command when setting a value to the mode operation codes field is {0:D2}µs", + unit).AppendLine(); + } + } + } + + if(csd.SupportedModes.HasFlag(SupportedModes.VendorSpecific)) + sb.AppendLine("\tDevice supports Vendor Specific Mode"); + + if(csd.BarrierSupport == 0x01) + { + sb.AppendLine("\tDevice supports the barrier command"); + } + + if(csd.CMDQueuingSupport.HasFlag(CMDQueuingSupport.Supported)) + sb.AppendFormat("\tDevice supports command queuing with a depth of {0}", csd.CMDQueuingDepth + 1). + AppendLine(); + + sb.AppendFormat("\t{0} firmware sectors correctly programmed", csd.NumberOfFWSectorsCorrectlyProgrammed). + AppendLine(); + + switch(csd.DeviceLifeEstimationTypeB) + { + case 1: + sb.AppendLine("\tDevice used between 0% and 10% of its estimated life time"); + + break; + case 2: + sb.AppendLine("\tDevice used between 10% and 20% of its estimated life time"); + + break; + case 3: + sb.AppendLine("\tDevice used between 20% and 30% of its estimated life time"); + + break; + case 4: + sb.AppendLine("\tDevice used between 30% and 40% of its estimated life time"); + + break; + case 5: + sb.AppendLine("\tDevice used between 40% and 50% of its estimated life time"); + + break; + case 6: + sb.AppendLine("\tDevice used between 50% and 60% of its estimated life time"); + + break; + case 7: + sb.AppendLine("\tDevice used between 60% and 70% of its estimated life time"); + + break; + case 8: + sb.AppendLine("\tDevice used between 70% and 80% of its estimated life time"); + + break; + case 9: + sb.AppendLine("\tDevice used between 80% and 90% of its estimated life time"); + + break; + case 10: + sb.AppendLine("\tDevice used between 90% and 100% of its estimated life time"); + + break; + case 11: + sb.AppendLine("\tDevice exceeded its maximum estimated life time"); + + break; + } + + switch(csd.DeviceLifeEstimationTypeA) + { + case 1: + sb.AppendLine("\tDevice used between 0% and 10% of its estimated life time"); + + break; + case 2: + sb.AppendLine("\tDevice used between 10% and 20% of its estimated life time"); + + break; + case 3: + sb.AppendLine("\tDevice used between 20% and 30% of its estimated life time"); + + break; + case 4: + sb.AppendLine("\tDevice used between 30% and 40% of its estimated life time"); + + break; + case 5: + sb.AppendLine("\tDevice used between 40% and 50% of its estimated life time"); + + break; + case 6: + sb.AppendLine("\tDevice used between 50% and 60% of its estimated life time"); + + break; + case 7: + sb.AppendLine("\tDevice used between 60% and 70% of its estimated life time"); + + break; + case 8: + sb.AppendLine("\tDevice used between 70% and 80% of its estimated life time"); + + break; + case 9: + sb.AppendLine("\tDevice used between 80% and 90% of its estimated life time"); + + break; + case 10: + sb.AppendLine("\tDevice used between 90% and 100% of its estimated life time"); + + break; + case 11: + sb.AppendLine("\tDevice exceeded its maximum estimated life time"); + + break; + } + + switch(csd.PreEOLInformation) + { + case 1: + sb.AppendLine("\tDevice informs it's in good health"); + + break; + case 2: + sb.AppendLine("\tDevice informs it should be replaced soon"); + + break; + case 3: + sb.AppendLine("\tDevice informs it should be replace immediately"); + + break; + } + + if(csd.OptimalReadSize == 0) + sb.AppendLine("\tDevice does not report an optimal read size"); + else + sb.AppendFormat("\tOptimal read size is {0} KiB", 4 * csd.OptimalReadSize).AppendLine(); + + if(csd.OptimalWriteSize == 0) + sb.AppendLine("\tDevice does not report an optimal write size"); + else + sb.AppendFormat("\tOptimal write size is {0} KiB", 4 * csd.OptimalWriteSize).AppendLine(); + + if(csd.OptimalTrimUnitSize == 0) + sb.AppendLine("\tDevice does not report an optimal trim size"); + else + sb.AppendFormat("\tOptimal trim size is {0} KiB", 4 * Math.Pow(2, csd.OptimalTrimUnitSize - 1)). + AppendLine(); + + sb.AppendFormat("\tDevice version: {0}", csd.DeviceVersion).AppendLine(); + sb.AppendFormat("\tFirmware version: {0}", csd.FirmwareVersion).AppendLine(); + + if(csd.CacheSize == 0) + sb.AppendLine("\tDevice has no cache"); + else + sb.AppendFormat("\tDevice has {0} KiB of cache", csd.CacheSize / 8).AppendLine(); + + if(csd.GenericCMD6Timeout > 0) + sb.AppendFormat("\tDevice takes a maximum of {0} ms by default for a SWITCH command", + csd.GenericCMD6Timeout * 10).AppendLine(); + + if(csd.PowerOffNotificationTimeout > 0) + sb. + AppendFormat("\tDevice takes a maximum of {0} by default to power off from a SWITCH command notification", + csd.PowerOffNotificationTimeout * 10).AppendLine(); + + switch(csd.BackgroundOperationsStatus & 0x03) + { + case 0: + sb.AppendLine("\tDevice has no pending background operations"); + + break; + case 1: + sb.AppendLine("\tDevice has non critical operations outstanding"); + + break; + case 2: + sb.AppendLine("\tDevice has performance impacted operations outstanding"); + + break; + case 3: + sb.AppendLine("\tDevice has critical operations outstanding"); + + break; + } + + sb.AppendFormat("\tLast WRITE MULTIPLE command correctly programmed {0} sectors", + csd.CorrectlyProgrammedSectors).AppendLine(); + + if(csd.InitializationTimeAfterPartition > 0) + sb.AppendFormat("\tDevice takes a maximum of {0} ms for initialization after partition", + csd.InitializationTimeAfterPartition * 100).AppendLine(); + + if(csd.CacheFlushingPolicy.HasFlag(CacheFlushingPolicy.FIFO)) + sb.AppendLine("\tDevice uses a FIFO policy for cache flushing"); + + if(csd.TRIMMultiplier > 0) + sb.AppendFormat("\tDevice takes a maximum of {0} ms for trimming a single erase group", + csd.TRIMMultiplier * 300).AppendLine(); + + if(csd.SecureFeatureSupport.HasFlag(SecureFeatureSupport.Sanitize)) + sb.AppendLine("\tDevice supports the sanitize operation"); + + if(csd.SecureFeatureSupport.HasFlag(SecureFeatureSupport.Trim)) + sb.AppendLine("\tDevice supports supports the secure and insecure trim operations"); + + if(csd.SecureFeatureSupport.HasFlag(SecureFeatureSupport.Defective)) + sb.AppendLine("\tDevice supports automatic erase on retired defective blocks"); + + if(csd.SecureFeatureSupport.HasFlag(SecureFeatureSupport.Purge)) + sb.AppendLine("\tDevice supports secure purge operations"); + + if(csd.SecureEraseMultiplier > 0) + sb.AppendFormat("\tDevice takes a maximum of {0} ms for securely erasing a single erase group", + csd.SecureEraseMultiplier * 300).AppendLine(); + + if(csd.SecureTRIMMultiplier > 0) + sb.AppendFormat("\tDevice takes a maximum of {0} ms for securely trimming a single erase group", + csd.SecureTRIMMultiplier * 300).AppendLine(); + + if(csd.BootInformation.HasFlag(BootInformation.HighSpeed)) + sb.AppendLine("\tDevice supports high speed timing on boot"); + + if(csd.BootInformation.HasFlag(BootInformation.DDR)) + sb.AppendLine("\tDevice supports dual data rate on boot"); + + if(csd.BootInformation.HasFlag(BootInformation.Alternative)) + sb.AppendLine("\tDevice supports alternative boot method"); + + if(csd.BootPartitionSize > 0) + sb.AppendFormat("\tDevice has a {0} KiB boot partition", csd.BootPartitionSize * 128).AppendLine(); + + if((csd.AccessSize & 0x0F) > 0) + sb.AppendFormat("\tDevice has a page size of {0} KiB", + 512 * Math.Pow(2, (csd.AccessSize & 0x0F) - 1) / 1024.0).AppendLine(); + + if(csd.HighCapacityEraseUnitSize > 0) + sb.AppendFormat("\tDevice erase groups are {0} KiB", csd.HighCapacityEraseUnitSize * 512).AppendLine(); + + if(csd.HighCapacityEraseTimeout > 0) + sb.AppendFormat("\tDevice takes a maximum of {0} ms for erasing a single erase group", + csd.HighCapacityEraseTimeout * 300).AppendLine(); + + if(csd.HighCapacityWriteProtectGroupSize > 0) + sb.AppendFormat("\tDevice smallest write protect group is made of {0} erase groups", + csd.HighCapacityWriteProtectGroupSize).AppendLine(); + + if(csd.SleepCurrentVcc > 0) + { + unit = Math.Pow(2, csd.SleepCurrentVcc); + + if(unit > 1000) + sb.AppendFormat("\tDevice uses {0} mA on Vcc when sleeping", unit / 1000).AppendLine(); + else + sb.AppendFormat("\tDevice uses {0} μA on Vcc when sleeping", unit).AppendLine(); + } + + if(csd.SleepCurrentVccQ > 0) + { + unit = Math.Pow(2, csd.SleepCurrentVccQ); + + if(unit > 1000) + sb.AppendFormat("\tDevice uses {0} mA on Vccq when sleeping", unit / 1000).AppendLine(); + else + sb.AppendFormat("\tDevice uses {0} μA on Vccq when sleeping", unit).AppendLine(); + } + + if(csd.ProductionStateAwarenessTimeout > 0) + { + unit = Math.Pow(2, csd.ProductionStateAwareness) * 100; + + if(unit > 1000000) + sb.AppendFormat("\tDevice takes a maximum of {0} s to switch production state awareness", + unit / 1000000).AppendLine(); + else if(unit > 1000) + sb.AppendFormat("\tDevice takes a maximum of {0} ms to switch production state awareness", + unit / 1000).AppendLine(); + else + sb.AppendFormat("\tDevice takes a maximum of {0} μs to switch production state awareness", unit). + AppendLine(); + } + + if(csd.SleepAwakeTimeout > 0) + { + unit = Math.Pow(2, csd.SleepAwakeTimeout) * 100; + + if(unit > 1000000) + sb.AppendFormat("\tDevice takes a maximum of {0} ms to transition between sleep and standby states", + unit / 1000000).AppendLine(); + else if(unit > 1000) + sb.AppendFormat("\tDevice takes a maximum of {0} μs to transition between sleep and standby states", + unit / 1000).AppendLine(); + else + sb.AppendFormat("\tDevice takes a maximum of {0} ns to transition between sleep and standby states", + unit).AppendLine(); + } + + if(csd.SleepNotificationTimeout > 0) + { + unit = Math.Pow(2, csd.SleepNotificationTimeout) * 10; + + if(unit > 1000000) + sb.AppendFormat("\tDevice takes a maximum of {0} s to move to sleep state", unit / 1000000). + AppendLine(); + else if(unit > 1000) + sb.AppendFormat("\tDevice takes a maximum of {0} ms to move to sleep state", unit / 1000). + AppendLine(); + else + sb.AppendFormat("\tDevice takes a maximum of {0} μs to move to sleep state", unit).AppendLine(); + } + + sb.AppendFormat("\tDevice has {0} sectors", csd.SectorCount).AppendLine(); + + if(csd.SecureWriteProtectInformation.HasFlag(SecureWriteProtectInformation.Supported)) + { + sb.AppendLine("\tDevice supports secure write protection"); + + if(csd.SecureWriteProtectInformation.HasFlag(SecureWriteProtectInformation.Enabled)) + sb.AppendLine("\tDevice has secure write protection enabled"); + } + + unit = csd.MinimumReadPerformance26 * 300; + + if(csd.MinimumReadPerformance26 == 0) + sb.AppendLine("\tDevice cannot achieve 2.4MB/s reading in SDR 26Mhz mode"); + else + sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in SDR 26Mhz mode", unit / 1000). + AppendLine(); + + unit = csd.MinimumReadPerformance26_4 * 300; + + if(csd.MinimumReadPerformance26_4 == 0) + sb.AppendLine("\tDevice cannot achieve 2.4MB/s reading in SDR 26Mhz 4-bit mode"); + else + sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in SDR 26Mhz 4-bit mode", + unit / 1000).AppendLine(); + + unit = csd.MinimumReadPerformance52 * 300; + + if(csd.MinimumReadPerformance52 == 0) + sb.AppendLine("\tDevice cannot achieve 2.4MB/s reading in SDR 52Mhz mode"); + else + sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in SDR 52Mhz mode", unit / 1000). + AppendLine(); + + unit = csd.MinimumReadPerformanceDDR52 * 600; + + if(csd.MinimumReadPerformanceDDR52 == 0) + sb.AppendLine("\tDevice cannot achieve 4.8MB/s reading in DDR 52Mhz mode"); + else + sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s reading in DDR 52Mhz mode", unit / 1000). + AppendLine(); + + unit = csd.MinimumWritePerformance26 * 300; + + if(csd.MinimumWritePerformance26 == 0) + sb.AppendLine("\tDevice cannot achieve 2.4MB/s writing in SDR 26Mhz mode"); + else + sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s writing in SDR 26Mhz mode", unit / 1000). + AppendLine(); + + unit = csd.MinimumWritePerformance26_4 * 300; + + if(csd.MinimumWritePerformance26_4 == 0) + sb.AppendLine("\tDevice cannot achieve 2.4MB/s writing in SDR 26Mhz 4-bit mode"); + else + sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s writing in SDR 26Mhz 4-bit mode", + unit / 1000).AppendLine(); + + unit = csd.MinimumWritePerformance52 * 300; + + if(csd.MinimumWritePerformance52 == 0) + sb.AppendLine("\tDevice cannot achieve 2.4MB/s writing in SDR 52Mhz mode"); + else + sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s writing in SDR 52Mhz mode", unit / 1000). + AppendLine(); + + unit = csd.MinimumWritePerformanceDDR52 * 600; + + if(csd.MinimumWritePerformanceDDR52 == 0) + sb.AppendLine("\tDevice cannot achieve 4.8MB/s writing in DDR 52Mhz mode"); + else + sb.AppendFormat("\tDevice can achieve a minimum of {0}MB/s writing in DDR 52Mhz mode", unit / 1000). + AppendLine(); + + if(csd.PartitionSwitchingTime > 0) + sb.AppendFormat("\tDevice can take a maximum of {0} ms when switching partitions", + csd.PartitionSwitchingTime * 10).AppendLine(); + + if(csd.OutOfInterruptBusyTiming > 0) + sb.AppendFormat("\tDevice can take a maximum of {0} ms when releasing from an interrupt", + csd.OutOfInterruptBusyTiming * 10).AppendLine(); + + if(csd.DriverStrength.HasFlag(DriverStrength.Type0)) + sb.AppendLine("\tDevice supports I/O driver strength type 0."); + + if(csd.DriverStrength.HasFlag(DriverStrength.Type1)) + sb.AppendLine("\tDevice supports I/O driver strength type 1."); + + if(csd.DriverStrength.HasFlag(DriverStrength.Type2)) + sb.AppendLine("\tDevice supports I/O driver strength type 2."); + + if(csd.DriverStrength.HasFlag(DriverStrength.Type3)) + sb.AppendLine("\tDevice supports I/O driver strength type 3."); + + if(csd.DriverStrength.HasFlag(DriverStrength.Type4)) + sb.AppendLine("\tDevice supports I/O driver strength type 4."); + + if(csd.DeviceType.HasFlag(DeviceType.HS_26)) + sb.AppendLine("\tDevice supports 26 Mhz mode"); + + if(csd.DeviceType.HasFlag(DeviceType.HS_52)) + sb.AppendLine("\tDevice supports 52 Mhz mode"); + + if(csd.DeviceType.HasFlag(DeviceType.HS_DDR_52)) + sb.AppendLine("\tDevice supports DDR 52 Mhz mode at 1.8V or 3V"); + + if(csd.DeviceType.HasFlag(DeviceType.HS_DDR_52_LV)) + sb.AppendLine("\tDevice supports DDR 52 Mhz mode 1.2V"); + + if(csd.DeviceType.HasFlag(DeviceType.HS200_18)) + sb.AppendLine("\tDevice supports HS-200 mode (SDR 200Mhz) at 1.8V"); + + if(csd.DeviceType.HasFlag(DeviceType.HS200_12)) + sb.AppendLine("\tDevice supports HS-200 mode (SDR 200Mhz) at 1.2V"); + + if(csd.DeviceType.HasFlag(DeviceType.HS400_18)) + sb.AppendLine("\tDevice supports HS-400 mode (DDR 200Mhz) at 1.8V"); + + if(csd.DeviceType.HasFlag(DeviceType.HS400_12)) + sb.AppendLine("\tDevice supports HS-400 mode (DDR 200Mhz) at 1.2V"); + + sb.AppendFormat("\tCSD version 1.{0} revision 1.{1}", csd.Structure, csd.Revision).AppendLine(); + + switch(csd.CommandSet) + { + case 0: + sb.AppendLine("\tDevice follows compatibility MMC command set."); + + break; + case 1: + switch(csd.CommandSetRevision) + { + case 0: + sb.AppendLine("\tDevice follows standard MMC command set v4.0."); + + break; + default: + sb.AppendFormat("\tDevice follows standard MMC command set with unknown version code {0}.", + csd.CommandSetRevision).AppendLine(); + + break; + } + + break; + default: + sb.AppendFormat("\tDevice follows unknown MMC command set code {0} with revision code {1}.", + csd.CommandSet, csd.CommandSetRevision).AppendLine(); + + break; + } + + switch(csd.HighSpeedInterfaceTiming & 0x0F) + { + case 0: break; + case 1: + sb.AppendLine("\tDevice is in High Speed mode."); + + break; + case 2: + sb.AppendLine("\tDevice is in HS-200 mode."); + + break; + case 3: + sb.AppendLine("\tDevice is in HS-400 mode."); + + break; + default: + sb.AppendFormat("\tDevice has unknown timing mode {0}.", csd.HighSpeedInterfaceTiming & 0x0F). + AppendLine(); + + break; + } + + sb.AppendFormat("\tSelected driver strength is type {0}.", (csd.HighSpeedInterfaceTiming & 0xF0) >> 4). + AppendLine(); + + if((csd.StrobeSupport & 0x01) == 0x01) + { + sb.AppendLine("\tDevice supports enhanced strobe mode"); + + sb.AppendLine((csd.BusWidth & 0x80) == 0x80 + ? "\tDevice uses strobe during Data Out, CRC and CMD responses" + : "\tDevice uses strobe during Data Out and CRC responses"); + } + + switch(csd.BusWidth & 0x0F) + { + case 0: + sb.AppendLine("\tDevice is using 1-bit data bus"); + + break; + case 1: + sb.AppendLine("\tDevice is using 4-bit data bus"); + + break; + case 2: + sb.AppendLine("\tDevice is using 8-bit data bus"); + + break; + case 5: + sb.AppendLine("\tDevice is using 4-bit DDR data bus"); + + break; + case 6: + sb.AppendLine("\tDevice is using 8-bit DDR data bus"); + + break; + default: + sb.AppendFormat("\tDevice is using unknown data bus code {0}", csd.BusWidth & 0x0F).AppendLine(); + + break; + } + + switch(csd.ErasedMemoryContent) + { + case 0: + case 1: + sb.AppendFormat("\tErased memory range shall be '{0}'.", csd.ErasedMemoryContent).AppendLine(); + + break; + default: + sb.AppendFormat("\tUnknown erased memory content code {0}", csd.ErasedMemoryContent).AppendLine(); + + break; + } + + if((csd.PartitionConfiguration & 0x40) == 0x40) + sb.AppendLine("\tDevice sends boot acknowledge"); + + switch((csd.PartitionConfiguration & 0x38) >> 3) + { + case 0: + sb.AppendLine("\tDevice is not boot enabled"); + + break; + case 1: + sb.AppendLine("\tDevice boot partition 1 is enabled"); + + break; + case 2: + sb.AppendLine("\tDevice boot partition 2 is enabled"); + + break; + case 7: + sb.AppendLine("\tDevice user area is enable for boot"); + + break; + default: + sb.AppendFormat("\tUnknown enabled boot partition code {0}", + (csd.PartitionConfiguration & 0x38) >> 3).AppendLine(); + + break; + } + + switch(csd.PartitionConfiguration & 0x07) + { + case 0: + sb.AppendLine("\tThere is no access to boot partition"); + + break; + case 1: + sb.AppendLine("\tThere is read/write access to boot partition 1"); + + break; + case 2: + sb.AppendLine("\tThere is read/write access to boot partition 2"); + + break; + case 3: + sb.AppendLine("\tThere is read/write access to replay protected memory block"); + + break; + default: + sb.AppendFormat("\tThere is access to general purpose partition {0}", + (csd.PartitionConfiguration & 0x07) - 3).AppendLine(); + + break; + } + + if(csd.BootConfigProtection.HasFlag(BootConfigProtection.Permanent)) + sb.AppendLine("\tChange of the boot configuration register bits is permanently disabled."); + else if(csd.BootConfigProtection.HasFlag(BootConfigProtection.PowerCycle)) + sb.AppendLine("\tChange of the boot configuration register bits is disabled until the next power cycle."); + + switch(csd.BootBusConditions & 0x03) + { + case 0: + sb.AppendLine("\tDevice will boot up in x1 SDR or x4 DDR bus width."); + + break; + case 1: + sb.AppendLine("\tDevice will boot up in x4 SDR or DDR bus width."); + + break; + case 2: + sb.AppendLine("\tDevice will boot up in x8 SDR or DDR bus width."); + + break; + case 3: + sb.AppendLine("\tUnknown boot condition for bus width with code 3."); + + break; + } + + sb.AppendLine((csd.BootBusConditions & 4) == 4 + ? "\tDevice will retain boot conditions after boot operation." + : "\tDevice will reset boot conditions to compatibility mode after boot operation."); + + switch((csd.BootBusConditions & 0x24) >> 3) + { + case 0: + sb.AppendLine("\tDevice will use single data rate with compatible timings in boot operation."); + + break; + case 1: + sb.AppendLine("\tDevice will use single data rate with high speed timings in boot operation."); + + break; + case 2: + sb.AppendLine("\tDevice will use dual data rate in boot operation."); + + break; + case 3: + sb.AppendLine("\tDevice will use unknown boot mode with code 3."); + + break; + } + + if(csd.HighCapacityEraseGroupDefinition.HasFlag(HighCapacityEraseGroupDefinition.Enabled)) + sb.AppendLine("\tDevice will use high capacity erase unit size, timeout and write protect group size definitions."); + + switch(csd.BootWriteProtectionStatus & 0x03) + { + case 0: + sb.AppendLine("\tBoot area 1 is not protected"); + + break; + case 1: + sb.AppendLine("\tBoot area 1 is power on protected"); + + break; + case 2: + sb.AppendLine("\tBoot area 1 is permanently protected"); + + break; + } + + switch((csd.BootWriteProtectionStatus & 0x0C) >> 2) + { + case 0: + sb.AppendLine("\tBoot area 2 is not protected"); + + break; + case 1: + sb.AppendLine("\tBoot area 2 is power on protected"); + + break; + case 2: + sb.AppendLine("\tBoot area 2 is permanently protected"); + + break; + } + + if(csd.BootAreaWriteProtectionRegister.HasFlag(BootAreaWriteProtectionRegister.Permanent)) + { + if(csd.BootAreaWriteProtectionRegister.HasFlag(BootAreaWriteProtectionRegister.Selected)) + { + sb.AppendLine(csd.BootAreaWriteProtectionRegister.HasFlag(BootAreaWriteProtectionRegister. + PermanentArea2) + ? "\tBoot area 2 is permanently write protected." + : "\tBoot area 1 is permanently write protected."); + } + else + sb.AppendLine("\tBoth boot areas are permanently write protected."); + } + else if(csd.BootAreaWriteProtectionRegister.HasFlag(BootAreaWriteProtectionRegister.PowerOn)) + { + if(csd.BootAreaWriteProtectionRegister.HasFlag(BootAreaWriteProtectionRegister.Selected)) + { + sb.AppendLine(csd.BootAreaWriteProtectionRegister.HasFlag(BootAreaWriteProtectionRegister. + PowerOnArea2) + ? "\tBoot area 2 is write protected until next power cycle." + : "\tBoot area 1 is write protected until next power cycle."); + } + else + sb.AppendLine("\tBoth boot areas are write protected until next power cycle."); + } + + if(csd.BootAreaWriteProtectionRegister.HasFlag(BootAreaWriteProtectionRegister.PermanentDisable)) + sb.AppendLine("\tPermanent write protection of boot areas is disabled."); + + if(csd.BootAreaWriteProtectionRegister.HasFlag(BootAreaWriteProtectionRegister.PowerOnDisable)) + sb.AppendLine("\tPower cycled write protection of boot areas is disabled."); + + if(csd.UserAreaWriteProtectionRegister.HasFlag(UserAreaWriteProtectionRegister.DisablePassword)) + sb.AppendLine("\tUse of password protection features is permanently disabled."); + + if(csd.UserAreaWriteProtectionRegister.HasFlag(UserAreaWriteProtectionRegister.DisableWriteProtect)) + sb.AppendLine("\tUse of permanent write protection is disabled."); + + if(csd.UserAreaWriteProtectionRegister.HasFlag(UserAreaWriteProtectionRegister.DisablePermanent)) + sb.AppendLine("\tPermanent write protection is disabled."); + + if(csd.UserAreaWriteProtectionRegister.HasFlag(UserAreaWriteProtectionRegister.DisablePowerOn)) + sb.AppendLine("\tPower cycled write protection is disabled."); + + if(csd.UserAreaWriteProtectionRegister.HasFlag(UserAreaWriteProtectionRegister.ApplyPermanent)) + sb.AppendLine("\tPermanent write protection will be applied to selected group."); + + if(csd.UserAreaWriteProtectionRegister.HasFlag(UserAreaWriteProtectionRegister.ApplyPowerOn)) + sb.AppendLine("\tPower cycled write protection will be applied to selected group."); + + if((csd.FirmwareConfiguration & 0x01) == 0x01) + sb.AppendLine("\tFirmware updates are permanently disabled"); + + if(csd.RPMBSize > 0) + sb.AppendFormat("\tDevice has a {0} KiB replay protected memory block", csd.RPMBSize * 128). + AppendLine(); + + if(csd.PartitioningSupport.HasFlag(PartitioningSupport.Supported)) + { + sb.AppendLine("\tDevice supports partitioning features"); + + if(csd.PartitioningSupport.HasFlag(PartitioningSupport.Enhanced)) + sb.AppendLine("\tDevice can have enhanced technological features in partitions and user data area"); + + if(csd.PartitioningSupport.HasFlag(PartitioningSupport.Extended)) + sb.AppendLine("\tDevice can have extended partitions attribute."); + } + + switch(csd.NativeSectorSize) + { + case 0: + sb.AppendLine("\tDevice natively uses 512 byte sectors"); + + break; + case 1: + sb.AppendLine("\tDevice natively uses 4096 byte sectors"); + + break; + default: + sb.AppendFormat("\tDevice natively uses unknown sector size indicated by code {0}", + csd.NativeSectorSize).AppendLine(); + + break; + } + + switch(csd.SectorSizeEmulation) + { + case 0: + sb.AppendLine("\tDevice is emulating 512 byte sectors"); + + break; + case 1: + sb.AppendLine("\tDevice is using natively sized sectors"); + + break; + default: + sb.AppendFormat("\tDevice emulates unknown sector size indicated by code {0}", + csd.NativeSectorSize).AppendLine(); + + break; + } + + switch(csd.SectorSize) + { + case 0: + sb.AppendLine("\tDevice currently addresses 512 byte sectors"); + + break; + case 1: + sb.AppendLine("\tDevice currently addresses 4096 byte sectors"); + + break; + default: + sb.AppendFormat("\tDevice currently addresses unknown sector size indicated by code {0}", + csd.NativeSectorSize).AppendLine(); + + break; + } + + if((csd.CacheControl & 0x01) == 0x01) + sb.AppendLine("\tDevice's cache is enabled"); + + if((csd.CommandQueueModeEnable & 0x01) == 0x01) + sb.AppendLine("\tDevice has enabled command queuing"); + + return sb.ToString(); + } + + public static string PrettifyExtendedCSD(byte[] response) => PrettifyExtendedCSD(DecodeExtendedCSD(response)); + } +} \ No newline at end of file diff --git a/Aaru.Decoders/MMC/OCR.cs b/Aaru.Decoders/MMC/OCR.cs new file mode 100644 index 000000000..7ead3792e --- /dev/null +++ b/Aaru.Decoders/MMC/OCR.cs @@ -0,0 +1,182 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : OCR.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes MultiMediaCard OCR. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Helpers; + +namespace Aaru.Decoders.MMC +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public class OCR + { + public byte AccessMode; + public bool OneSix; + public bool PowerUp; + public bool ThreeFive; + public bool ThreeFour; + public bool ThreeOne; + public bool ThreeThree; + public bool ThreeTwo; + public bool ThreeZero; + public bool TwoEight; + public bool TwoFive; + public bool TwoFour; + public bool TwoNine; + public bool TwoOne; + public bool TwoSeven; + public bool TwoSix; + public bool TwoThree; + public bool TwoTwo; + public bool TwoZero; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Decoders + { + public static OCR DecodeOCR(uint response) + { + response = Swapping.Swap(response); + + return new OCR + { + PowerUp = (response & 0x80000000) == 0x80000000, + AccessMode = (byte)((response & 0x60000000) >> 29), + ThreeFive = (response & 0x00800000) == 0x00800000, + ThreeFour = (response & 0x00400000) == 0x00400000, + ThreeThree = (response & 0x00200000) == 0x00200000, + ThreeTwo = (response & 0x00100000) == 0x00100000, + ThreeOne = (response & 0x00080000) == 0x00080000, + ThreeZero = (response & 0x00040000) == 0x00040000, + TwoNine = (response & 0x00020000) == 0x00020000, + TwoEight = (response & 0x00010000) == 0x00010000, + TwoSeven = (response & 0x00008000) == 0x00008000, + TwoSix = (response & 0x00004000) == 0x00004000, + TwoFive = (response & 0x00002000) == 0x00002000, + TwoFour = (response & 0x00001000) == 0x00001000, + TwoThree = (response & 0x00000800) == 0x00000800, + TwoTwo = (response & 0x00000400) == 0x00000400, + TwoOne = (response & 0x00000200) == 0x00000200, + TwoZero = (response & 0x00000100) == 0x00000100, + OneSix = (response & 0x00000080) == 0x00000080 + }; + } + + public static OCR DecodeOCR(byte[] response) => + response?.Length != 4 ? null : DecodeOCR(BitConverter.ToUInt32(response, 0)); + + public static string PrettifyOCR(OCR ocr) + { + if(ocr == null) + return null; + + var sb = new StringBuilder(); + sb.AppendLine("MultiMediaCard Operation Conditions Register:"); + + if(!ocr.PowerUp) + sb.AppendLine("\tDevice is powering up"); + + switch(ocr.AccessMode) + { + case 0: + sb.AppendLine("\tDevice is byte addressed"); + + break; + case 2: + sb.AppendLine("\tDevice is sector addressed"); + + break; + default: + sb.AppendFormat("\tUnknown device access mode {0}", ocr.AccessMode).AppendLine(); + + break; + } + + if(ocr.ThreeFive) + sb.AppendLine("\tDevice can work with supply 3.5~3.6V"); + + if(ocr.ThreeFour) + sb.AppendLine("\tDevice can work with supply 3.4~3.5V"); + + if(ocr.ThreeThree) + sb.AppendLine("\tDevice can work with supply 3.3~3.4V"); + + if(ocr.ThreeTwo) + sb.AppendLine("\tDevice can work with supply 3.2~3.3V"); + + if(ocr.ThreeOne) + sb.AppendLine("\tDevice can work with supply 3.1~3.2V"); + + if(ocr.TwoNine) + sb.AppendLine("\tDevice can work with supply 2.9~3.0V"); + + if(ocr.TwoEight) + sb.AppendLine("\tDevice can work with supply 2.8~2.9V"); + + if(ocr.TwoSeven) + sb.AppendLine("\tDevice can work with supply 2.7~2.8V"); + + if(ocr.TwoSix) + sb.AppendLine("\tDevice can work with supply 2.6~2.7V"); + + if(ocr.TwoFive) + sb.AppendLine("\tDevice can work with supply 2.5~2.6V"); + + if(ocr.TwoFour) + sb.AppendLine("\tDevice can work with supply 2.4~2.5V"); + + if(ocr.TwoThree) + sb.AppendLine("\tDevice can work with supply 2.3~2.4V"); + + if(ocr.TwoTwo) + sb.AppendLine("\tDevice can work with supply 2.2~2.3V"); + + if(ocr.TwoOne) + sb.AppendLine("\tDevice can work with supply 2.1~2.2V"); + + if(ocr.TwoZero) + sb.AppendLine("\tDevice can work with supply 2.0~2.1V"); + + if(ocr.OneSix) + sb.AppendLine("\tDevice can work with supply 1.65~1.95V"); + + return sb.ToString(); + } + + public static string PrettifyOCR(byte[] response) => PrettifyOCR(DecodeOCR(response)); + + public static string PrettifyOCR(uint response) => PrettifyOCR(DecodeOCR(response)); + } +} \ No newline at end of file diff --git a/Aaru.Decoders/MMC/VendorString.cs b/Aaru.Decoders/MMC/VendorString.cs new file mode 100644 index 000000000..af6e4f725 --- /dev/null +++ b/Aaru.Decoders/MMC/VendorString.cs @@ -0,0 +1,49 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : VendorString.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes MultiMediaCard vendor code. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.Decoders.MMC +{ + /// Decodes MultiMediaCard vendors + public static class VendorString + { + /// Converts the byte value of a MultiMediaCard vendor ID to the manufacturer's name string + /// MMC vendor ID + /// Manufacturer + public static string Prettify(byte mmcVendorId) => mmcVendorId switch + { + 0x07 => "Nokia", + 0x15 => "Samsung", + 0x2C => "extreMEmory", + _ => $"Unknown manufacturer ID 0x{mmcVendorId:X2}" + }; + } +} \ No newline at end of file diff --git a/Aaru.Decoders/PCMCIA/CIS.cs b/Aaru.Decoders/PCMCIA/CIS.cs new file mode 100644 index 000000000..449b70753 --- /dev/null +++ b/Aaru.Decoders/PCMCIA/CIS.cs @@ -0,0 +1,318 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CIS.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes PCMCIA Card Information Structure. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using Aaru.Helpers; + +namespace Aaru.Decoders.PCMCIA +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class CIS + { + // TODO: Handle links? Or are they removed in lower layers of the operating system drivers? + public static Tuple[] GetTuples(byte[] data) + { + List tuples = new List(); + int position = 0; + + while(position < data.Length) + { + var tuple = new Tuple + { + Code = (TupleCodes)data[position] + }; + + if(tuple.Code == TupleCodes.CISTPL_NULL) + continue; + + if(tuple.Code == TupleCodes.CISTPL_END) + break; + + tuple.Link = data[position + 1]; + + if(position + 2 + tuple.Link > data.Length) + break; + + tuple.Data = new byte[tuple.Link + 2]; + Array.Copy(data, position, tuple.Data, 0, tuple.Link + 2); + + tuples.Add(tuple); + position += tuple.Link + 2; + } + + return tuples.ToArray(); + } + + public static DeviceGeometryTuple DecodeDeviceGeometryTuple(Tuple tuple) + { + if(tuple == null) + return null; + + if(tuple.Code != TupleCodes.CISTPL_DEVICEGEO && + tuple.Code != TupleCodes.CISTPL_DEVICEGEO_A) + return null; + + return tuple.Data == null ? null : DecodeDeviceGeometryTuple(tuple.Data); + } + + public static DeviceGeometryTuple DecodeDeviceGeometryTuple(byte[] data) + { + if((data?.Length - 2) % 6 != 0) + return null; + + var tuple = new DeviceGeometryTuple(); + List geometries = new List(); + + for(int position = 2; position < data.Length; position += 6) + { + var geometry = new DeviceGeometry + { + CardInterface = data[position], + EraseBlockSize = data[position + 1], + ReadBlockSize = data[position + 2], + WriteBlockSize = data[position + 3], + Partitions = data[position + 4], + Interleaving = data[position + 5] + }; + + geometries.Add(geometry); + } + + tuple.Code = (TupleCodes)data[0]; + tuple.Link = data[1]; + tuple.Geometries = geometries.ToArray(); + + return tuple; + } + + public static string PrettifyDeviceGeometryTuple(DeviceGeometryTuple tuple) + { + if(tuple == null) + return null; + + if(tuple.Code != TupleCodes.CISTPL_DEVICEGEO && + tuple.Code != TupleCodes.CISTPL_DEVICEGEO_A) + return null; + + var sb = new StringBuilder(); + sb.AppendLine("PCMCIA Device Geometry Tuples:"); + + foreach(DeviceGeometry geometry in tuple.Geometries) + { + sb.AppendLine("\tGeometry:"); + sb.AppendFormat("\t\tDevice width: {0} bits", (1 << (geometry.CardInterface - 1)) * 8).AppendLine(); + + sb.AppendFormat("\t\tErase block = {0} bytes", + (1 << (geometry.EraseBlockSize - 1)) * (1 << (geometry.Interleaving - 1))).AppendLine(); + + sb.AppendFormat("\t\tRead block = {0} bytes", + (1 << (geometry.ReadBlockSize - 1)) * (1 << (geometry.Interleaving - 1))).AppendLine(); + + sb.AppendFormat("\t\tWrite block = {0} bytes", + (1 << (geometry.WriteBlockSize - 1)) * (1 << (geometry.Interleaving - 1))).AppendLine(); + + sb.AppendFormat("\t\tPartition alignment = {0} bytes", + (1 << (geometry.EraseBlockSize - 1)) * (1 << (geometry.Interleaving - 1)) * + (1 << (geometry.Partitions - 1))).AppendLine(); + } + + return sb.ToString(); + } + + public static string PrettifyDeviceGeometryTuple(Tuple tuple) => + PrettifyDeviceGeometryTuple(DecodeDeviceGeometryTuple(tuple)); + + public static string PrettifyDeviceGeometryTuple(byte[] data) => + PrettifyDeviceGeometryTuple(DecodeDeviceGeometryTuple(data)); + + public static ManufacturerIdentificationTuple DecodeManufacturerIdentificationTuple(Tuple tuple) + { + if(tuple?.Code != TupleCodes.CISTPL_MANFID) + return null; + + return tuple.Data == null ? null : DecodeManufacturerIdentificationTuple(tuple.Data); + } + + public static ManufacturerIdentificationTuple DecodeManufacturerIdentificationTuple(byte[] data) + { + if(data == null) + return null; + + if(data.Length < 6) + return null; + + return new ManufacturerIdentificationTuple + { + Code = (TupleCodes)data[0], + Link = data[1], + ManufacturerID = BitConverter.ToUInt16(data, 2), + CardID = BitConverter.ToUInt16(data, 4) + }; + } + + public static string PrettifyManufacturerIdentificationTuple(ManufacturerIdentificationTuple tuple) + { + if(tuple?.Code != TupleCodes.CISTPL_MANFID) + return null; + + var sb = new StringBuilder(); + sb.AppendLine("PCMCIA Manufacturer Identification Tuple:"); + sb.AppendFormat("\tManufacturer ID: {0}", VendorCode.Prettify(tuple.ManufacturerID)).AppendLine(); + sb.AppendFormat("\tCard ID:D 0x{0:X4}", tuple.CardID).AppendLine(); + + return sb.ToString(); + } + + public static string PrettifyManufacturerIdentificationTuple(Tuple tuple) => + PrettifyManufacturerIdentificationTuple(DecodeManufacturerIdentificationTuple(tuple)); + + public static string PrettifyManufacturerIdentificationTuple(byte[] data) => + PrettifyManufacturerIdentificationTuple(DecodeManufacturerIdentificationTuple(data)); + + public static Level1VersionTuple DecodeLevel1VersionTuple(Tuple tuple) + { + if(tuple?.Code != TupleCodes.CISTPL_VERS_1) + return null; + + return tuple.Data == null ? null : DecodeLevel1VersionTuple(tuple.Data); + } + + public static Level1VersionTuple DecodeLevel1VersionTuple(byte[] data) + { + if(data == null) + return null; + + if(data.Length < 4) + return null; + + List buffer = new List(); + List strings = null; + bool firstString = false; + bool secondString = false; + + var tuple = new Level1VersionTuple + { + Code = (TupleCodes)data[0], + Link = data[1], + MajorVersion = data[2], + MinorVersion = data[3] + }; + + for(int position = 4; position < data.Length; position++) + { + if(data[position] == 0xFF) + break; + + buffer.Add(data[position]); + + if(data[position] != 0x00) + continue; + + if(!firstString) + { + tuple.Manufacturer = StringHandlers.CToString(buffer.ToArray()); + buffer = new List(); + firstString = true; + + continue; + } + + // TODO: Check this + if(!secondString) + { + tuple.Product = StringHandlers.CToString(buffer.ToArray()); + buffer = new List(); + firstString = true; + + continue; + } + + if(strings == null) + strings = new List(); + + strings.Add(StringHandlers.CToString(buffer.ToArray())); + buffer = new List(); + } + + if(strings != null) + tuple.AdditionalInformation = strings.ToArray(); + + return tuple; + } + + public static string PrettifyLevel1VersionTuple(Level1VersionTuple tuple) + { + if(tuple?.Code != TupleCodes.CISTPL_VERS_1) + return null; + + var sb = new StringBuilder(); + sb.AppendLine("PCMCIA Level 1 Version / Product Information Tuple:"); + + sb.AppendFormat("\tCard indicates compliance with PC Card Standard Release {0}.{1}", tuple.MajorVersion, + tuple.MinorVersion).AppendLine(); + + if(string.IsNullOrEmpty(tuple.Manufacturer)) + sb.AppendLine("\tNo manufacturer information string."); + else + sb.AppendFormat("\tManufacturer: {0}", tuple.Manufacturer).AppendLine(); + + if(string.IsNullOrEmpty(tuple.Product)) + sb.AppendLine("\tNo product name string."); + else + sb.AppendFormat("\tProduct name: {0}", tuple.Product).AppendLine(); + + if(tuple.AdditionalInformation == null || + tuple.AdditionalInformation.Length == 0) + sb.AppendLine("\tNo additional information."); + else + { + sb.AppendLine("\tAdditional information:"); + + foreach(string info in tuple.AdditionalInformation.Where(info => !string.IsNullOrEmpty(info))) + sb.AppendFormat("\t\t{0}", info).AppendLine(); + } + + return sb.ToString(); + } + + public static string PrettifyLevel1VersionTuple(Tuple tuple) => + PrettifyLevel1VersionTuple(DecodeLevel1VersionTuple(tuple)); + + public static string PrettifyLevel1VersionTuple(byte[] data) => + PrettifyLevel1VersionTuple(DecodeLevel1VersionTuple(data)); + } +} \ No newline at end of file diff --git a/Aaru.Decoders/PCMCIA/Enums.cs b/Aaru.Decoders/PCMCIA/Enums.cs new file mode 100644 index 000000000..b34cafbe9 --- /dev/null +++ b/Aaru.Decoders/PCMCIA/Enums.cs @@ -0,0 +1,174 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Enums.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Contains PCMCIA enumerations. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.Decoders.PCMCIA +{ + /// Tuple codes. + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum TupleCodes : byte + { + /// Checksum control + CISTPL_CHECKSUM = 0x10, + /// End-of-chain + CISTPL_END = 0xFF, + /// Indirect access PC Card memory + CISTPL_INDIRECT = 0x03, + /// Link-target-control + CISTPL_LINKTARGET = 0x13, + /// Longlink to attribute memory + CISTPL_LONGLINK_A = 0x11, + /// Longlink to common memory + CISTPL_LONGLINK_C = 0x12, + /// Longlink to next chain on a Cardbus PC Card + CISTPL_LONGLINK_CB = 0x02, + /// Longlink to function specific chains + CISTPL_LONGLINK_MFC = 0x06, + /// No-link to common memory + CISTPL_NO_LINK = 0x14, + /// Null tuple + CISTPL_NULL = 0x00, + /// Alternate language string + CISTPL_ALTSTR = 0x16, + /// Common memory device information + CISTPL_DEVICE = 0x01, + /// Attribute memory device information + CISTPL_DEVICE_A = 0x17, + /// Other operating conditions information for attribute memory + CISTPL_DEVICE_OA = 0x1D, + /// Other operating conditions information for common memory + CISTPL_DEVICE_OC = 0x1C, + /// Device geometry information for common memory + CISTPL_DEVICEGEO = 0x1E, + /// Device geometry information for attribute memory + CISTPL_DEVICEGEO_A = 0x1F, + /// Extended common memory device information + CISTPL_EXTDEVIC = 0x09, + /// Function extensions + CISTPL_FUNCE = 0x22, + /// Function class identification + CISTPL_FUNCID = 0x21, + /// JEDEC programming information for attribute memory + CISTPL_JEDEC_A = 0x19, + /// JEDEC programming information for common memory + CISTPL_JEDEC_C = 0x18, + /// Manufacturer identification string + CISTPL_MANFID = 0x20, + /// Level 1 version/product information + CISTPL_VERS_1 = 0x15, + /// BAR for a CardBus PC Card + CISTPL_BAR = 0x07, + /// Configuration-table-entry + CISTPL_CFTABLE_ENTRY = 0x1B, + /// Configuration-table-entry for a CardBus PC Card + CISTPL_CFTABLE_ENTRY_CB = 0x05, + /// Configuration tuple for a 16-bit PC Card + CISTPL_CONFIG = 0x1A, + /// Configuration tuple for a CardBus PC Card + CISTPL_CONFIG_CB = 0x04, + /// Function state save/restore definition + CISTPL_PWR_MGMNT = 0x08, + /// Battery replacement date + CISTPL_BATTERY = 0x45, + /// Card initialization date + CISTPL_DATE = 0x44, + /// Level 2 version/product information + CISTPL_VERS_2 = 0x40, + /// Byte ordering for disk-like partitions + CISTPL_BYTEORDER = 0x43, + /// Data recording format for common memory + CISTPL_FORMAT = 0x41, + /// Data recording format for attribute memory + CISTPL_FORMAT_A = 0x47, + /// Partition geometry + CISTPL_GEOMETRY = 0x42, + /// Software interleaving + CISTPL_SWIL = 0x23, + /// Partition organization + CISTPL_ORG = 0x46, + /// Special purpose + CISTPL_SPCL = 0x90 + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum DeviceTypeCodes : byte + { + /// No device, used to designate a hole + DTYPE_NULL = 0, + /// Masked ROM + DTYPE_ROM = 1, + /// One-type-programmable ROM + DTYPE_OTPROM = 2, + /// UV-Erasable Programmable ROM + DTYPE_EPROM = 3, + /// Electronically-Erasable Programmable ROM + DTYPE_EEPROM = 4, + /// Flash memory + DTYPE_FLASH = 5, + /// Static RAM + DTYPE_SRAM = 6, + /// Dynamic RAM + DTYPE_DRAM = 7, + /// Function-specific memory address range + DTYPE_FUNCSPEC = 13, + /// Extended type follows + DTYPE_EXTEND = 14 + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum DeviceSpeedCodes : byte + { + /// No device + DSPEED_NULL = 0, + /// 250 ns + DSPEED_250NS = 1, + /// 200 ns + DSPEED_200NS = 2, + /// 150 ns + DSPEED_150NS = 3, + /// 100 ns + DSPEED_100NS = 4, + /// Extended speed follows + DSPEED_EXT = 7 + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum FunctionCodes : byte + { + MultiFunction = 0x00, Memory = 0x01, Serial = 0x02, + Parallel = 0x03, FixedDisk = 0x04, Video = 0x05, + Network = 0x06, AIMS = 0x07, SCSI = 0x08, + Security = 0x09, Instrument = 0x0A, HighSpeedSerial = 0x0B, + VendorSpecific = 0xFE + } +} \ No newline at end of file diff --git a/Aaru.Decoders/PCMCIA/Types.cs b/Aaru.Decoders/PCMCIA/Types.cs new file mode 100644 index 000000000..e30ef3e9c --- /dev/null +++ b/Aaru.Decoders/PCMCIA/Types.cs @@ -0,0 +1,381 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Types.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Contains PCMCIA tuple structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.Decoders.PCMCIA +{ + /// Basic classure of a PCMCIA tuple + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public class Tuple + { + public TupleCodes Code; + public byte[] Data; + public byte Link; + } + + /// Checksum tuple + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public class ChecksumTuple + { + /// Modulo-256 sum of region + public byte Checksum; + /// + /// + /// + public TupleCodes Code; + /// Length of region to be checksummed + public ushort Length; + /// Link to next tuple + public byte Link; + /// Offset to region to be checksummed + public short Offset; + } + + /// Indirect Access PC Card Memory + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public class IndirectTuple + { + /// + /// + /// + public TupleCodes Code; + /// Link to next tuple + public byte Link; + } + + /// Link target tuple + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public class LinkTargetTuple + { + /// + /// + /// + public TupleCodes Code; + /// Link to next tuple + public byte Link; + /// 'C''I''S' in ASCII + public byte[] Tag; + } + + /// 16-bit PC Card Long Link Tuple + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public class LongLinkTuple + { + /// Target address + public uint Address; + /// + /// or or + /// + /// + public TupleCodes Code; + /// Link to next tuple + public byte Link; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), + SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")] + public class ConfigurationAddress + { + /// Target address + public uint Address; + /// Target address space, 0 = attribute, 1 = common + public byte TargetAddressSpace; + } + + /// Multiple function link tuple + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public class MultipleFunctionLinkTuple + { + /// Link to more configuration registers + public ConfigurationAddress[] Addresses; + /// + /// + /// + public TupleCodes Code; + /// Link to next tuple + public byte Link; + /// How many functions follow + public byte NumberFunctions; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public class NoLinkTuple + { + /// + /// + /// + public TupleCodes Code; + /// Link to next tuple + public byte Link; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public class AlternateStringTuple + { + /// + /// + /// + public TupleCodes Code; + /// Link to next tuple + public byte Link; + /// + /// Array of strings. On memory they're preceded by an ISO Escape Code indicating codepage. Here they're stored as + /// Unicode, so no need for it. + /// + public string[] Strings; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), + SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")] + public class ExtendedDeviceSpeed + { + /// Speed exponent + public byte Exponent; + /// Another extended follows + public bool Extended; + /// Speed mantisa + public byte Mantissa; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public struct DeviceInfo + { + /// Device type code + public DeviceTypeCodes Type; + /// Write protected + public bool WPS; + /// Speed code + public DeviceSpeedCodes Speed; + /// Extended speeds + public ExtendedDeviceSpeed[] ExtendedSpeeds; + /// Extended types + public byte[] ExtendedTypes; + /// Size in units - 1 + public byte Units; + /// Code to define units unit + public byte SizeCode; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public class DeviceTuple + { + /// or + public TupleCodes Code; + /// Array of device information bytes + public DeviceInfo[] Infos; + /// Link to next tuple + public byte Link; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public struct OtherConditionInfo + { + /// True if another other condition info follows + public bool Extended; + /// Vcc used + public byte VccUsed; + /// Supports WAIT# signal + public bool MWAIT; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public class OtherConditionTuple + { + /// or + public TupleCodes Code; + /// Array of device information bytes + public DeviceInfo[] Infos; + /// Link to next tuple + public byte Link; + /// Array of other condition information bytes + public OtherConditionInfo[] OtherConditionInfos; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public struct DeviceGeometry + { + /// 1 << n-1 bytes, 2 = 16-bit PC Card, 3 = CardBus PC Card + public byte CardInterface; + /// + /// Erase block size in 1 << n-1 increments of wide accesses. If n == 4, and + /// == 16, erase block size = 32 * 4 = 128 bytes + /// + public byte EraseBlockSize; + /// + /// Read block size in 1 << n-1 increments of wide accesses. If n == 4, and + /// == 16, read block size = 32 * 4 = 128 bytes + /// + public byte ReadBlockSize; + /// + /// Write block size in 1 << n-1 increments of wide accesses. If n == 4, and + /// == 16, write block size = 32 * 4 = 128 bytes + /// + public byte WriteBlockSize; + /// + /// Device partitioning in granularity of 1 << n-1 erase blocks If n == 4, and erase block is 128 bytes, + /// partitions must be aligned to 32 erase block, or 4096 bytes + /// + public byte Partitions; + /// Card employs a multiple of 1 << n-1 times interleaving the entire memory arrays + public byte Interleaving; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public class DeviceGeometryTuple + { + /// or + public TupleCodes Code; + /// Array of device geometries + public DeviceGeometry[] Geometries; + /// Link to next tuple + public byte Link; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public class FunctionIdentificationTuple + { + /// + /// + /// + public TupleCodes Code; + /// Function code + public FunctionCodes Function; + /// Link to next tuple + public byte Link; + /// Device wants to be part of power-on-self-test + public bool POST; + /// Device contains boot ROM + public bool ROM; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public class ManufacturerIdentificationTuple + { + /// Card ID + public ushort CardID; + /// + /// + /// + public TupleCodes Code; + /// Link to next tuple + public byte Link; + /// Manufacturer ID + public ushort ManufacturerID; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public class Level1VersionTuple + { + /// Additional information strings + public string[] AdditionalInformation; + /// + /// + /// + public TupleCodes Code; + /// Link to next tuple + public byte Link; + /// Major version of standard compliance + public byte MajorVersion; + /// Manufacturer string + public string Manufacturer; + /// Minor version of standard compliance + public byte MinorVersion; + /// Product string + public string Product; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public class Level2VersionTuple + { + /// Address of first data byte + public ushort Address; + /// Number of copies of CIS present + public byte CISCopies; + /// + /// + /// + public TupleCodes Code; + /// Level of compliance + public byte Compliance; + /// Informational message about the card + public string Information; + /// Link to next tuple + public byte Link; + /// Vendor of software that formatted the card + public string OEM; + /// Version of this classure + public byte StructureVersion; + /// Vendor-specific byte + public byte VendorSpecific1; + /// Vendor-specific byte + public byte VendorSpecific2; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public class GeometryTuple + { + /// + /// + /// + public TupleCodes Code; + /// Cylinders + public ushort Cylinders; + /// Link to next tuple + public byte Link; + /// Sectors per track + public byte SectorsPerTrack; + /// Tracks per cylinder + public byte TracksPerCylinder; + } +} \ No newline at end of file diff --git a/Aaru.Decoders/PCMCIA/VendorCode.cs b/Aaru.Decoders/PCMCIA/VendorCode.cs new file mode 100644 index 000000000..58da760db --- /dev/null +++ b/Aaru.Decoders/PCMCIA/VendorCode.cs @@ -0,0 +1,363 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : VendorCode.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes PCMCIA vendor code. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.Decoders.PCMCIA +{ + [SuppressMessage("ReSharper", "MemberCanBeInternal")] + public static class VendorCode + { + public static string Prettify(ushort id) + { + switch(id) + { + #region JEDEC + case 0x01: return "AMD"; + case 0x02: return "AMI"; + case 0x83: return "Fairchild"; + case 0x04: return "Fujitsu"; + case 0x85: return "GTE"; + case 0x86: return "Harris"; + case 0x07: return "Hitachi"; + case 0x08: return "Inmos"; + case 0x89: return "Intel"; + case 0x8A: return "I.T.T."; + case 0x0B: return "Intersil"; + case 0x8C: return "Monolithic Memories"; + case 0x0D: return "Mostek"; + case 0x0E: return "Freescale"; + case 0x8F: return "National"; + case 0x10: return "NEC"; + case 0x91: return "RCA"; + case 0x92: return "Raytheon"; + case 0x13: return "Conexant"; + case 0x94: return "Seeq"; + case 0x15: return "NXP"; + case 0x16: return "Synertek"; + case 0x97: return "Texas Instruments"; + case 0x98: return "Toshiba"; + case 0x19: return "Xicor"; + case 0x1A: return "Zilog"; + case 0x9B: return "Eurotechnique"; + case 0x1C: return "Mitsubishi2"; + case 0x9D: return "Lucent"; + case 0x9E: return "Exel"; + case 0x1F: return "Atmel"; + case 0x20: return "SGS/Thomson"; + case 0xA1: return "Lattice Semiconductor"; + case 0xA2: return "NCR"; + case 0x23: return "Wafer Scale Integration"; + case 0xA4: return "International Business Machines"; + case 0x25: return "Tristar"; + case 0x26: return "Visic"; + case 0xA7: return "International CMOS Technology"; + case 0xA8: return "SSSI"; + case 0x29: return "Microchip Technology"; + case 0x2A: return "Ricoh"; + case 0xAB: return "VLSI"; + case 0x2C: return "Micron Technology"; + case 0xAD: return "Hynix Semiconductor"; + case 0xAE: return "OKI Semiconductor"; + case 0x2F: return "ACTEL"; + case 0xB0: return "Sharp"; + case 0x31: return "Catalyst"; + case 0x32: return "Panasonic"; + case 0xB3: return "IDT"; + case 0x34: return "Cypress"; + case 0xB5: return "Digital Equipment Corporation"; + case 0xB6: return "LSI Logic"; + case 0x37: return "Zarlink"; + case 0x38: return "UTMC"; + case 0xB9: return "Thinking Machine"; + case 0xBA: return "Thomson CSF"; + case 0x3B: return "Integrated CMOS"; + case 0xBC: return "Honeywell"; + case 0x3D: return "Tektronix"; + case 0x3E: return "Oracle Corporation"; + case 0xBF: return "Silicon Storage Technology"; + case 0x40: return "ProMos"; + case 0xC1: return "Infineon"; + case 0xC2: return "Macronix"; + case 0x43: return "Xerox"; + case 0xC4: return "Plus Logic"; + case 0x45: return "SanDisk Corporation"; + case 0x46: return "Elan Circuit Technology"; + case 0xC7: return "European Silicon"; + case 0xC8: return "Apple"; + case 0x49: return "Xilinx"; + case 0x4A: return "Compaq"; + case 0xCB: return "Protocol Engines"; + case 0x4C: return "SCI"; + case 0xCD: return "Seiko Instruments"; + case 0xCE: return "Samsung"; + case 0x4F: return "I3 Design System"; + case 0xD0: return "Klic"; + case 0x51: return "Crosspoint Solutions"; + case 0x52: return "Alliance Semiconductor"; + case 0xD3: return "Tandem"; + case 0x54: return "Hewlett-Packard"; + case 0xD5: return "Integrated Silicon Solutions"; + case 0xD6: return "Brooktree"; + case 0x57: return "New Media"; + case 0x58: return "MHS Electronic"; + case 0xD9: return "Performance Semiconductors"; + case 0xDA: return "Winbond Electronic"; + case 0x5B: return "Kawasaki Steel"; + case 0x5D: return "TECMAR"; + case 0x5E: return "Exar"; + case 0xDF: return "PCMCIA"; + case 0xE0: return "LG Semiconductor"; + case 0x61: return "Northern Telecom"; + case 0x62: return "Sanyo2"; + case 0xE3: return "Array Microsystems"; + case 0x64: return "Crystal Semiconductor"; + case 0xE5: return "Analog Devices"; + case 0xE6: return "PMC-Sierra"; + case 0x67: return "Asparix"; + case 0x68: return "Convex Computer"; + case 0xE9: return "Nimbus Technology"; + case 0x6B: return "Transwitch"; + case 0xEC: return "Micronas"; + case 0x6D: return "Canon"; + case 0x6E: return "Altera"; + case 0xEF: return "NEXCOM"; + case 0x70: return "Qualcomm"; + case 0xF1: return "Sony"; + case 0xF2: return "Cray Research"; + case 0x73: return "AMS"; + case 0xF4: return "Vitesse"; + case 0x75: return "Aster Electronics"; + case 0x76: return "Bay Networks"; + case 0xF7: return "Zentrum"; + case 0xF8: return "TRW"; + case 0x79: return "Thesys"; + case 0x7A: return "Solbourne Computer"; + case 0xFB: return "Allied-Signal"; + case 0x7C: return "Dialog Semiconductor"; + case 0xFD: return "Media Vision"; + case 0xFE: return "Numonyx Corporation"; + case 0x7F01: return "Cirrus Logic"; + case 0x7F02: return "National Instruments"; + case 0x7F04: return "Alcatel Mietec"; + case 0x7F07: return "JTAG Technologies"; + case 0x7F08: return "Loral"; + case 0x7F0B: return "Bestlink Systems"; + case 0x7F0D: return "GENNUM"; + case 0x7F0E: return "VideoLogic"; + case 0x7F10: return "Chip Express"; + case 0x7F13: return "TCSI"; + case 0x7F15: return "Hughes Aircraft"; + case 0x7F16: return "Lanstar Semiconductor"; + case 0x7F19: return "Music Semi"; + case 0x7F1A: return "Ericsson Components"; + case 0x7F1C: return "Eon Silicon Devices"; + case 0x7F1F: return "Integ.Memories Tech."; + case 0x7F20: return "Corollary Inc."; + case 0x7F23: return "EIV(Switzerland)"; + case 0x7F25: return "Zarlink(formerly Mitel)"; + case 0x7F26: return "Clearpoint"; + case 0x7F29: return "Vanguard"; + case 0x7F2A: return "Hagiwara Sys-Com"; + case 0x7F2C: return "Celestica"; + case 0x7F2F: return "Rohm Company Ltd."; + case 0x7F31: return "Libit Signal Processing"; + case 0x7F32: return "Enhanced Memories Inc."; + case 0x7F34: return "Adaptec Inc."; + case 0x7F37: return "AMIC Technology"; + case 0x7F38: return "Adobe Systems"; + case 0x7F3B: return "Newport Digital"; + case 0x7F3D: return "T Square"; + case 0x7F3E: return "Seiko Epson"; + case 0x7F40: return "Viking Components"; + case 0x7F43: return "Suwa Electronics"; + case 0x7F45: return "Micron CMS"; + case 0x7F46: return "American Computer &Digital Components Inc"; + case 0x7F49: return "CPU Design"; + case 0x7F4A: return "Price Point"; + case 0x7F4C: return "Tellabs"; + case 0x7F4F: return "Transcend Information"; + case 0x7F51: return "CKD Corporation Ltd."; + case 0x7F52: return "Capital Instruments, Inc."; + case 0x7F54: return "Linvex Technology"; + case 0x7F57: return "Dynamem, Inc."; + case 0x7F58: return "NERA ASA"; + case 0x7F5B: return "Acorn Computers"; + case 0x7F5D: return "Oak Technology, Inc."; + case 0x7F5E: return "Itec Memory"; + case 0x7F61: return "Wintec Industries"; + case 0x7F62: return "Super PC Memory"; + case 0x7F64: return "Galvantech"; + case 0x7F67: return "GateField"; + case 0x7F68: return "Integrated Memory System"; + case 0x7F6B: return "Goldenram"; + case 0x7F6D: return "Cimaron Communications"; + case 0x7F6E: return "Nippon Steel Semi.Corp."; + case 0x7F70: return "AMCC"; + case 0x7F73: return "Digital Microwave"; + case 0x7F75: return "MIMOS Semiconductor"; + case 0x7F76: return "Advanced Fibre"; + case 0x7F79: return "Acbel Polytech Inc."; + case 0x7F7A: return "Apacer Technology"; + case 0x7F7C: return "FOXCONN"; + case 0x7F83: return "ILC Data Device"; + case 0x7F85: return "Micro Linear"; + case 0x7F86: return "Univ.Of NC"; + case 0x7F89: return "Nchip"; + case 0x7F8A: return "Galileo Tech"; + case 0x7F8C: return "Graychip"; + case 0x7F8F: return "Robert Bosch"; + case 0x7F91: return "DATARAM"; + case 0x7F92: return "United Microelec Corp."; + case 0x7F94: return "Smart Modular"; + case 0x7F97: return "Qlogic"; + case 0x7F98: return "Kingston"; + case 0x7F9B: return "SpaSE"; + case 0x7F9D: return "Programmable Micro Corp"; + case 0x7F9E: return "DoD"; + case 0x7FA1: return "Dallas Semiconductor"; + case 0x7FA2: return "Omnivision"; + case 0x7FA4: return "Novatel Wireless"; + case 0x7FA7: return "Cabletron"; + case 0x7FA8: return "Silicon Technology"; + case 0x7FAB: return "Vantis"; + case 0x7FAD: return "Century"; + case 0x7FAE: return "Hal Computers"; + case 0x7FB0: return "Juniper Networks"; + case 0x7FB3: return "Tundra Semiconductor"; + case 0x7FB5: return "LightSpeed Semi."; + case 0x7FB6: return "ZSP Corp."; + case 0x7FB9: return "Dynachip"; + case 0x7FBA: return "PNY Electronics"; + case 0x7FBC: return "MMC Networks"; + case 0x7FBF: return "Broadcom"; + case 0x7FC1: return "V3 Semiconductor"; + case 0x7FC2: return "Flextronics(formerly Orbit)"; + case 0x7FC4: return "Transmeta"; + case 0x7FC7: return "Enhance 3000 Inc"; + case 0x7FC8: return "Tower Semiconductor"; + case 0x7FCB: return "Maxim Integrated Product"; + case 0x7FCD: return "Centaur Technology"; + case 0x7FCE: return "Unigen Corporation"; + case 0x7FD0: return "Memory Card Technology"; + case 0x7FD3: return "Aica Kogyo, Ltd."; + case 0x7FD5: return "MSC Vertriebs GmbH"; + case 0x7FD6: return "AKM Company, Ltd."; + case 0x7FD9: return "GSI Technology"; + case 0x7FDA: return "Dane-Elec (C Memory)"; + case 0x7FDC: return "Lara Technology"; + case 0x7FDF: return "Tanisys Technology"; + case 0x7FE0: return "Truevision"; + case 0x7FE3: return "MGV Memory"; + case 0x7FE5: return "Gadzoox Networks"; + case 0x7FE6: return "Multi Dimensional Cons."; + case 0x7FE9: return "Triscend"; + case 0x7FEA: return "XaQti"; + case 0x7FEC: return "Clear Logic"; + case 0x7FEF: return "Advantage Memory"; + case 0x7FF1: return "LeCroy"; + case 0x7FF2: return "Yamaha Corporation"; + case 0x7FF4: return "NetLogic Microsystems"; + case 0x7FF7: return "BF Goodrich Data."; + case 0x7FF8: return "Epigram"; + case 0x7FFB: return "Admor Memory"; + case 0x7FFD: return "Quadratics Superconductor"; + case 0x7FFE: return "3COM"; + #endregion JEDEC + + case 0x0100: return "Digital Equipment Corporation"; + case 0x0101: return "3Com Corporation"; + case 0x0102: return "Megahertz Corporation"; + case 0x0104: return "Socket Communications"; + case 0x0105: return "TDK Corporation"; + case 0x0108: return "Standard Microsystems Corporation"; + case 0x0109: return "Motorola Corporation"; + case 0x010b: return "National Instruments"; + case 0x0115: return "US Robotics Corporation"; + case 0x0121: return "Olicom"; + case 0x0126: return "Proxim"; + case 0x0128: return "Megahertz Corporation"; + case 0x012F: return "Adaptec Corporation"; + case 0x0137: return "Quatech"; + case 0x0138: return "Compaq"; + case 0x0140: return "Ositech"; + case 0x0143: return "D-Link"; + case 0x0149: return "Netgear"; + case 0x014D: return "Simple Technology"; + case 0x0156: return "Lucent Technologies"; + case 0x015F: return "Aironet Wireless Communications"; + case 0x016B: return "Ericsson"; + case 0x016C: return "Psion"; + case 0x0183: return "Compaq"; + case 0x0186: return "Kingston"; + case 0x0192: return "Sierra Wireless"; + case 0x0194: return "Dayna Corporation"; + case 0x01a6: return "Raytheon"; + case 0x01BF: return "Belkin"; + case 0x01EB: return "Bay Networks"; + case 0x0200: return "Farallon Communications"; + case 0x021B: return "Telecom Device"; + case 0x023D: return "Nokia Communications"; + case 0x0250: return "Samsung"; + case 0x0264: return "Anycom"; + case 0x0268: return "Alvarion Ltd."; + case 0x026C: return "Symbol"; + case 0x026F: return "BUFFALO"; + case 0x0274: return "The Linksys Group"; + case 0x0288: return "NEC Infrontia"; + case 0x028A: return "I-O DATA"; + case 0x02AA: return "Asustek Computer"; + case 0x02AC: return "Siemens"; + case 0x02D2: return "Microsoft Corporation"; + case 0x02DF: return "AmbiCom Inc"; + case 0x0a02: return "BreezeCOM"; + case 0x10CD: return "NewMedia"; + case 0x1668: return "ACTIONTEC"; + case 0x3401: return "Lasat Communications A/S"; + case 0x4E01: return "Lexar Media"; + case 0x5241: return "Archos"; + case 0x890F: return "Dual"; + case 0x8A01: return "Compex Corporation"; + case 0xC001: return "Contec"; + case 0xC00B: return "MACNICA"; + case 0xC00C: return "Roland"; + case 0xC00F: return "Corega K.K."; + case 0xC012: return "Hagiwara SYS-COM"; + case 0xC015: return "RATOC System Inc."; + case 0xC020: return "NextCom K.K."; + case 0xC250: return "EMTAC Technology Corporation"; + case 0xD601: return "Elsa"; + default: return $"Unknown vendor id 0x{id:X4}"; + } + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/DiscStructureCapabilities.cs b/Aaru.Decoders/SCSI/DiscStructureCapabilities.cs new file mode 100644 index 000000000..684b93632 --- /dev/null +++ b/Aaru.Decoders/SCSI/DiscStructureCapabilities.cs @@ -0,0 +1,79 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : DiscStructureCapabilities.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI DISC STRUCTURE structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class DiscStructureCapabilities + { + public static Capability[] Decode(byte[] response) + { + ushort len = (ushort)((response[0] << 8) + response[1]); + + if(len + 2 != response.Length) + return null; + + List caps = new List(); + + uint offset = 4; + + while(offset < response.Length) + { + var cap = new Capability + { + FormatCode = response[offset], + SDS = (response[offset + 1] & 0x80) == 0x80, + RDS = (response[offset + 1] & 0x40) == 0x40 + }; + + caps.Add(cap); + offset += 4; + } + + return caps.ToArray(); + } + + public struct Capability + { + /// READ/SEND DISC STRUCTURE format code + public byte FormatCode; + /// Supported in SEND DISC STRUCTURE + public bool SDS; + /// Supported in READ DISC STRUCTURE + public bool RDS; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/EVPD.cs b/Aaru.Decoders/SCSI/EVPD.cs new file mode 100644 index 000000000..c593a5897 --- /dev/null +++ b/Aaru.Decoders/SCSI/EVPD.cs @@ -0,0 +1,2376 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : EVPD.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI EVPDs. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using Aaru.CommonTypes.Structs.Devices.ATA; +using Aaru.CommonTypes.Structs.Devices.SCSI; +using Aaru.Helpers; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global"), + SuppressMessage("ReSharper", "UnassignedField.Global")] + public static class EVPD + { + /// Decodes VPD page 0x00: Supported VPD pages + /// A byte array containing all supported VPD pages. + /// Page 0x00. + public static byte[] DecodePage00(byte[] page) + { + if(page?[1] != 0) + return null; + + if(page.Length != page[3] + 4) + return null; + + byte[] decoded = new byte[page.Length - 4]; + + Array.Copy(page, 4, decoded, 0, page.Length - 4); + + return decoded; + } + + /// Decides VPD pages 0x01 to 0x7F: ASCII Information + /// An ASCII string with the contents of the page. + /// Page 0x01-0x7F. + public static string DecodeASCIIPage(byte[] page) + { + if(page == null) + return null; + + if(page[1] == 0 || + page[1] > 0x7F) + return null; + + if(page.Length != page[3] + 4) + return null; + + byte[] ascii = new byte[page[4]]; + + Array.Copy(page, 5, ascii, 0, page[4]); + + return StringHandlers.CToString(ascii); + } + + /// Decodes VPD page 0x80: Unit Serial Number + /// The unit serial number. + /// Page 0x80. + public static string DecodePage80(byte[] page) + { + if(page?[1] != 0x80) + return null; + + if(page.Length != page[3] + 4) + return null; + + byte[] ascii = new byte[page.Length - 4]; + + Array.Copy(page, 4, ascii, 0, page.Length - 4); + + for(int i = 0; i < ascii.Length - 1; i++) + if(ascii[i] < 0x20) + return null; + + return StringHandlers.CToString(ascii); + } + + /// Decodes VPD page 0x82: ASCII implemented operating definition + /// ASCII implemented operating definition. + /// Page 0x82. + public static string DecodePage82(byte[] page) + { + if(page?[1] != 0x82) + return null; + + if(page.Length != page[3] + 4) + return null; + + byte[] ascii = new byte[page.Length - 4]; + + Array.Copy(page, 4, ascii, 0, page.Length - 4); + + return StringHandlers.CToString(ascii); + } + + #region EVPD Page 0xB1: Manufacturer-assigned Serial Number page + public static string DecodePageB1(byte[] page) + { + if(page?[1] != 0xB1) + return null; + + if(page.Length != page[3] + 4) + return null; + + byte[] ascii = new byte[page.Length - 4]; + + Array.Copy(page, 4, ascii, 0, page.Length - 4); + + return StringHandlers.CToString(ascii).Trim(); + } + #endregion EVPD Page 0xB1: Manufacturer-assigned Serial Number page + + #region EVPD Page 0xB2: TapeAlert Supported Flags page + public static ulong DecodePageB2(byte[] page) + { + if(page?[1] != 0xB2) + return 0; + + if(page.Length != 12) + return 0; + + byte[] bitmap = new byte[8]; + + Array.Copy(page, 4, bitmap, 0, 8); + + return BitConverter.ToUInt64(bitmap.Reverse().ToArray(), 0); + } + #endregion EVPD Page 0xB2: TapeAlert Supported Flags page + + #region EVPD Page 0xB3: Automation Device Serial Number page + public static string DecodePageB3(byte[] page) + { + if(page?[1] != 0xB3) + return null; + + if(page.Length != page[3] + 4) + return null; + + byte[] ascii = new byte[page.Length - 4]; + + Array.Copy(page, 4, ascii, 0, page.Length - 4); + + return StringHandlers.CToString(ascii).Trim(); + } + #endregion EVPD Page 0xB3: Automation Device Serial Number page + + #region EVPD Page 0xB4: Data Transfer Device Element Address page + public static string DecodePageB4(byte[] page) + { + if(page?[1] != 0xB3) + return null; + + if(page.Length != page[3] + 4) + return null; + + byte[] element = new byte[page.Length - 4]; + var sb = new StringBuilder(); + + foreach(byte b in element) + sb.AppendFormat("{0:X2}", b); + + return sb.ToString(); + } + #endregion EVPD Page 0xB4: Data Transfer Device Element Address page + + #region EVPD Page 0x81: Implemented operating definition page + /// Implemented operating definition page Page code 0x81 + public struct Page_81 + { + /// The peripheral qualifier. + public PeripheralQualifiers PeripheralQualifier; + /// The type of the peripheral device. + public PeripheralDeviceTypes PeripheralDeviceType; + /// The page code. + public byte PageCode; + /// The length of the page. + public byte PageLength; + /// Current operating definition + public ScsiDefinitions Current; + /// Default operating definition + public ScsiDefinitions Default; + /// Support operating definition list + public ScsiDefinitions[] Supported; + } + + public static Page_81? DecodePage_81(byte[] pageResponse) + { + if(pageResponse?[1] != 0x81) + return null; + + if(pageResponse[3] + 4 != pageResponse.Length) + return null; + + if(pageResponse.Length < 6) + return null; + + var decoded = new Page_81 + { + PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), + PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), + PageLength = (byte)(pageResponse[3] + 4), + Current = (ScsiDefinitions)(pageResponse[4] & 0x7F), + Default = (ScsiDefinitions)(pageResponse[5] & 0x7F) + }; + + int position = 6; + List definitions = new List(); + + while(position < pageResponse.Length) + { + var definition = (ScsiDefinitions)(pageResponse[position] & 0x7F); + position++; + definitions.Add(definition); + } + + decoded.Supported = definitions.ToArray(); + + return decoded; + } + + public static string PrettifyPage_81(byte[] pageResponse) => PrettifyPage_81(DecodePage_81(pageResponse)); + + public static string DefinitionToString(ScsiDefinitions definition) + { + switch(definition) + { + case ScsiDefinitions.Current: return ""; + case ScsiDefinitions.CCS: return "CCS"; + case ScsiDefinitions.SCSI1: return "SCSI-1"; + case ScsiDefinitions.SCSI2: return "SCSI-2"; + case ScsiDefinitions.SCSI3: return "SCSI-3"; + default: return $"Unknown definition code {(byte)definition}"; + } + } + + public static string PrettifyPage_81(Page_81? modePage) + { + if(!modePage.HasValue) + return null; + + Page_81 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Implemented operating definitions:"); + + sb.AppendFormat("\tDefault operating definition: {0}", DefinitionToString(page.Current)).AppendLine(); + sb.AppendFormat("\tCurrent operating definition: {0}", DefinitionToString(page.Current)).AppendLine(); + + if(page.Supported.Length == 0) + { + sb.AppendLine("\tThere are no supported definitions"); + + return sb.ToString(); + } + + sb.AppendLine("\tSupported operating definitions:"); + + foreach(ScsiDefinitions definition in page.Supported) + sb.AppendFormat("\t\t{0}", DefinitionToString(definition)).AppendLine(); + + return sb.ToString(); + } + #endregion EVPD Page 0x81: Implemented operating definition page + + #region EVPD Page 0x83: Device identification page + public enum IdentificationAssociation : byte + { + /// Identifier field is associated with the addressed logical unit + LogicalUnit = 0, + /// Identifier field is associated with the target port + TargetPort = 1, + /// Identifier field is associated with the target device that contains the LUN + TargetDevice = 2 + } + + public enum IdentificationCodeSet : byte + { + /// Identifier is binary + Binary = 1, + /// Identifier is pure ASCII + ASCII = 2, + /// Identifier is in UTF-8 + UTF8 = 3 + } + + public enum IdentificationTypes : byte + { + /// No assignment authority was used and there is no guarantee the identifier is unique + NoAuthority = 0, + /// Concatenates vendor and product identifier from INQUIRY plus unit serial number from page 80h + Inquiry = 1, + /// Identifier is a 64-bit IEEE EUI-64, or extended + EUI = 2, + /// Identifier is compatible with 64-bit FC-PH Name_Identifier + NAA = 3, + /// Identifier to relative port in device + Relative = 4, + /// Identifier to group of target ports in device + TargetPortGroup = 5, + /// Identifier to group of target LUNs in device + LogicalUnitGroup = 6, + /// MD5 of device identification values + MD5 = 7, + /// SCSI name string + SCSI = 8, + /// Protocol specific port identifier + ProtocolSpecific = 9 + } + + public struct IdentificatonDescriptor + { + /// Protocol identifier + public ProtocolIdentifiers ProtocolIdentifier; + /// Defines how the identifier is stored + public IdentificationCodeSet CodeSet; + /// Set if protocol identifier is valid + public bool PIV; + /// Identifies which decide the identifier associates with + public IdentificationAssociation Association; + /// Defines the type of the identifier + public IdentificationTypes Type; + /// Length of the identifier + public byte Length; + /// Identifier as a string if applicable + public string ASCII; + /// Binary identifier + public byte[] Binary; + } + + /// Device identification page Page code 0x83 + public struct Page_83 + { + /// The peripheral qualifier. + public PeripheralQualifiers PeripheralQualifier; + /// The type of the peripheral device. + public PeripheralDeviceTypes PeripheralDeviceType; + /// The page code. + public byte PageCode; + /// The length of the page. + public byte PageLength; + /// The descriptors. + public IdentificatonDescriptor[] Descriptors; + } + + public static Page_83? DecodePage_83(byte[] pageResponse) + { + if(pageResponse?[1] != 0x83) + return null; + + if(pageResponse[3] + 4 != pageResponse.Length) + return null; + + if(pageResponse.Length < 6) + return null; + + var decoded = new Page_83 + { + PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), + PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), + PageLength = (byte)(pageResponse[3] + 4) + }; + + int position = 4; + List descriptors = new List(); + + while(position < pageResponse.Length) + { + var descriptor = new IdentificatonDescriptor + { + ProtocolIdentifier = (ProtocolIdentifiers)((pageResponse[position] & 0xF0) >> 4), + CodeSet = (IdentificationCodeSet)(pageResponse[position] & 0x0F), + PIV = (pageResponse[position + 1] & 0x80) == 0x80, + Association = (IdentificationAssociation)((pageResponse[position + 1] & 0x30) >> 4), + Type = (IdentificationTypes)(pageResponse[position + 1] & 0x0F), + Length = pageResponse[position + 3] + }; + + descriptor.Binary = new byte[descriptor.Length]; + + if(descriptor.Length + position + 4 >= pageResponse.Length) + descriptor.Length = (byte)(pageResponse.Length - position - 4); + + Array.Copy(pageResponse, position + 4, descriptor.Binary, 0, descriptor.Length); + + switch(descriptor.CodeSet) + { + case IdentificationCodeSet.ASCII: + descriptor.ASCII = StringHandlers.CToString(descriptor.Binary); + + break; + case IdentificationCodeSet.UTF8: + descriptor.ASCII = Encoding.UTF8.GetString(descriptor.Binary); + + break; + default: + descriptor.ASCII = ""; + + break; + } + + position += 4 + descriptor.Length; + descriptors.Add(descriptor); + } + + decoded.Descriptors = descriptors.ToArray(); + + return decoded; + } + + public static string PrettifyPage_83(byte[] pageResponse) => PrettifyPage_83(DecodePage_83(pageResponse)); + + public static string PrettifyPage_83(Page_83? modePage) + { + if(!modePage.HasValue) + return null; + + Page_83 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Device identification:"); + + if(page.Descriptors.Length == 0) + { + sb.AppendLine("\tThere are no identifiers"); + + return sb.ToString(); + } + + foreach(IdentificatonDescriptor descriptor in page.Descriptors) + { + switch(descriptor.Association) + { + case IdentificationAssociation.LogicalUnit: + sb.AppendLine("\tIdentifier belongs to addressed logical unit"); + + break; + case IdentificationAssociation.TargetPort: + sb.AppendLine("\tIdentifier belongs to target port"); + + break; + case IdentificationAssociation.TargetDevice: + sb.AppendLine("\tIdentifier belongs to target device that contains the addressed logical unit"); + + break; + default: + sb.AppendFormat("\tIndentifier has unknown association with code {0}", + (byte)descriptor.Association).AppendLine(); + + break; + } + + if(descriptor.PIV) + { + string protocol; + + switch(descriptor.ProtocolIdentifier) + { + case ProtocolIdentifiers.ADT: + protocol = "Automation/Drive Interface Transport"; + + break; + case ProtocolIdentifiers.ATA: + protocol = "AT Attachment Interface (ATA/ATAPI)"; + + break; + case ProtocolIdentifiers.FibreChannel: + protocol = "Fibre Channel"; + + break; + case ProtocolIdentifiers.Firewire: + protocol = "IEEE 1394"; + + break; + case ProtocolIdentifiers.iSCSI: + protocol = "Internet SCSI"; + + break; + case ProtocolIdentifiers.NoProtocol: + protocol = "no specific"; + + break; + case ProtocolIdentifiers.PCIe: + protocol = "PCI Express"; + + break; + case ProtocolIdentifiers.RDMAP: + protocol = "SCSI Remote Direct Memory Access"; + + break; + case ProtocolIdentifiers.SAS: + protocol = "Serial Attachment SCSI"; + + break; + case ProtocolIdentifiers.SCSI: + protocol = "Parallel SCSI"; + + break; + case ProtocolIdentifiers.SCSIe: + protocol = "SCSI over PCI Express"; + + break; + case ProtocolIdentifiers.SSA: + protocol = "SSA"; + + break; + case ProtocolIdentifiers.UAS: + protocol = "USB Attached SCSI"; + + break; + default: + protocol = $"unknown code {(byte)descriptor.ProtocolIdentifier}"; + + break; + } + + sb.AppendFormat("\tDescriptor referes to {0} protocol", protocol).AppendLine(); + } + + switch(descriptor.Type) + { + case IdentificationTypes.NoAuthority: + switch(descriptor.CodeSet) + { + case IdentificationCodeSet.ASCII: + case IdentificationCodeSet.UTF8: + sb.AppendFormat("\tVendor descriptor contains: {0}", descriptor.ASCII).AppendLine(); + + break; + case IdentificationCodeSet.Binary: + sb.AppendFormat("\tVendor descriptor contains binary data (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)).AppendLine(); + + break; + default: + sb.AppendFormat("\tVendor descriptor contains unknown kind {1} of data (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40), + (byte)descriptor.CodeSet).AppendLine(); + + break; + } + + break; + case IdentificationTypes.Inquiry: + switch(descriptor.CodeSet) + { + case IdentificationCodeSet.ASCII: + case IdentificationCodeSet.UTF8: + sb.AppendFormat("\tInquiry descriptor contains: {0}", descriptor.ASCII).AppendLine(); + + break; + case IdentificationCodeSet.Binary: + sb.AppendFormat("\tInquiry descriptor contains binary data (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)).AppendLine(); + + break; + default: + sb.AppendFormat("\tInquiry descriptor contains unknown kind {1} of data (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40), + (byte)descriptor.CodeSet).AppendLine(); + + break; + } + + break; + case IdentificationTypes.EUI: + if(descriptor.CodeSet == IdentificationCodeSet.ASCII || + descriptor.CodeSet == IdentificationCodeSet.UTF8) + sb.AppendFormat("\tIEEE EUI-64: {0}", descriptor.ASCII).AppendLine(); + else + { + sb.AppendFormat("\tIEEE EUI-64: {0:X2}", descriptor.Binary[0]); + + for(int i = 1; i < descriptor.Binary.Length; i++) + sb.AppendFormat(":{0:X2}", descriptor.Binary[i]); + + sb.AppendLine(); + } + + break; + case IdentificationTypes.NAA: + if(descriptor.CodeSet == IdentificationCodeSet.ASCII || + descriptor.CodeSet == IdentificationCodeSet.UTF8) + sb.AppendFormat("\tNAA: {0}", descriptor.ASCII).AppendLine(); + else + { + sb.AppendFormat("\tNAA: {0:X2}", descriptor.Binary[0]); + + for(int i = 1; i < descriptor.Binary.Length; i++) + sb.AppendFormat(":{0:X2}", descriptor.Binary[i]); + + sb.AppendLine(); + } + + break; + case IdentificationTypes.Relative: + if(descriptor.CodeSet == IdentificationCodeSet.ASCII || + descriptor.CodeSet == IdentificationCodeSet.UTF8) + sb.AppendFormat("\tRelative target port identifier: {0}", descriptor.ASCII).AppendLine(); + else + sb.AppendFormat("\tRelative target port identifier: {0}", + (descriptor.Binary[2] << 8) + descriptor.Binary[3]).AppendLine(); + + break; + case IdentificationTypes.TargetPortGroup: + if(descriptor.CodeSet == IdentificationCodeSet.ASCII || + descriptor.CodeSet == IdentificationCodeSet.UTF8) + sb.AppendFormat("\tTarget group identifier: {0}", descriptor.ASCII).AppendLine(); + else + sb.AppendFormat("\tTarget group identifier: {0}", + (descriptor.Binary[2] << 8) + descriptor.Binary[3]).AppendLine(); + + break; + case IdentificationTypes.LogicalUnitGroup: + if(descriptor.CodeSet == IdentificationCodeSet.ASCII || + descriptor.CodeSet == IdentificationCodeSet.UTF8) + sb.AppendFormat("\tLogical unit group identifier: {0}", descriptor.ASCII).AppendLine(); + else + sb.AppendFormat("\tLogical unit group identifier: {0}", + (descriptor.Binary[2] << 8) + descriptor.Binary[3]).AppendLine(); + + break; + case IdentificationTypes.MD5: + if(descriptor.CodeSet == IdentificationCodeSet.ASCII || + descriptor.CodeSet == IdentificationCodeSet.UTF8) + sb.AppendFormat("\tMD5 logical unit identifier: {0}", descriptor.ASCII).AppendLine(); + else + { + sb.AppendFormat("\tMD5 logical unit identifier: {0:x2}", descriptor.Binary[0]); + + for(int i = 1; i < descriptor.Binary.Length; i++) + sb.AppendFormat("{0:x2}", descriptor.Binary[i]); + + sb.AppendLine(); + } + + break; + case IdentificationTypes.SCSI: + if(descriptor.CodeSet == IdentificationCodeSet.ASCII || + descriptor.CodeSet == IdentificationCodeSet.UTF8) + sb.AppendFormat("\tSCSI name string identifier: {0}", descriptor.ASCII).AppendLine(); + else + sb.AppendFormat("\tSCSI name string identifier (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)).AppendLine(); + + break; + case IdentificationTypes.ProtocolSpecific: + { + if(descriptor.PIV) + switch(descriptor.ProtocolIdentifier) + { + case ProtocolIdentifiers.ADT: + sb. + AppendFormat("\tProtocol (Automation/Drive Interface Transport) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + + break; + case ProtocolIdentifiers.ATA: + sb. + AppendFormat("\tProtocol (ATA/ATAPI) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + + break; + case ProtocolIdentifiers.FibreChannel: + sb. + AppendFormat("\tProtocol (Fibre Channel) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + + break; + case ProtocolIdentifiers.Firewire: + sb. + AppendFormat("\tProtocol (IEEE 1394) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + + break; + case ProtocolIdentifiers.iSCSI: + sb. + AppendFormat("\tProtocol (Internet SCSI) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + + break; + case ProtocolIdentifiers.NoProtocol: + sb. + AppendFormat("\tProtocol (unknown) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + + break; + case ProtocolIdentifiers.PCIe: + sb. + AppendFormat("\tProtocol (PCI Express) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + + break; + case ProtocolIdentifiers.RDMAP: + sb. + AppendFormat("\tProtocol (SCSI Remote Direct Memory Access) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + + break; + case ProtocolIdentifiers.SAS: + sb. + AppendFormat("\tProtocol (Serial Attachment SCSI) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + + break; + case ProtocolIdentifiers.SCSI: + sb. + AppendFormat("\tProtocol (Parallel SCSI) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + + break; + case ProtocolIdentifiers.SSA: + sb. + AppendFormat("\tProtocol (SSA) specific descriptor with unknown format (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + + break; + case ProtocolIdentifiers.SCSIe: + sb.AppendFormat("\tProtocol (SCSIe) specific descriptor: Routing ID is {0}", + (descriptor.Binary[0] << 8) + descriptor.Binary[1]).AppendLine(); + + break; + case ProtocolIdentifiers.UAS: + sb. + AppendFormat("\tProtocol (UAS) specific descriptor: USB address {0} interface {1}", + descriptor.Binary[0] & 0x7F, descriptor.Binary[2]).AppendLine(); + + break; + default: + sb. + AppendFormat("\tProtocol (unknown code {0}) specific descriptor with unknown format (hex): {1}", + (byte)descriptor.ProtocolIdentifier, + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40)). + AppendLine(); + + break; + } + } + + break; + default: + switch(descriptor.CodeSet) + { + case IdentificationCodeSet.ASCII: + case IdentificationCodeSet.UTF8: + sb.AppendFormat("\tUnknown descriptor type {1} contains: {0}", descriptor.ASCII, + (byte)descriptor.Type).AppendLine(); + + break; + case IdentificationCodeSet.Binary: + sb.AppendFormat("\tUnknown descriptor type {1} contains binary data (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40), + (byte)descriptor.Type).AppendLine(); + + break; + default: + sb. + AppendFormat("Inquiry descriptor type {2} contains unknown kind {1} of data (hex): {0}", + PrintHex.ByteArrayToHexArrayString(descriptor.Binary, 40), + (byte)descriptor.CodeSet, (byte)descriptor.Type).AppendLine(); + + break; + } + + break; + } + } + + return sb.ToString(); + } + #endregion EVPD Page 0x83: Device identification page + + #region EVPD Page 0x84: Software Interface Identification page + public struct SoftwareIdentifier + { + /// EUI-48 identifier + public byte[] Identifier; + } + + /// Software Interface Identification page Page code 0x84 + public struct Page_84 + { + /// The peripheral qualifier. + public PeripheralQualifiers PeripheralQualifier; + /// The type of the peripheral device. + public PeripheralDeviceTypes PeripheralDeviceType; + /// The page code. + public byte PageCode; + /// The length of the page. + public byte PageLength; + /// The descriptors. + public SoftwareIdentifier[] Identifiers; + } + + public static Page_84? DecodePage_84(byte[] pageResponse) + { + if(pageResponse?[1] != 0x84) + return null; + + if(pageResponse[3] + 4 != pageResponse.Length) + return null; + + if(pageResponse.Length < 10) + return null; + + var decoded = new Page_84 + { + PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), + PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), + PageLength = (byte)(pageResponse[3] + 4) + }; + + int position = 4; + List identifiers = new List(); + + while(position < pageResponse.Length) + { + var identifier = new SoftwareIdentifier + { + Identifier = new byte[6] + }; + + Array.Copy(pageResponse, position, identifier.Identifier, 0, 6); + identifiers.Add(identifier); + position += 6; + } + + decoded.Identifiers = identifiers.ToArray(); + + return decoded; + } + + public static string PrettifyPage_84(byte[] pageResponse) => PrettifyPage_84(DecodePage_84(pageResponse)); + + public static string PrettifyPage_84(Page_84? modePage) + { + if(!modePage.HasValue) + return null; + + Page_84 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Software Interface Identifiers:"); + + if(page.Identifiers.Length == 0) + { + sb.AppendLine("\tThere are no identifiers"); + + return sb.ToString(); + } + + foreach(SoftwareIdentifier identifier in page.Identifiers) + { + sb.AppendFormat("\t{0:X2}", identifier.Identifier[0]); + + for(int i = 1; i < identifier.Identifier.Length; i++) + sb.AppendFormat(":{0:X2}", identifier.Identifier[i]); + + sb.AppendLine(); + } + + return sb.ToString(); + } + #endregion EVPD Page 0x84: Software Interface Identification page + + #region EVPD Page 0x85: Management Network Addresses page + public enum NetworkServiceTypes : byte + { + Unspecified = 0, StorageConf = 1, Diagnostics = 2, + Status = 3, Logging = 4, CodeDownload = 5, + CopyService = 6, Administrative = 7 + } + + public struct NetworkDescriptor + { + /// Identifies which device the identifier associates with + public IdentificationAssociation Association; + /// Defines the type of the identifier + public NetworkServiceTypes Type; + /// Length of the identifier + public ushort Length; + /// Binary identifier + public byte[] Address; + } + + /// Device identification page Page code 0x85 + public struct Page_85 + { + /// The peripheral qualifier. + public PeripheralQualifiers PeripheralQualifier; + /// The type of the peripheral device. + public PeripheralDeviceTypes PeripheralDeviceType; + /// The page code. + public byte PageCode; + /// The length of the page. + public ushort PageLength; + /// The descriptors. + public NetworkDescriptor[] Descriptors; + } + + public static Page_85? DecodePage_85(byte[] pageResponse) + { + if(pageResponse?[1] != 0x85) + return null; + + if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) + return null; + + if(pageResponse.Length < 4) + return null; + + var decoded = new Page_85 + { + PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), + PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), + PageLength = (ushort)((pageResponse[2] << 8) + pageResponse[3] + 4) + }; + + int position = 4; + List descriptors = new List(); + + while(position < pageResponse.Length) + { + var descriptor = new NetworkDescriptor + { + Association = (IdentificationAssociation)((pageResponse[position] & 0x60) >> 5), + Type = (NetworkServiceTypes)(pageResponse[position] & 0x1F), + Length = (ushort)((pageResponse[position + 2] << 8) + pageResponse[position + 3]) + }; + + descriptor.Address = new byte[descriptor.Length]; + Array.Copy(pageResponse, position + 4, descriptor.Address, 0, descriptor.Length); + + position += 4 + descriptor.Length; + descriptors.Add(descriptor); + } + + decoded.Descriptors = descriptors.ToArray(); + + return decoded; + } + + public static string PrettifyPage_85(byte[] pageResponse) => PrettifyPage_85(DecodePage_85(pageResponse)); + + public static string PrettifyPage_85(Page_85? modePage) + { + if(!modePage.HasValue) + return null; + + Page_85 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Management Network Addresses:"); + + if(page.Descriptors.Length == 0) + { + sb.AppendLine("\tThere are no addresses"); + + return sb.ToString(); + } + + foreach(NetworkDescriptor descriptor in page.Descriptors) + { + switch(descriptor.Association) + { + case IdentificationAssociation.LogicalUnit: + sb.AppendLine("\tIdentifier belongs to addressed logical unit"); + + break; + case IdentificationAssociation.TargetPort: + sb.AppendLine("\tIdentifier belongs to target port"); + + break; + case IdentificationAssociation.TargetDevice: + sb.AppendLine("\tIdentifier belongs to target device that contains the addressed logical unit"); + + break; + default: + sb.AppendFormat("\tIndentifier has unknown association with code {0}", + (byte)descriptor.Association).AppendLine(); + + break; + } + + switch(descriptor.Type) + { + case NetworkServiceTypes.CodeDownload: + sb.AppendFormat("Address for code download: {0}", StringHandlers.CToString(descriptor.Address)). + AppendLine(); + + break; + case NetworkServiceTypes.Diagnostics: + sb.AppendFormat("Address for diagnostics: {0}", StringHandlers.CToString(descriptor.Address)). + AppendLine(); + + break; + case NetworkServiceTypes.Logging: + sb.AppendFormat("Address for logging: {0}", StringHandlers.CToString(descriptor.Address)). + AppendLine(); + + break; + case NetworkServiceTypes.Status: + sb.AppendFormat("Address for status: {0}", StringHandlers.CToString(descriptor.Address)). + AppendLine(); + + break; + case NetworkServiceTypes.StorageConf: + sb.AppendFormat("Address for storage configuration service: {0}", + StringHandlers.CToString(descriptor.Address)).AppendLine(); + + break; + case NetworkServiceTypes.Unspecified: + sb.AppendFormat("Unspecified address: {0}", StringHandlers.CToString(descriptor.Address)). + AppendLine(); + + break; + case NetworkServiceTypes.CopyService: + sb.AppendFormat("Address for copy service: {0}", StringHandlers.CToString(descriptor.Address)). + AppendLine(); + + break; + case NetworkServiceTypes.Administrative: + sb.AppendFormat("Address for administrative configuration service: {0}", + StringHandlers.CToString(descriptor.Address)).AppendLine(); + + break; + default: + sb.AppendFormat("Address of unknown type {1}: {0}", + StringHandlers.CToString(descriptor.Address), (byte)descriptor.Type). + AppendLine(); + + break; + } + } + + return sb.ToString(); + } + #endregion EVPD Page 0x85: Management Network Addresses page + + #region EVPD Page 0x86: Extended INQUIRY data page + /// Device identification page Page code 0x86 + public struct Page_86 + { + /// The peripheral qualifier. + public PeripheralQualifiers PeripheralQualifier; + /// The type of the peripheral device. + public PeripheralDeviceTypes PeripheralDeviceType; + /// The page code. + public byte PageCode; + /// The length of the page. + public byte PageLength; + /// Indicates how a device server activates microcode + public byte ActivateMicrocode; + /// Protection types supported by device + public byte SPT; + /// Checks logical block guard field + public bool GRD_CHK; + /// Checks logical block application tag + public bool APP_CHK; + /// Checks logical block reference + public bool REF_CHK; + /// Supports unit attention condition sense key specific data + public bool UASK_SUP; + /// Supports grouping + public bool GROUP_SUP; + /// Supports priority + public bool PRIOR_SUP; + /// Supports head of queue + public bool HEADSUP; + /// Supports ordered + public bool ORDSUP; + /// Supports simple + public bool SIMPSUP; + /// Supports marking a block as uncorrectable + public bool WU_SUP; + /// Supports disabling correction on WRITE LONG + public bool CRD_SUP; + /// Supports a non-volatile cache + public bool NV_SUP; + /// Supports a volatile cache + public bool V_SUP; + /// Disable protection information checks + public bool NO_PI_CHK; + /// Protection information interval supported + public bool P_I_I_SUP; + /// Clears all LUNs unit attention when clearing one + public bool LUICLR; + /// Referrals support + public bool R_SUP; + /// History snapshots release effects + public bool HSSRELEF; + /// Capability based command security + public bool CBCS; + /// Indicates how it handles microcode updating with multiple nexuxes + public byte Nexus; + /// Time to complete extended self-test + public ushort ExtendedTestMinutes; + /// Power on activation support + public bool POA_SUP; + /// Hard reset actication + public bool HRA_SUP; + /// Vendor specific activation + public bool VSA_SUP; + /// Maximum length in bytes of sense data + public byte MaximumSenseLength; + } + + public static Page_86? DecodePage_86(byte[] pageResponse) + { + if(pageResponse?[1] != 0x86) + return null; + + if(pageResponse[3] + 4 != pageResponse.Length) + return null; + + if(pageResponse.Length < 64) + return null; + + return new Page_86 + { + PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), + PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), + PageLength = (byte)(pageResponse[3] + 4), + ActivateMicrocode = (byte)((pageResponse[4] & 0xC0) >> 6), + SPT = (byte)((pageResponse[4] & 0x38) >> 3), + GRD_CHK = (pageResponse[4] & 0x04) == 0x04, + APP_CHK = (pageResponse[4] & 0x02) == 0x02, + REF_CHK = (pageResponse[4] & 0x01) == 0x01, + UASK_SUP = (pageResponse[5] & 0x20) == 0x20, + GROUP_SUP = (pageResponse[5] & 0x10) == 0x10, + PRIOR_SUP = (pageResponse[5] & 0x08) == 0x08, + HEADSUP = (pageResponse[5] & 0x04) == 0x04, + ORDSUP = (pageResponse[5] & 0x02) == 0x02, + SIMPSUP = (pageResponse[5] & 0x01) == 0x01, + WU_SUP = (pageResponse[6] & 0x08) == 0x08, + CRD_SUP = (pageResponse[6] & 0x04) == 0x04, + NV_SUP = (pageResponse[6] & 0x02) == 0x02, + V_SUP = (pageResponse[6] & 0x01) == 0x01, + NO_PI_CHK = (pageResponse[7] & 0x20) == 0x20, + P_I_I_SUP = (pageResponse[7] & 0x10) == 0x10, + LUICLR = (pageResponse[7] & 0x01) == 0x01, + R_SUP = (pageResponse[8] & 0x10) == 0x10, + HSSRELEF = (pageResponse[8] & 0x02) == 0x02, + CBCS = (pageResponse[8] & 0x01) == 0x01, + Nexus = (byte)(pageResponse[9] & 0x0F), + ExtendedTestMinutes = (ushort)((pageResponse[10] << 8) + pageResponse[11]), + POA_SUP = (pageResponse[12] & 0x80) == 0x80, + HRA_SUP = (pageResponse[12] & 0x40) == 0x40, + VSA_SUP = (pageResponse[12] & 0x20) == 0x20, + MaximumSenseLength = pageResponse[13] + }; + } + + public static string PrettifyPage_86(byte[] pageResponse) => PrettifyPage_86(DecodePage_86(pageResponse)); + + public static string PrettifyPage_86(Page_86? modePage) + { + if(!modePage.HasValue) + return null; + + Page_86 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Extended INQUIRY Data:"); + + switch(page.PeripheralDeviceType) + { + case PeripheralDeviceTypes.DirectAccess: + case PeripheralDeviceTypes.SCSIZonedBlockDevice: + switch(page.SPT) + { + case 0: + sb.AppendLine("Logical unit supports type 1 protection"); + + break; + case 1: + sb.AppendLine("Logical unit supports types 1 and 2 protection"); + + break; + case 2: + sb.AppendLine("Logical unit supports type 2 protection"); + + break; + case 3: + sb.AppendLine("Logical unit supports types 1 and 3 protection"); + + break; + case 4: + sb.AppendLine("Logical unit supports type 3 protection"); + + break; + case 5: + sb.AppendLine("Logical unit supports types 2 and 3 protection"); + + break; + case 7: + sb.AppendLine("Logical unit supports types 1, 2 and 3 protection"); + + break; + default: + sb.AppendFormat("Logical unit supports unknown protection defined by code {0}", page.SPT). + AppendLine(); + + break; + } + + break; + case PeripheralDeviceTypes.SequentialAccess when page.SPT == 1: + sb.AppendLine("Logical unit supports logical block protection"); + + break; + } + + if(page.GRD_CHK) + sb.AppendLine("Device checks the logical block guard"); + + if(page.APP_CHK) + sb.AppendLine("Device checks the logical block application tag"); + + if(page.REF_CHK) + sb.AppendLine("Device checks the logical block reference tag"); + + if(page.UASK_SUP) + sb.AppendLine("Device supports unit attention condition sense key specific data"); + + if(page.GROUP_SUP) + sb.AppendLine("Device supports grouping"); + + if(page.PRIOR_SUP) + sb.AppendLine("Device supports priority"); + + if(page.HEADSUP) + sb.AppendLine("Device supports head of queue"); + + if(page.ORDSUP) + sb.AppendLine("Device supports the ORDERED task attribute"); + + if(page.SIMPSUP) + sb.AppendLine("Device supports the SIMPLE task attribute"); + + if(page.WU_SUP) + sb.AppendLine("Device supports marking a block as uncorrectable with WRITE LONG"); + + if(page.CRD_SUP) + sb.AppendLine("Device supports disabling correction with WRITE LONG"); + + if(page.NV_SUP) + sb.AppendLine("Device has a non-volatile cache"); + + if(page.V_SUP) + sb.AppendLine("Device has a volatile cache"); + + if(page.NO_PI_CHK) + sb.AppendLine("Device has disabled protection information checks"); + + if(page.P_I_I_SUP) + sb.AppendLine("Device supports protection information intervals"); + + if(page.LUICLR) + sb.AppendLine("Device clears any unit attention condition in all LUNs after reporting for any LUN"); + + if(page.R_SUP) + sb.AppendLine("Device supports referrals"); + + if(page.HSSRELEF) + sb.AppendLine("Devoce implements alternate reset handling"); + + if(page.CBCS) + sb.AppendLine("Device supports capability-based command security"); + + if(page.POA_SUP) + sb.AppendLine("Device supports power-on activation for new microcode"); + + if(page.HRA_SUP) + sb.AppendLine("Device supports hard reset activation for new microcode"); + + if(page.VSA_SUP) + sb.AppendLine("Device supports vendor specific activation for new microcode"); + + if(page.ExtendedTestMinutes > 0) + sb.AppendFormat("Extended self-test takes {0} to complete", + TimeSpan.FromMinutes(page.ExtendedTestMinutes)).AppendLine(); + + if(page.MaximumSenseLength > 0) + sb.AppendFormat("Device supports a maximum of {0} bytes for sense data", page.MaximumSenseLength). + AppendLine(); + + return sb.ToString(); + } + #endregion EVPD Page 0x86: Extended INQUIRY data page + + #region EVPD Page 0x89: ATA Information page + /// ATA Information page Page code 0x89 + public struct Page_89 + { + /// The peripheral qualifier. + public PeripheralQualifiers PeripheralQualifier; + /// The type of the peripheral device. + public PeripheralDeviceTypes PeripheralDeviceType; + /// The page code. + public byte PageCode; + /// The length of the page. + public ushort PageLength; + /// Contains the SAT vendor identification + public byte[] VendorIdentification; + /// Contains the SAT product identification + public byte[] ProductIdentification; + /// Contains the SAT revision level + public byte[] ProductRevisionLevel; + /// Contains the ATA device signature + public byte[] Signature; + /// Contains the command code used to identify the device + public byte CommandCode; + /// Contains the response to ATA IDENTIFY (PACKET) DEVICE + public byte[] IdentifyData; + } + + public static Page_89? DecodePage_89(byte[] pageResponse) + { + if(pageResponse?[1] != 0x89) + return null; + + if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) + return null; + + if(pageResponse.Length < 572) + return null; + + var decoded = new Page_89 + { + PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), + PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), + PageLength = (ushort)((pageResponse[2] << 8) + pageResponse[3] + 4), + VendorIdentification = new byte[8], + ProductIdentification = new byte[16], + ProductRevisionLevel = new byte[4], + Signature = new byte[20], + IdentifyData = new byte[512] + }; + + Array.Copy(pageResponse, 8, decoded.VendorIdentification, 0, 8); + Array.Copy(pageResponse, 16, decoded.ProductIdentification, 0, 16); + Array.Copy(pageResponse, 32, decoded.ProductRevisionLevel, 0, 4); + Array.Copy(pageResponse, 36, decoded.Signature, 0, 20); + decoded.CommandCode = pageResponse[56]; + Array.Copy(pageResponse, 60, decoded.IdentifyData, 0, 512); + + return decoded; + } + + public static string PrettifyPage_89(byte[] pageResponse) => PrettifyPage_89(DecodePage_89(pageResponse)); + + // TODO: Decode ATA signature? + public static string PrettifyPage_89(Page_89? modePage) + { + if(!modePage.HasValue) + return null; + + Page_89 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI to ATA Translation Layer Data:"); + + sb.AppendFormat("\tTranslation layer vendor: {0}", + VendorString.Prettify(StringHandlers.CToString(page.VendorIdentification).Trim())). + AppendLine(); + + sb.AppendFormat("\tTranslation layer name: {0}", + StringHandlers.CToString(page.ProductIdentification).Trim()).AppendLine(); + + sb.AppendFormat("\tTranslation layer release level: {0}", + StringHandlers.CToString(page.ProductRevisionLevel).Trim()).AppendLine(); + + switch(page.CommandCode) + { + case 0xEC: + sb.AppendLine("\tDevice responded to ATA IDENTIFY DEVICE command."); + + break; + case 0xA1: + sb.AppendLine("\tDevice responded to ATA IDENTIFY PACKET DEVICE command."); + + break; + default: + sb.AppendFormat("\tDevice responded to ATA command {0:X2}h", page.CommandCode).AppendLine(); + + break; + } + + switch(page.Signature[0]) + { + case 0x00: + sb.AppendLine("\tDevice uses Parallel ATA."); + + break; + case 0x34: + sb.AppendLine("\tDevice uses Serial ATA."); + + break; + default: + sb.AppendFormat("\tDevice uses unknown transport with code {0}", page.Signature[0]).AppendLine(); + + break; + } + + Identify.IdentifyDevice? id = Identify.Decode(page.IdentifyData); + + if(id != null) + { + sb.AppendLine("\tATA IDENTIFY information follows:"); + sb.AppendFormat("{0}", ATA.Identify.Prettify(id)).AppendLine(); + } + else + sb.AppendLine("\tCould not decode ATA IDENTIFY information"); + + return sb.ToString(); + } + #endregion EVPD Page 0x89: ATA Information page + + #region EVPD Page 0xC0 (Quantum): Firmware Build Information page + /// Firmware Build Information page Page code 0xC0 (Quantum) + public struct Page_C0_Quantum + { + /// The peripheral qualifier. + public PeripheralQualifiers PeripheralQualifier; + /// The type of the peripheral device. + public PeripheralDeviceTypes PeripheralDeviceType; + /// The page code. + public byte PageCode; + /// The length of the page. + public byte PageLength; + /// Servo firmware checksum + public ushort ServoFirmwareChecksum; + /// Servo EEPROM checksum + public ushort ServoEEPROMChecksum; + /// Read/Write firmware checksum + public uint ReadWriteFirmwareChecksum; + /// Read/Write firmware build data + public byte[] ReadWriteFirmwareBuildData; + } + + public static Page_C0_Quantum? DecodePage_C0_Quantum(byte[] pageResponse) + { + if(pageResponse?[1] != 0xC0) + return null; + + if(pageResponse[3] != 20) + return null; + + if(pageResponse.Length != 36) + return null; + + var decoded = new Page_C0_Quantum + { + PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), + PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), + PageLength = (byte)(pageResponse[3] + 4), + ServoFirmwareChecksum = (ushort)((pageResponse[4] << 8) + pageResponse[5]), + ServoEEPROMChecksum = (ushort)((pageResponse[6] << 8) + pageResponse[7]), + ReadWriteFirmwareChecksum = (uint)((pageResponse[8] << 24) + (pageResponse[9] << 16) + + (pageResponse[10] << 8) + pageResponse[11]), + ReadWriteFirmwareBuildData = new byte[24] + }; + + Array.Copy(pageResponse, 12, decoded.ReadWriteFirmwareBuildData, 0, 24); + + return decoded; + } + + public static string PrettifyPage_C0_Quantum(byte[] pageResponse) => + PrettifyPage_C0_Quantum(DecodePage_C0_Quantum(pageResponse)); + + public static string PrettifyPage_C0_Quantum(Page_C0_Quantum? modePage) + { + if(!modePage.HasValue) + return null; + + Page_C0_Quantum page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("Quantum Firmware Build Information page:"); + + sb.AppendFormat("\tServo firmware checksum: 0x{0:X4}", page.ServoFirmwareChecksum).AppendLine(); + sb.AppendFormat("\tEEPROM firmware checksum: 0x{0:X4}", page.ServoEEPROMChecksum).AppendLine(); + sb.AppendFormat("\tRead/write firmware checksum: 0x{0:X8}", page.ReadWriteFirmwareChecksum).AppendLine(); + + sb.AppendFormat("\tRead/write firmware build date: {0}", + StringHandlers.CToString(page.ReadWriteFirmwareBuildData)).AppendLine(); + + return sb.ToString(); + } + #endregion EVPD Page 0xC0 (Quantum): Firmware Build Information page + + #region EVPD Pages 0xC0, 0xC1 (Certance): Drive component revision level pages + /// Drive component revision level pages Page codes 0xC0, 0xC1 (Certance) + public struct Page_C0_C1_Certance + { + /// The peripheral qualifier. + public PeripheralQualifiers PeripheralQualifier; + /// The type of the peripheral device. + public PeripheralDeviceTypes PeripheralDeviceType; + /// The page code. + public byte PageCode; + /// The length of the page. + public byte PageLength; + public byte[] Component; + public byte[] Version; + public byte[] Date; + public byte[] Variant; + } + + public static Page_C0_C1_Certance? DecodePage_C0_C1_Certance(byte[] pageResponse) + { + if(pageResponse == null) + return null; + + if(pageResponse[1] != 0xC0 && + pageResponse[1] != 0xC1) + return null; + + if(pageResponse[3] != 92) + return null; + + if(pageResponse.Length != 96) + return null; + + var decoded = new Page_C0_C1_Certance + { + PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), + PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), + PageLength = (byte)(pageResponse[3] + 4), + Component = new byte[26], + Version = new byte[19], + Date = new byte[24], + Variant = new byte[23] + }; + + Array.Copy(pageResponse, 4, decoded.Component, 0, 26); + Array.Copy(pageResponse, 30, decoded.Version, 0, 19); + Array.Copy(pageResponse, 49, decoded.Date, 0, 24); + Array.Copy(pageResponse, 73, decoded.Variant, 0, 23); + + return decoded; + } + + public static string PrettifyPage_C0_C1_Certance(byte[] pageResponse) => + PrettifyPage_C0_C1_Certance(DecodePage_C0_C1_Certance(pageResponse)); + + public static string PrettifyPage_C0_C1_Certance(Page_C0_C1_Certance? modePage) + { + if(!modePage.HasValue) + return null; + + Page_C0_C1_Certance page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("Certance Drive Component Revision Levels page:"); + + sb.AppendFormat("\tComponent: {0}", StringHandlers.CToString(page.Component)).AppendLine(); + sb.AppendFormat("\tVersion: {0}", StringHandlers.CToString(page.Version)).AppendLine(); + sb.AppendFormat("\tDate: {0}", StringHandlers.CToString(page.Date)).AppendLine(); + sb.AppendFormat("\tVariant: {0}", StringHandlers.CToString(page.Variant)).AppendLine(); + + return sb.ToString(); + } + #endregion EVPD Pages 0xC0, 0xC1 (Certance): Drive component revision level pages + + #region EVPD Pages 0xC2, 0xC3, 0xC4, 0xC5, 0xC6 (Certance): Drive component serial number pages + /// Drive component serial number pages Page codes 0xC2, 0xC3, 0xC4, 0xC5, 0xC6 (Certance) + public struct Page_C2_C3_C4_C5_C6_Certance + { + /// The peripheral qualifier. + public PeripheralQualifiers PeripheralQualifier; + /// The type of the peripheral device. + public PeripheralDeviceTypes PeripheralDeviceType; + /// The page code. + public byte PageCode; + /// The length of the page. + public byte PageLength; + public byte[] SerialNumber; + } + + public static Page_C2_C3_C4_C5_C6_Certance? DecodePage_C2_C3_C4_C5_C6_Certance(byte[] pageResponse) + { + if(pageResponse == null) + return null; + + if(pageResponse[1] != 0xC2 && + pageResponse[1] != 0xC3 && + pageResponse[1] != 0xC4 && + pageResponse[1] != 0xC5 && + pageResponse[1] != 0xC6) + return null; + + if(pageResponse[3] != 12) + return null; + + if(pageResponse.Length != 16) + return null; + + var decoded = new Page_C2_C3_C4_C5_C6_Certance + { + PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), + PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), + PageLength = (byte)(pageResponse[3] + 4), + SerialNumber = new byte[12] + }; + + Array.Copy(pageResponse, 4, decoded.SerialNumber, 0, 12); + + return decoded; + } + + public static string PrettifyPage_C2_C3_C4_C5_C6_Certance(byte[] pageResponse) => + PrettifyPage_C2_C3_C4_C5_C6_Certance(DecodePage_C2_C3_C4_C5_C6_Certance(pageResponse)); + + public static string PrettifyPage_C2_C3_C4_C5_C6_Certance(Page_C2_C3_C4_C5_C6_Certance? modePage) + { + if(!modePage.HasValue) + return null; + + Page_C2_C3_C4_C5_C6_Certance page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("Certance Drive Component Serial Number page:"); + + switch(page.PageCode) + { + case 0xC2: + sb.AppendFormat("\tHead Assembly Serial Number: {0}", StringHandlers.CToString(page.SerialNumber)). + AppendLine(); + + break; + case 0xC3: + sb.AppendFormat("\tReel Motor 1 Serial Number: {0}", StringHandlers.CToString(page.SerialNumber)). + AppendLine(); + + break; + case 0xC4: + sb.AppendFormat("\tReel Motor 2 Serial Number: {0}", StringHandlers.CToString(page.SerialNumber)). + AppendLine(); + + break; + case 0xC5: + sb.AppendFormat("\tBoard Serial Number: {0}", StringHandlers.CToString(page.SerialNumber)). + AppendLine(); + + break; + case 0xC6: + sb.AppendFormat("\tBase Mechanical Serial Number: {0}", + StringHandlers.CToString(page.SerialNumber)).AppendLine(); + + break; + } + + return sb.ToString(); + } + #endregion EVPD Pages 0xC0, 0xC1 (Certance): Drive component revision level pages + + #region EVPD Page 0xDF (Certance): Drive status pages + /// Drive status pages Page codes 0xDF (Certance) + public struct Page_DF_Certance + { + /// The peripheral qualifier. + public PeripheralQualifiers PeripheralQualifier; + /// The type of the peripheral device. + public PeripheralDeviceTypes PeripheralDeviceType; + /// The page code. + public byte PageCode; + /// The length of the page. + public byte PageLength; + /// Command forwarding + public byte CmdFwd; + /// Alerts + public bool Alerts; + /// Removable prevention + public bool NoRemov; + /// Unit reservation + public bool UnitRsvd; + /// Needs cleaning + public bool Clean; + /// Tape threaded + public bool Threaded; + /// Commands await forwarding + public bool Lun1Cmd; + /// Autoload mode + public byte AutoloadMode; + /// Cartridge type + public byte CartridgeType; + /// Cartridge format + public byte CartridgeFormat; + /// Cartridge capacity in 10e9 bytes + public ushort CartridgeCapacity; + /// Port A transport type + public byte PortATransportType; + /// Port A SCSI ID + public byte PortASelectionID; + /// Total number of head-tape contact time + public uint OperatingHours; + /// ID that reserved the device + public ulong InitiatorID; + /// Cartridge serial number + public byte[] CartridgeSerialNumber; + } + + public static Page_DF_Certance? DecodePage_DF_Certance(byte[] pageResponse) + { + if(pageResponse?[1] != 0xDF) + return null; + + if(pageResponse[3] != 60) + return null; + + if(pageResponse.Length != 64) + return null; + + var decoded = new Page_DF_Certance + { + PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), + PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), + PageLength = (byte)(pageResponse[3] + 4), + CmdFwd = (byte)((pageResponse[5] & 0xC0) >> 5), + Alerts = (pageResponse[5] & 0x20) == 0x20, + NoRemov = (pageResponse[5] & 0x08) == 0x08, + UnitRsvd = (pageResponse[5] & 0x04) == 0x04, + Clean = (pageResponse[5] & 0x01) == 0x01, + Threaded = (pageResponse[6] & 0x10) == 0x10, + Lun1Cmd = (pageResponse[6] & 0x08) == 0x08, + AutoloadMode = (byte)(pageResponse[6] & 0x07), + CartridgeType = pageResponse[8], + CartridgeFormat = pageResponse[9], + CartridgeCapacity = (ushort)((pageResponse[10] << 8) + pageResponse[11] + 4), + PortATransportType = pageResponse[12], + PortASelectionID = pageResponse[15], + OperatingHours = (uint)((pageResponse[20] << 24) + (pageResponse[21] << 16) + (pageResponse[22] << 8) + + pageResponse[23]), + CartridgeSerialNumber = new byte[32] + }; + + byte[] buf = new byte[8]; + Array.Copy(pageResponse, 24, buf, 0, 8); + decoded.InitiatorID = BitConverter.ToUInt64(buf.Reverse().ToArray(), 0); + Array.Copy(pageResponse, 32, decoded.CartridgeSerialNumber, 0, 32); + + return decoded; + } + + public static string PrettifyPage_DF_Certance(byte[] pageResponse) => + PrettifyPage_DF_Certance(DecodePage_DF_Certance(pageResponse)); + + public static string PrettifyPage_DF_Certance(Page_DF_Certance? modePage) + { + if(!modePage.HasValue) + return null; + + Page_DF_Certance page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("Certance drive status page:"); + + switch(page.CmdFwd) + { + case 0: + sb.AppendLine("\tCommand forwarding is disabled"); + + break; + case 1: + sb.AppendLine("\tCommand forwarding is enabled"); + + break; + default: + sb.AppendFormat("\tUnknown command forwarding code {0}", page.CmdFwd).AppendLine(); + + break; + } + + if(page.Alerts) + sb.AppendLine("\tAlerts are enabled"); + + if(page.NoRemov) + sb.AppendLine("\tCartridge removable is prevented"); + + if(page.UnitRsvd) + sb.AppendFormat("\tUnit is reserved by initiator ID {0:X16}", page.InitiatorID).AppendLine(); + + if(page.Clean) + sb.AppendLine("\tDevice needs cleaning cartridge"); + + if(page.Threaded) + sb.AppendLine("\tCartridge tape is threaded"); + + if(page.Lun1Cmd) + sb.AppendLine("\tThere are commands pending to be forwarded"); + + switch(page.AutoloadMode) + { + case 0: + sb.AppendLine("\tCartridge will be loaded and threaded on insertion"); + + break; + case 1: + sb.AppendLine("\tCartridge will be loaded but not threaded on insertion"); + + break; + case 2: + sb.AppendLine("\tCartridge will not be loaded"); + + break; + default: + sb.AppendFormat("\tUnknown autoloading mode code {0}", page.AutoloadMode).AppendLine(); + + break; + } + + switch(page.PortATransportType) + { + case 0: + sb.AppendLine("\tPort A link is down"); + + break; + case 3: + sb.AppendLine("\tPort A uses Parallel SCSI Ultra-160 interface"); + + break; + default: + sb.AppendFormat("\tUnknown port A transport type code {0}", page.PortATransportType).AppendLine(); + + break; + } + + if(page.PortATransportType > 0) + sb.AppendFormat("\tDrive responds to SCSI ID {0}", page.PortASelectionID).AppendLine(); + + sb.AppendFormat("\tDrive has been operating {0}", TimeSpan.FromHours(page.OperatingHours)).AppendLine(); + + if(page.CartridgeType > 0) + { + switch(page.CartridgeFormat) + { + case 0: + sb.AppendLine("\tInserted cartridge is LTO"); + + break; + default: + sb.AppendFormat("\tUnknown cartridge format code {0}", page.CartridgeType).AppendLine(); + + break; + } + + switch(page.CartridgeType) + { + case 0: + sb.AppendLine("\tThere is no cartridge inserted"); + + break; + case 1: + sb.AppendLine("\tCleaning cartridge inserted"); + + break; + case 2: + sb.AppendLine("\tUnknown data cartridge inserted"); + + break; + case 3: + sb.AppendLine("\tFirmware cartridge inserted"); + + break; + case 4: + sb.AppendLine("\tLTO Ultrium 1 Type A cartridge inserted"); + + break; + case 5: + sb.AppendLine("\tLTO Ultrium 1 Type B cartridge inserted"); + + break; + case 6: + sb.AppendLine("\tLTO Ultrium 1 Type C cartridge inserted"); + + break; + case 7: + sb.AppendLine("\tLTO Ultrium 1 Type D cartridge inserted"); + + break; + case 8: + sb.AppendLine("\tLTO Ultrium 2 cartridge inserted"); + + break; + default: + sb.AppendFormat("\tUnknown cartridge type code {0}", page.CartridgeType).AppendLine(); + + break; + } + + sb.AppendFormat("\tCartridge has an uncompressed capabity of {0} gigabytes", page.CartridgeCapacity). + AppendLine(); + + sb.AppendFormat("\tCartridge serial number: {0}", + StringHandlers.SpacePaddedToString(page.CartridgeSerialNumber)).AppendLine(); + } + else + sb.AppendLine("\tThere is no cartridge inserted"); + + return sb.ToString(); + } + #endregion EVPD Page 0xDF (Certance): Drive status pages + + #region EVPD Page 0xC0 (IBM): Drive Component Revision Levels page + /// Drive Component Revision Levels page Page code 0xC0 (IBM) + public struct Page_C0_IBM + { + /// The peripheral qualifier. + public PeripheralQualifiers PeripheralQualifier; + /// The type of the peripheral device. + public PeripheralDeviceTypes PeripheralDeviceType; + /// The page code. + public byte PageCode; + /// The length of the page. + public byte PageLength; + public byte[] CodeName; + public byte[] Date; + } + + public static Page_C0_IBM? DecodePage_C0_IBM(byte[] pageResponse) + { + if(pageResponse?[1] != 0xC0) + return null; + + if(pageResponse[3] != 39) + return null; + + if(pageResponse.Length != 43) + return null; + + var decoded = new Page_C0_IBM + { + PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), + PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), + PageLength = (byte)(pageResponse[3] + 4), + CodeName = new byte[12], + Date = new byte[8] + }; + + Array.Copy(pageResponse, 4, decoded.CodeName, 0, 12); + Array.Copy(pageResponse, 23, decoded.Date, 0, 8); + + return decoded; + } + + public static string PrettifyPage_C0_IBM(byte[] pageResponse) => + PrettifyPage_C0_IBM(DecodePage_C0_IBM(pageResponse)); + + public static string PrettifyPage_C0_IBM(Page_C0_IBM? modePage) + { + if(!modePage.HasValue) + return null; + + Page_C0_IBM page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("IBM Drive Component Revision Levels page:"); + + sb.AppendFormat("\tCode name: {0}", StringHandlers.CToString(page.CodeName)).AppendLine(); + sb.AppendFormat("\tDate: {0}", StringHandlers.CToString(page.Date)).AppendLine(); + + return sb.ToString(); + } + #endregion EVPD Page 0xC0 (IBM): Drive Component Revision Levels page + + #region EVPD Page 0xC1 (IBM): Drive Serial Numbers page + /// Drive Serial Numbers page Page code 0xC1 (IBM) + public struct Page_C1_IBM + { + /// The peripheral qualifier. + public PeripheralQualifiers PeripheralQualifier; + /// The type of the peripheral device. + public PeripheralDeviceTypes PeripheralDeviceType; + /// The page code. + public byte PageCode; + /// The length of the page. + public byte PageLength; + public byte[] ManufacturingSerial; + public byte[] ReportedSerial; + } + + public static Page_C1_IBM? DecodePage_C1_IBM(byte[] pageResponse) + { + if(pageResponse?[1] != 0xC1) + return null; + + if(pageResponse[3] != 24) + return null; + + if(pageResponse.Length != 28) + return null; + + var decoded = new Page_C1_IBM + { + PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), + PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), + PageLength = (byte)(pageResponse[3] + 4), + ManufacturingSerial = new byte[12], + ReportedSerial = new byte[12] + }; + + Array.Copy(pageResponse, 4, decoded.ManufacturingSerial, 0, 12); + Array.Copy(pageResponse, 16, decoded.ReportedSerial, 0, 12); + + return decoded; + } + + public static string PrettifyPage_C1_IBM(byte[] pageResponse) => + PrettifyPage_C1_IBM(DecodePage_C1_IBM(pageResponse)); + + public static string PrettifyPage_C1_IBM(Page_C1_IBM? modePage) + { + if(!modePage.HasValue) + return null; + + Page_C1_IBM page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("IBM Drive Serial Numbers page:"); + + sb.AppendFormat("\tManufacturing serial number: {0}", StringHandlers.CToString(page.ManufacturingSerial)). + AppendLine(); + + sb.AppendFormat("\tReported serial number: {0}", StringHandlers.CToString(page.ReportedSerial)). + AppendLine(); + + return sb.ToString(); + } + #endregion EVPD Page 0xC1 (IBM): Drive Serial Numbers page + + #region EVPD Page 0xB0: Sequential-access device capabilities page + /// Sequential-access device capabilities page Page code 0xB0 + public struct Page_B0 + { + /// The peripheral qualifier. + public PeripheralQualifiers PeripheralQualifier; + /// The type of the peripheral device. + public PeripheralDeviceTypes PeripheralDeviceType; + /// The page code. + public byte PageCode; + /// The length of the page. + public ushort PageLength; + public bool TSMC; + public bool WORM; + } + + public static Page_B0? DecodePage_B0(byte[] pageResponse) + { + if(pageResponse?[1] != 0xB0) + return null; + + if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) + return null; + + if(pageResponse.Length < 5) + return null; + + var decoded = new Page_B0 + { + PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), + PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), + PageLength = (ushort)((pageResponse[2] << 8) + pageResponse[3] + 4), + TSMC = (pageResponse[4] & 0x02) == 0x02, + WORM = (pageResponse[4] & 0x01) == 0x01 + }; + + return decoded; + } + + public static string PrettifyPage_B0(byte[] pageResponse) => PrettifyPage_B0(DecodePage_B0(pageResponse)); + + public static string PrettifyPage_B0(Page_B0? modePage) + { + if(!modePage.HasValue) + return null; + + Page_B0 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Sequential-access Device Capabilities:"); + + if(page.WORM) + sb.AppendLine("\tDevice supports WORM media"); + + if(page.TSMC) + sb.AppendLine("\tDevice supports Tape Stream Mirroring"); + + return sb.ToString(); + } + #endregion EVPD Page 0xB0: Sequential-access device capabilities page + + #region EVPD Pages 0xC0 to 0xC5 (HP): Drive component revision level pages + /// Drive component revision level pages Page codes 0xC0 to 0xC5 (HP) + public struct Page_C0_to_C5_HP + { + /// The peripheral qualifier. + public PeripheralQualifiers PeripheralQualifier; + /// The type of the peripheral device. + public PeripheralDeviceTypes PeripheralDeviceType; + /// The page code. + public byte PageCode; + /// The length of the page. + public byte PageLength; + public byte[] Component; + public byte[] Version; + public byte[] Date; + public byte[] Variant; + public byte[] Copyright; + } + + public static Page_C0_to_C5_HP? DecodePage_C0_to_C5_HP(byte[] pageResponse) + { + if(pageResponse == null) + return null; + + if(pageResponse[1] != 0xC0 && + pageResponse[1] != 0xC1 && + pageResponse[1] != 0xC2 && + pageResponse[1] != 0xC3 && + pageResponse[1] != 0xC4 && + pageResponse[1] != 0xC5) + return null; + + if(pageResponse.Length < 4) + return null; + + var decoded = new Page_C0_to_C5_HP + { + PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), + PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), + PageLength = (byte)(pageResponse[3] + 4), + PageCode = pageResponse[1] + }; + + if(pageResponse[3] == 92 && + pageResponse.Length >= 96) + { + decoded.Component = new byte[26]; + decoded.Version = new byte[19]; + decoded.Date = new byte[24]; + decoded.Variant = new byte[23]; + + Array.Copy(pageResponse, 4, decoded.Component, 0, 26); + Array.Copy(pageResponse, 30, decoded.Version, 0, 19); + Array.Copy(pageResponse, 49, decoded.Date, 0, 24); + Array.Copy(pageResponse, 73, decoded.Variant, 0, 23); + + return decoded; + } + + if(pageResponse[4] != pageResponse[3] - 1) + return null; + + List array = new List(); + + const string fwRegExStr = + @"Firmware Rev\s+=\s+(?\d+\.\d+)\s+Build date\s+=\s+(?(\w|\d|\s*.)*)\s*$"; + + const string fwcRegExStr = @"FW_CONF\s+=\s+(?0x[0-9A-Fa-f]{8})\s*$"; + const string servoRegExStr = @"Servo\s+Rev\s+=\s+(?\d+\.\d+)\s*$"; + var fwRegEx = new Regex(fwRegExStr); + var fwcRegEx = new Regex(fwcRegExStr); + var servoRegEx = new Regex(servoRegExStr); + + for(int pos = 5; pos < pageResponse.Length; pos++) + if(pageResponse[pos] == 0x00) + { + string str = StringHandlers.CToString(array.ToArray()); + Match fwMatch = fwRegEx.Match(str); + Match fwcMatch = fwcRegEx.Match(str); + Match servoMatch = servoRegEx.Match(str); + + if(str.ToLowerInvariant().StartsWith("copyright", StringComparison.Ordinal)) + decoded.Copyright = Encoding.ASCII.GetBytes(str); + else if(fwMatch.Success) + { + decoded.Component = Encoding.ASCII.GetBytes("Firmware"); + decoded.Version = Encoding.ASCII.GetBytes(fwMatch.Groups["fw"].Value); + decoded.Date = Encoding.ASCII.GetBytes(fwMatch.Groups["date"].Value); + } + else if(fwcMatch.Success) + decoded.Variant = Encoding.ASCII.GetBytes(fwMatch.Groups["value"].Value); + else if(servoMatch.Success) + { + decoded.Component = Encoding.ASCII.GetBytes("Servo"); + decoded.Version = Encoding.ASCII.GetBytes(servoMatch.Groups["version"].Value); + } + + array = new List(); + } + else + array.Add(pageResponse[pos]); + + return decoded; + } + + public static string PrettifyPage_C0_to_C5_HP(byte[] pageResponse) => + PrettifyPage_C0_to_C5_HP(DecodePage_C0_to_C5_HP(pageResponse)); + + public static string PrettifyPage_C0_to_C5_HP(Page_C0_to_C5_HP? modePage) + { + if(!modePage.HasValue) + return null; + + Page_C0_to_C5_HP page = modePage.Value; + var sb = new StringBuilder(); + + switch(page.PageCode) + { + case 0xC0: + sb.AppendLine("HP Drive Firmware Revision Levels page:"); + + break; + case 0xC1: + sb.AppendLine("HP Drive Hardware Revision Levels page:"); + + break; + case 0xC2: + sb.AppendLine("HP Drive PCA Revision Levels page:"); + + break; + case 0xC3: + sb.AppendLine("HP Drive Mechanism Revision Levels page:"); + + break; + case 0xC4: + sb.AppendLine("HP Drive Head Assembly Revision Levels page:"); + + break; + case 0xC5: + sb.AppendLine("HP Drive ACI Revision Levels page:"); + + break; + } + + if(page.Component != null && + page.Component.Length > 0) + sb.AppendFormat("\tComponent: {0}", StringHandlers.CToString(page.Component)).AppendLine(); + + if(page.Version != null && + page.Version.Length > 0) + sb.AppendFormat("\tVersion: {0}", StringHandlers.CToString(page.Version)).AppendLine(); + + if(page.Date != null && + page.Date.Length > 0) + sb.AppendFormat("\tDate: {0}", StringHandlers.CToString(page.Date)).AppendLine(); + + if(page.Variant != null && + page.Variant.Length > 0) + sb.AppendFormat("\tVariant: {0}", StringHandlers.CToString(page.Variant)).AppendLine(); + + if(page.Copyright != null && + page.Copyright.Length > 0) + sb.AppendFormat("\tCopyright: {0}", StringHandlers.CToString(page.Copyright)).AppendLine(); + + return sb.ToString(); + } + #endregion EVPD Pages 0xC0 to 0xC5 (HP): Drive component revision level pages + + #region EVPD Page 0xC0 (Seagate): Firmware numbers page + /// Firmware numbers page Page code 0xC0 (Seagate) + public struct Page_C0_Seagate + { + /// The peripheral qualifier. + public PeripheralQualifiers PeripheralQualifier; + /// The type of the peripheral device. + public PeripheralDeviceTypes PeripheralDeviceType; + /// The page code. + public byte PageCode; + /// The length of the page. + public byte PageLength; + public byte[] ControllerFirmware; + public byte[] BootFirmware; + public byte[] ServoFirmware; + } + + public static Page_C0_Seagate? DecodePage_C0_Seagate(byte[] pageResponse) + { + if(pageResponse?[1] != 0xC0) + return null; + + if(pageResponse[3] != 12) + return null; + + if(pageResponse.Length != 16) + return null; + + var decoded = new Page_C0_Seagate + { + PeripheralQualifier = (PeripheralQualifiers)((pageResponse[0] & 0xE0) >> 5), + PeripheralDeviceType = (PeripheralDeviceTypes)(pageResponse[0] & 0x1F), + PageLength = (byte)(pageResponse[3] + 4), + PageCode = pageResponse[1], + ControllerFirmware = new byte[4], + BootFirmware = new byte[4], + ServoFirmware = new byte[4] + }; + + Array.Copy(pageResponse, 4, decoded.ControllerFirmware, 0, 4); + Array.Copy(pageResponse, 8, decoded.BootFirmware, 0, 4); + Array.Copy(pageResponse, 12, decoded.ServoFirmware, 0, 4); + + return decoded; + } + + public static string PrettifyPage_C0_Seagate(byte[] pageResponse) => + PrettifyPage_C0_Seagate(DecodePage_C0_Seagate(pageResponse)); + + public static string PrettifyPage_C0_Seagate(Page_C0_Seagate? modePage) + { + if(!modePage.HasValue) + return null; + + Page_C0_Seagate page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("Seagate Firmware Numbers page:"); + + sb.AppendFormat("\tController firmware version: {0}", StringHandlers.CToString(page.ControllerFirmware)). + AppendLine(); + + sb.AppendFormat("\tBoot firmware version: {0}", StringHandlers.CToString(page.BootFirmware)).AppendLine(); + sb.AppendFormat("\tServo firmware version: {0}", StringHandlers.CToString(page.ServoFirmware)).AppendLine(); + + return sb.ToString(); + } + #endregion EVPD Page 0xC0 (Seagate): Firmware numbers page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Inquiry.cs b/Aaru.Decoders/SCSI/Inquiry.cs new file mode 100644 index 000000000..bb82e0ffb --- /dev/null +++ b/Aaru.Decoders/SCSI/Inquiry.cs @@ -0,0 +1,2490 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Inquiry.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI INQUIRY responses. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using Aaru.CommonTypes.Structs.Devices.SCSI; +using Aaru.Helpers; + +namespace Aaru.Decoders.SCSI +{ + // Information from the following standards: + // T9/375-D revision 10l + // T10/995-D revision 10 + // T10/1236-D revision 20 + // T10/1416-D revision 23 + // T10/1731-D revision 16 + // T10/502 revision 05 + // RFC 7144 + // ECMA-111 + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class Inquiry + { + public static string Prettify(CommonTypes.Structs.Devices.SCSI.Inquiry? SCSIInquiryResponse) + { + if(SCSIInquiryResponse == null) + return null; + + CommonTypes.Structs.Devices.SCSI.Inquiry response = SCSIInquiryResponse.Value; + + var sb = new StringBuilder(); + + sb.AppendFormat("Device vendor: {0}", + VendorString.Prettify(StringHandlers.CToString(response.VendorIdentification).Trim())). + AppendLine(); + + sb.AppendFormat("Device name: {0}", StringHandlers.CToString(response.ProductIdentification).Trim()). + AppendLine(); + + sb.AppendFormat("Device release level: {0}", + StringHandlers.CToString(response.ProductRevisionLevel).Trim()).AppendLine(); + + switch((PeripheralQualifiers)response.PeripheralQualifier) + { + case PeripheralQualifiers.Supported: + sb.AppendLine("Device is connected and supported."); + + break; + case PeripheralQualifiers.Unconnected: + sb.AppendLine("Device is supported but not connected."); + + break; + case PeripheralQualifiers.Reserved: + sb.AppendLine("Reserved value set in Peripheral Qualifier field."); + + break; + case PeripheralQualifiers.Unsupported: + sb.AppendLine("Device is connected but unsupported."); + + break; + default: + sb.AppendFormat("Vendor value {0} set in Peripheral Qualifier field.", + response.PeripheralQualifier).AppendLine(); + + break; + } + + switch((PeripheralDeviceTypes)response.PeripheralDeviceType) + { + case PeripheralDeviceTypes.DirectAccess: //0x00, + sb.AppendLine("Direct-access device"); + + break; + case PeripheralDeviceTypes.SequentialAccess: //0x01, + sb.AppendLine("Sequential-access device"); + + break; + case PeripheralDeviceTypes.PrinterDevice: //0x02, + sb.AppendLine("Printer device"); + + break; + case PeripheralDeviceTypes.ProcessorDevice: //0x03, + sb.AppendLine("Processor device"); + + break; + case PeripheralDeviceTypes.WriteOnceDevice: //0x04, + sb.AppendLine("Write-once device"); + + break; + case PeripheralDeviceTypes.MultiMediaDevice: //0x05, + sb.AppendLine("CD-ROM/DVD/etc device"); + + break; + case PeripheralDeviceTypes.ScannerDevice: //0x06, + sb.AppendLine("Scanner device"); + + break; + case PeripheralDeviceTypes.OpticalDevice: //0x07, + sb.AppendLine("Optical memory device"); + + break; + case PeripheralDeviceTypes.MediumChangerDevice: //0x08, + sb.AppendLine("Medium change device"); + + break; + case PeripheralDeviceTypes.CommsDevice: //0x09, + sb.AppendLine("Communications device"); + + break; + case PeripheralDeviceTypes.PrePressDevice1: //0x0A, + sb.AppendLine("Graphics arts pre-press device (defined in ASC IT8)"); + + break; + case PeripheralDeviceTypes.PrePressDevice2: //0x0B, + sb.AppendLine("Graphics arts pre-press device (defined in ASC IT8)"); + + break; + case PeripheralDeviceTypes.ArrayControllerDevice: //0x0C, + sb.AppendLine("Array controller device"); + + break; + case PeripheralDeviceTypes.EnclosureServiceDevice: //0x0D, + sb.AppendLine("Enclosure services device"); + + break; + case PeripheralDeviceTypes.SimplifiedDevice: //0x0E, + sb.AppendLine("Simplified direct-access device"); + + break; + case PeripheralDeviceTypes.OCRWDevice: //0x0F, + sb.AppendLine("Optical card reader/writer device"); + + break; + case PeripheralDeviceTypes.BridgingExpander: //0x10, + sb.AppendLine("Bridging Expanders"); + + break; + case PeripheralDeviceTypes.ObjectDevice: //0x11, + sb.AppendLine("Object-based Storage Device"); + + break; + case PeripheralDeviceTypes.ADCDevice: //0x12, + sb.AppendLine("Automation/Drive Interface"); + + break; + case PeripheralDeviceTypes.SCSISecurityManagerDevice: //0x13, + sb.AppendLine("Security Manager Device"); + + break; + case PeripheralDeviceTypes.SCSIZonedBlockDevice: //0x14 + sb.AppendLine("Host managed zoned block device"); + + break; + case PeripheralDeviceTypes.WellKnownDevice: //0x1E, + sb.AppendLine("Well known logical unit"); + + break; + case PeripheralDeviceTypes.UnknownDevice: //0x1F + sb.AppendLine("Unknown or no device type"); + + break; + default: + sb.AppendFormat("Unknown device type field value 0x{0:X2}", response.PeripheralDeviceType). + AppendLine(); + + break; + } + + switch((ANSIVersions)response.ANSIVersion) + { + case ANSIVersions.ANSINoVersion: + sb.AppendLine("Device does not claim to comply with any SCSI ANSI standard"); + + break; + case ANSIVersions.ANSI1986Version: + sb.AppendLine("Device claims to comply with ANSI X3.131:1986 (SCSI-1)"); + + break; + case ANSIVersions.ANSI1994Version: + sb.AppendLine("Device claims to comply with ANSI X3.131:1994 (SCSI-2)"); + + break; + case ANSIVersions.ANSI1997Version: + sb.AppendLine("Device claims to comply with ANSI X3.301:1997 (SPC-1)"); + + break; + case ANSIVersions.ANSI2001Version: + sb.AppendLine("Device claims to comply with ANSI X3.351:2001 (SPC-2)"); + + break; + case ANSIVersions.ANSI2005Version: + sb.AppendLine("Device claims to comply with ANSI X3.408:2005 (SPC-3)"); + + break; + case ANSIVersions.ANSI2008Version: + sb.AppendLine("Device claims to comply with ANSI X3.408:2005 (SPC-4)"); + + break; + default: + sb.AppendFormat("Device claims to comply with unknown SCSI ANSI standard value 0x{0:X2})", + response.ANSIVersion).AppendLine(); + + break; + } + + switch((ECMAVersions)response.ECMAVersion) + { + case ECMAVersions.ECMANoVersion: + sb.AppendLine("Device does not claim to comply with any SCSI ECMA standard"); + + break; + case ECMAVersions.ECMA111: + sb.AppendLine("Device claims to comply ECMA-111: Small Computer System Interface SCSI"); + + break; + default: + sb.AppendFormat("Device claims to comply with unknown SCSI ECMA standard value 0x{0:X2})", + response.ECMAVersion).AppendLine(); + + break; + } + + switch((ISOVersions)response.ISOVersion) + { + case ISOVersions.ISONoVersion: + sb.AppendLine("Device does not claim to comply with any SCSI ISO/IEC standard"); + + break; + case ISOVersions.ISO1995Version: + sb.AppendLine("Device claims to comply with ISO/IEC 9316:1995"); + + break; + default: + sb.AppendFormat("Device claims to comply with unknown SCSI ISO/IEC standard value 0x{0:X2})", + response.ISOVersion).AppendLine(); + + break; + } + + if(response.RMB) + sb.AppendLine("Device is removable"); + + if(response.AERC) + sb.AppendLine("Device supports Asynchronous Event Reporting Capability"); + + if(response.TrmTsk) + sb.AppendLine("Device supports TERMINATE TASK command"); + + if(response.NormACA) + sb.AppendLine("Device supports setting Normal ACA"); + + if(response.HiSup) + sb.AppendLine("Device supports LUN hierarchical addressing"); + + if(response.SCCS) + sb.AppendLine("Device contains an embedded storage array controller"); + + if(response.ACC) + sb.AppendLine("Device contains an Access Control Coordinator"); + + if(response.ThreePC) + sb.AppendLine("Device supports third-party copy commands"); + + if(response.Protect) + sb.AppendLine("Device supports protection information"); + + if(response.BQue) + sb.AppendLine("Device supports basic queueing"); + + if(response.EncServ) + sb.AppendLine("Device contains an embedded enclosure services component"); + + if(response.MultiP) + sb.AppendLine("Multi-port device"); + + if(response.MChngr) + sb.AppendLine("Device contains or is attached to a medium changer"); + + if(response.ACKREQQ) + sb.AppendLine("Device supports request and acknowledge handshakes"); + + if(response.Addr32) + sb.AppendLine("Device supports 32-bit wide SCSI addresses"); + + if(response.Addr16) + sb.AppendLine("Device supports 16-bit wide SCSI addresses"); + + if(response.RelAddr) + sb.AppendLine("Device supports relative addressing"); + + if(response.WBus32) + sb.AppendLine("Device supports 32-bit wide data transfers"); + + if(response.WBus16) + sb.AppendLine("Device supports 16-bit wide data transfers"); + + if(response.Sync) + sb.AppendLine("Device supports synchronous data transfer"); + + if(response.Linked) + sb.AppendLine("Device supports linked commands"); + + if(response.TranDis) + sb.AppendLine("Device supports CONTINUE TASK and TARGET TRANSFER DISABLE commands"); + + if(response.QAS) + sb.AppendLine("Device supports Quick Arbitration and Selection"); + + if(response.CmdQue) + sb.AppendLine("Device supports TCQ queue"); + + if(response.IUS) + sb.AppendLine("Device supports information unit transfers"); + + if(response.SftRe) + sb.AppendLine("Device implements RESET as a soft reset"); + #if DEBUG + if(response.VS1) + sb.AppendLine("Vendor specific bit 5 on byte 6 of INQUIRY response is set"); + #endif + + switch((TGPSValues)response.TPGS) + { + case TGPSValues.NotSupported: + sb.AppendLine("Device does not support asymmetrical access"); + + break; + case TGPSValues.OnlyImplicit: + sb.AppendLine("Device only supports implicit asymmetrical access"); + + break; + case TGPSValues.OnlyExplicit: + sb.AppendLine("Device only supports explicit asymmetrical access"); + + break; + case TGPSValues.Both: + sb.AppendLine("Device supports implicit and explicit asymmetrical access"); + + break; + default: + sb.AppendFormat("Unknown value in TPGS field 0x{0:X2}", response.TPGS).AppendLine(); + + break; + } + + switch((SPIClocking)response.Clocking) + { + case SPIClocking.ST: + sb.AppendLine("Device supports only ST clocking"); + + break; + case SPIClocking.DT: + sb.AppendLine("Device supports only DT clocking"); + + break; + case SPIClocking.Reserved: + sb.AppendLine("Reserved value 0x02 found in SPI clocking field"); + + break; + case SPIClocking.STandDT: + sb.AppendLine("Device supports ST and DT clocking"); + + break; + default: + sb.AppendFormat("Unknown value in SPI clocking field 0x{0:X2}", response.Clocking).AppendLine(); + + break; + } + + if(response.VersionDescriptors != null) + foreach(ushort VersionDescriptor in response.VersionDescriptors) + switch(VersionDescriptor) + { + case 0xFFFF: + case 0x0000: break; + case 0x0020: + sb.AppendLine("Device complies with SAM (no version claimed)"); + + break; + case 0x003B: + sb.AppendLine("Device complies with SAM T10/0994-D revision 18"); + + break; + case 0x003C: + sb.AppendLine("Device complies with SAM ANSI INCITS 270-1996"); + + break; + case 0x0040: + sb.AppendLine("Device complies with SAM-2 (no version claimed)"); + + break; + case 0x0054: + sb.AppendLine("Device complies with SAM-2 T10/1157-D revision 23"); + + break; + case 0x0055: + sb.AppendLine("Device complies with SAM-2 T10/1157-D revision 24"); + + break; + case 0x005C: + sb.AppendLine("Device complies with SAM-2 ANSI INCITS 366-2003"); + + break; + case 0x005E: + sb.AppendLine("Device complies with SAM-2 ISO/IEC 14776-412"); + + break; + case 0x0060: + sb.AppendLine("Device complies with SAM-3 (no version claimed)"); + + break; + case 0x0062: + sb.AppendLine("Device complies with SAM-3 T10/1561-D revision 7"); + + break; + case 0x0075: + sb.AppendLine("Device complies with SAM-3 T10/1561-D revision 13"); + + break; + case 0x0076: + sb.AppendLine("Device complies with SAM-3 T10/1561-D revision 14"); + + break; + case 0x0077: + sb.AppendLine("Device complies with SAM-3 ANSI INCITS 402-2005"); + + break; + case 0x0080: + sb.AppendLine("Device complies with SAM-4 (no version claimed)"); + + break; + case 0x0087: + sb.AppendLine("Device complies with SAM-4 T10/1683-D revision 13"); + + break; + case 0x008B: + sb.AppendLine("Device complies with SAM-4 T10/1683-D revision 14"); + + break; + case 0x0090: + sb.AppendLine("Device complies with SAM-4 ANSI INCITS 447-2008"); + + break; + case 0x0092: + sb.AppendLine("Device complies with SAM-4 ISO/IEC 14776-414"); + + break; + case 0x00A0: + sb.AppendLine("Device complies with SAM-5 (no version claimed)"); + + break; + case 0x00A2: + sb.AppendLine("Device complies with SAM-5 T10/2104-D revision 4"); + + break; + case 0x00A4: + sb.AppendLine("Device complies with SAM-5 T10/2104-D revision 20"); + + break; + case 0x00A6: + sb.AppendLine("Device complies with SAM-5 T10/2104-D revision 21"); + + break; + case 0x00C0: + sb.AppendLine("Device complies with SAM-6 (no version claimed)"); + + break; + case 0x0120: + sb.AppendLine("Device complies with SPC (no version claimed)"); + + break; + case 0x013B: + sb.AppendLine("Device complies with SPC T10/0995-D revision 11a"); + + break; + case 0x013C: + sb.AppendLine("Device complies with SPC ANSI INCITS 301-1997"); + + break; + case 0x0140: + sb.AppendLine("Device complies with MMC (no version claimed)"); + + break; + case 0x015B: + sb.AppendLine("Device complies with MMC T10/1048-D revision 10a"); + + break; + case 0x015C: + sb.AppendLine("Device complies with MMC ANSI INCITS 304-1997"); + + break; + case 0x0160: + sb.AppendLine("Device complies with SCC (no version claimed)"); + + break; + case 0x017B: + sb.AppendLine("Device complies with SCC T10/1047-D revision 06c"); + + break; + case 0x017C: + sb.AppendLine("Device complies with SCC ANSI INCITS 276-1997"); + + break; + case 0x0180: + sb.AppendLine("Device complies with SBC (no version claimed)"); + + break; + case 0x019B: + sb.AppendLine("Device complies with SBC T10/0996-D revision 08c"); + + break; + case 0x019C: + sb.AppendLine("Device complies with SBC ANSI INCITS 306-1998"); + + break; + case 0x01A0: + sb.AppendLine("Device complies with SMC (no version claimed)"); + + break; + case 0x01BB: + sb.AppendLine("Device complies with SMC T10/0999-D revision 10a"); + + break; + case 0x01BC: + sb.AppendLine("Device complies with SMC ANSI INCITS 314-1998"); + + break; + case 0x01BE: + sb.AppendLine("Device complies with SMC ISO/IEC 14776-351"); + + break; + case 0x01C0: + sb.AppendLine("Device complies with SES (no version claimed)"); + + break; + case 0x01DB: + sb.AppendLine("Device complies with SES T10/1212-D revision 08b"); + + break; + case 0x01DC: + sb.AppendLine("Device complies with SES ANSI INCITS 305-1998"); + + break; + case 0x01DD: + sb.AppendLine("Device complies with SES T10/1212 revision 08b w/ Amendment ANSI INCITS.305/AM1-2000"); + + break; + case 0x01DE: + sb.AppendLine("Device complies with SES ANSI INCITS 305-1998 w/ Amendment ANSI INCITS.305/AM1-2000"); + + break; + case 0x01E0: + sb.AppendLine("Device complies with SCC-2 (no version claimed)"); + + break; + case 0x01FB: + sb.AppendLine("Device complies with SCC-2 T10/1125-D revision 04"); + + break; + case 0x01FC: + sb.AppendLine("Device complies with SCC-2 ANSI INCITS 318-1998"); + + break; + case 0x0200: + sb.AppendLine("Device complies with SSC (no version claimed)"); + + break; + case 0x0201: + sb.AppendLine("Device complies with SSC T10/0997-D revision 17"); + + break; + case 0x0207: + sb.AppendLine("Device complies with SSC T10/0997-D revision 22"); + + break; + case 0x021C: + sb.AppendLine("Device complies with SSC ANSI INCITS 335-2000"); + + break; + case 0x0220: + sb.AppendLine("Device complies with RBC (no version claimed)"); + + break; + case 0x0238: + sb.AppendLine("Device complies with RBC T10/1240-D revision 10a"); + + break; + case 0x023C: + sb.AppendLine("Device complies with RBC ANSI INCITS 330-2000"); + + break; + case 0x0240: + sb.AppendLine("Device complies with MMC-2 (no version claimed)"); + + break; + case 0x0255: + sb.AppendLine("Device complies with MMC-2 T10/1228-D revision 11"); + + break; + case 0x025B: + sb.AppendLine("Device complies with MMC-2 T10/1228-D revision 11a"); + + break; + case 0x025C: + sb.AppendLine("Device complies with MMC-2 ANSI INCITS 333-2000"); + + break; + case 0x0260: + sb.AppendLine("Device complies with SPC-2 (no version claimed)"); + + break; + case 0x0267: + sb.AppendLine("Device complies with SPC-2 T10/1236-D revision 12"); + + break; + case 0x0269: + sb.AppendLine("Device complies with SPC-2 T10/1236-D revision 18"); + + break; + case 0x0275: + sb.AppendLine("Device complies with SPC-2 T10/1236-D revision 19"); + + break; + case 0x0276: + sb.AppendLine("Device complies with SPC-2 T10/1236-D revision 20"); + + break; + case 0x0277: + sb.AppendLine("Device complies with SPC-2 ANSI INCITS 351-2001"); + + break; + case 0x0278: + sb.AppendLine("Device complies with SPC-2 ISO/IEC 14776-452"); + + break; + case 0x0280: + sb.AppendLine("Device complies with OCRW (no version claimed)"); + + break; + case 0x029E: + sb.AppendLine("Device complies with OCRW ISO/IEC 14776-381"); + + break; + case 0x02A0: + sb.AppendLine("Device complies with MMC-3 (no version claimed)"); + + break; + case 0x02B5: + sb.AppendLine("Device complies with MMC-3 T10/1363-D revision 9"); + + break; + case 0x02B6: + sb.AppendLine("Device complies with MMC-3 T10/1363-D revision 10g"); + + break; + case 0x02B8: + sb.AppendLine("Device complies with MMC-3 ANSI INCITS 360-2002"); + + break; + case 0x02E0: + sb.AppendLine("Device complies with SMC-2 (no version claimed)"); + + break; + case 0x02F5: + sb.AppendLine("Device complies with SMC-2 T10/1383-D revision 5"); + + break; + case 0x02FC: + sb.AppendLine("Device complies with SMC-2 T10/1383-D revision 6"); + + break; + case 0x02FD: + sb.AppendLine("Device complies with SMC-2 T10/1383-D revision 7"); + + break; + case 0x02FE: + sb.AppendLine("Device complies with SMC-2 ANSI INCITS 382-2004"); + + break; + case 0x0300: + sb.AppendLine("Device complies with SPC-3 (no version claimed)"); + + break; + case 0x0301: + sb.AppendLine("Device complies with SPC-3 T10/1416-D revision 7"); + + break; + case 0x0307: + sb.AppendLine("Device complies with SPC-3 T10/1416-D revision 21"); + + break; + case 0x030F: + sb.AppendLine("Device complies with SPC-3 T10/1416-D revision 22"); + + break; + case 0x0312: + sb.AppendLine("Device complies with SPC-3 T10/1416-D revision 23"); + + break; + case 0x0314: + sb.AppendLine("Device complies with SPC-3 ANSI INCITS 408-2005"); + + break; + case 0x0316: + sb.AppendLine("Device complies with SPC-3 ISO/IEC 14776-453"); + + break; + case 0x0320: + sb.AppendLine("Device complies with SBC-2 (no version claimed)"); + + break; + case 0x0322: + sb.AppendLine("Device complies with SBC-2 T10/1417-D revision 5a"); + + break; + case 0x0324: + sb.AppendLine("Device complies with SBC-2 T10/1417-D revision 15"); + + break; + case 0x033B: + sb.AppendLine("Device complies with SBC-2 T10/1417-D revision 16"); + + break; + case 0x033D: + sb.AppendLine("Device complies with SBC-2 ANSI INCITS 405-2005"); + + break; + case 0x033E: + sb.AppendLine("Device complies with SBC-2 ISO/IEC 14776-322"); + + break; + case 0x0340: + sb.AppendLine("Device complies with OSD (no version claimed)"); + + break; + case 0x0341: + sb.AppendLine("Device complies with OSD T10/1355-D revision 0"); + + break; + case 0x0342: + sb.AppendLine("Device complies with OSD T10/1355-D revision 7a"); + + break; + case 0x0343: + sb.AppendLine("Device complies with OSD T10/1355-D revision 8"); + + break; + case 0x0344: + sb.AppendLine("Device complies with OSD T10/1355-D revision 9"); + + break; + case 0x0355: + sb.AppendLine("Device complies with OSD T10/1355-D revision 10"); + + break; + case 0x0356: + sb.AppendLine("Device complies with OSD ANSI INCITS 400-2004"); + + break; + case 0x0360: + sb.AppendLine("Device complies with SSC-2 (no version claimed)"); + + break; + case 0x0374: + sb.AppendLine("Device complies with SSC-2 T10/1434-D revision 7"); + + break; + case 0x0375: + sb.AppendLine("Device complies with SSC-2 T10/1434-D revision 9"); + + break; + case 0x037D: + sb.AppendLine("Device complies with SSC-2 ANSI INCITS 380-2003"); + + break; + case 0x0380: + sb.AppendLine("Device complies with BCC (no version claimed)"); + + break; + case 0x03A0: + sb.AppendLine("Device complies with MMC-4 (no version claimed)"); + + break; + case 0x03B0: + sb.AppendLine("Device complies with MMC-4 T10/1545-D revision 5"); + + break; + case 0x03B1: + sb.AppendLine("Device complies with MMC-4 T10/1545-D revision 5a"); + + break; + case 0x03BD: + sb.AppendLine("Device complies with MMC-4 T10/1545-D revision 3"); + + break; + case 0x03BE: + sb.AppendLine("Device complies with MMC-4 T10/1545-D revision 3d"); + + break; + case 0x03BF: + sb.AppendLine("Device complies with MMC-4 ANSI INCITS 401-2005"); + + break; + case 0x03C0: + sb.AppendLine("Device complies with ADC (no version claimed)"); + + break; + case 0x03D5: + sb.AppendLine("Device complies with ADC T10/1558-D revision 6"); + + break; + case 0x03D6: + sb.AppendLine("Device complies with ADC T10/1558-D revision 7"); + + break; + case 0x03D7: + sb.AppendLine("Device complies with ADC ANSI INCITS 403-2005"); + + break; + case 0x03E0: + sb.AppendLine("Device complies with SES-2 (no version claimed)"); + + break; + case 0x03E1: + sb.AppendLine("Device complies with SES-2 T10/1559-D revision 16"); + + break; + case 0x03E7: + sb.AppendLine("Device complies with SES-2 T10/1559-D revision 19"); + + break; + case 0x03EB: + sb.AppendLine("Device complies with SES-2 T10/1559-D revision 20"); + + break; + case 0x03F0: + sb.AppendLine("Device complies with SES-2 ANSI INCITS 448-2008"); + + break; + case 0x03F2: + sb.AppendLine("Device complies with SES-2 ISO/IEC 14776-372"); + + break; + case 0x0400: + sb.AppendLine("Device complies with SSC-3 (no version claimed)"); + + break; + case 0x0403: + sb.AppendLine("Device complies with SSC-3 T10/1611-D revision 04a"); + + break; + case 0x0407: + sb.AppendLine("Device complies with SSC-3 T10/1611-D revision 05"); + + break; + case 0x0409: + sb.AppendLine("Device complies with SSC-3 ANSI INCITS 467-2011"); + + break; + case 0x040B: + sb.AppendLine("Device complies with SSC-3 ISO/IEC 14776-333:2013"); + + break; + case 0x0420: + sb.AppendLine("Device complies with MMC-5 (no version claimed)"); + + break; + case 0x042F: + sb.AppendLine("Device complies with MMC-5 T10/1675-D revision 03"); + + break; + case 0x0431: + sb.AppendLine("Device complies with MMC-5 T10/1675-D revision 03b"); + + break; + case 0x0432: + sb.AppendLine("Device complies with MMC-5 T10/1675-D revision 04"); + + break; + case 0x0434: + sb.AppendLine("Device complies with MMC-5 ANSI INCITS 430-2007"); + + break; + case 0x0440: + sb.AppendLine("Device complies with OSD-2 (no version claimed)"); + + break; + case 0x0444: + sb.AppendLine("Device complies with OSD-2 T10/1729-D revision 4"); + + break; + case 0x0446: + sb.AppendLine("Device complies with OSD-2 T10/1729-D revision 5"); + + break; + case 0x0448: + sb.AppendLine("Device complies with OSD-2 ANSI INCITS 458-2011"); + + break; + case 0x0460: + sb.AppendLine("Device complies with SPC-4 (no version claimed)"); + + break; + case 0x0461: + sb.AppendLine("Device complies with SPC-4 T10/BSR INCITS 513 revision 16"); + + break; + case 0x0462: + sb.AppendLine("Device complies with SPC-4 T10/BSR INCITS 513 revision 18"); + + break; + case 0x0463: + sb.AppendLine("Device complies with SPC-4 T10/BSR INCITS 513 revision 23"); + + break; + case 0x0466: + sb.AppendLine("Device complies with SPC-4 T10/BSR INCITS 513 revision 36"); + + break; + case 0x0468: + sb.AppendLine("Device complies with SPC-4 T10/BSR INCITS 513 revision 37"); + + break; + case 0x0469: + sb.AppendLine("Device complies with SPC-4 T10/BSR INCITS 513 revision 37a"); + + break; + case 0x046C: + sb.AppendLine("Device complies with SPC-4 ANSI INCITS 513-2015"); + + break; + case 0x0480: + sb.AppendLine("Device complies with SMC-3 (no version claimed)"); + + break; + case 0x0482: + sb.AppendLine("Device complies with SMC-3 T10/1730-D revision 15"); + + break; + case 0x0484: + sb.AppendLine("Device complies with SMC-3 T10/1730-D revision 16"); + + break; + case 0x0486: + sb.AppendLine("Device complies with SMC-3 ANSI INCITS 484-2012"); + + break; + case 0x04A0: + sb.AppendLine("Device complies with ADC-2 (no version claimed)"); + + break; + case 0x04A7: + sb.AppendLine("Device complies with ADC-2 T10/1741-D revision 7"); + + break; + case 0x04AA: + sb.AppendLine("Device complies with ADC-2 T10/1741-D revision 8"); + + break; + case 0x04AC: + sb.AppendLine("Device complies with ADC-2 ANSI INCITS 441-2008"); + + break; + case 0x04C0: + sb.AppendLine("Device complies with SBC-3 (no version claimed)"); + + break; + case 0x04C3: + sb.AppendLine("Device complies with SBC-3 T10/BSR INCITS 514 revision 35"); + + break; + case 0x04C5: + sb.AppendLine("Device complies with SBC-3 T10/BSR INCITS 514 revision 36"); + + break; + case 0x04C8: + sb.AppendLine("Device complies with SBC-3 ANSI INCITS 514-2014"); + + break; + case 0x04E0: + sb.AppendLine("Device complies with MMC-6 (no version claimed)"); + + break; + case 0x04E3: + sb.AppendLine("Device complies with MMC-6 T10/1836-D revision 02b"); + + break; + case 0x04E5: + sb.AppendLine("Device complies with MMC-6 T10/1836-D revision 02g"); + + break; + case 0x04E6: + sb.AppendLine("Device complies with MMC-6 ANSI INCITS 468-2010"); + + break; + case 0x04E7: + sb.AppendLine("Device complies with MMC-6 ANSI INCITS 468-2010 + MMC-6/AM1 ANSI INCITS 468-2010/AM 1"); + + break; + case 0x0500: + sb.AppendLine("Device complies with ADC-3 (no version claimed)"); + + break; + case 0x0502: + sb.AppendLine("Device complies with ADC-3 T10/1895-D revision 04"); + + break; + case 0x0504: + sb.AppendLine("Device complies with ADC-3 T10/1895-D revision 05"); + + break; + case 0x0506: + sb.AppendLine("Device complies with ADC-3 T10/1895-D revision 05a"); + + break; + case 0x050A: + sb.AppendLine("Device complies with ADC-3 ANSI INCITS 497-2012"); + + break; + case 0x0520: + sb.AppendLine("Device complies with SSC-4 (no version claimed)"); + + break; + case 0x0523: + sb.AppendLine("Device complies with SSC-4 T10/BSR INCITS 516 revision 2"); + + break; + case 0x0525: + sb.AppendLine("Device complies with SSC-4 T10/BSR INCITS 516 revision 3"); + + break; + case 0x0527: + sb.AppendLine("Device complies with SSC-4 ANSI INCITS 516-2013"); + + break; + case 0x0560: + sb.AppendLine("Device complies with OSD-3 (no version claimed)"); + + break; + case 0x0580: + sb.AppendLine("Device complies with SES-3 (no version claimed)"); + + break; + case 0x05A0: + sb.AppendLine("Device complies with SSC-5 (no version claimed)"); + + break; + case 0x05C0: + sb.AppendLine("Device complies with SPC-5 (no version claimed)"); + + break; + case 0x05E0: + sb.AppendLine("Device complies with SFSC (no version claimed)"); + + break; + case 0x05E3: + sb.AppendLine("Device complies with SFSC BSR INCITS 501 revision 01"); + + break; + case 0x0600: + sb.AppendLine("Device complies with SBC-4 (no version claimed)"); + + break; + case 0x0620: + sb.AppendLine("Device complies with ZBC (no version claimed)"); + + break; + case 0x0622: + sb.AppendLine("Device complies with ZBC BSR INCITS 536 revision 02"); + + break; + case 0x0640: + sb.AppendLine("Device complies with ADC-4 (no version claimed)"); + + break; + case 0x0820: + sb.AppendLine("Device complies with SSA-TL2 (no version claimed)"); + + break; + case 0x083B: + sb.AppendLine("Device complies with SSA-TL2 T10.1/1147-D revision 05b"); + + break; + case 0x083C: + sb.AppendLine("Device complies with SSA-TL2 ANSI INCITS 308-1998"); + + break; + case 0x0840: + sb.AppendLine("Device complies with SSA-TL1 (no version claimed)"); + + break; + case 0x085B: + sb.AppendLine("Device complies with SSA-TL1 T10.1/0989-D revision 10b"); + + break; + case 0x085C: + sb.AppendLine("Device complies with SSA-TL1 ANSI INCITS 295-1996"); + + break; + case 0x0860: + sb.AppendLine("Device complies with SSA-S3P (no version claimed)"); + + break; + case 0x087B: + sb.AppendLine("Device complies with SSA-S3P T10.1/1051-D revision 05b"); + + break; + case 0x087C: + sb.AppendLine("Device complies with SSA-S3P ANSI INCITS 309-1998"); + + break; + case 0x0880: + sb.AppendLine("Device complies with SSA-S2P (no version claimed)"); + + break; + case 0x089B: + sb.AppendLine("Device complies with SSA-S2P T10.1/1121-D revision 07b"); + + break; + case 0x089C: + sb.AppendLine("Device complies with SSA-S2P ANSI INCITS 294-1996"); + + break; + case 0x08A0: + sb.AppendLine("Device complies with SIP (no version claimed)"); + + break; + case 0x08BB: + sb.AppendLine("Device complies with SIP T10/0856-D revision 10"); + + break; + case 0x08BC: + sb.AppendLine("Device complies with SIP ANSI INCITS 292-1997"); + + break; + case 0x08C0: + sb.AppendLine("Device complies with FCP (no version claimed)"); + + break; + case 0x08DB: + sb.AppendLine("Device complies with FCP T10/0993-D revision 12"); + + break; + case 0x08DC: + sb.AppendLine("Device complies with FCP ANSI INCITS 269-1996"); + + break; + case 0x08E0: + sb.AppendLine("Device complies with SBP-2 (no version claimed)"); + + break; + case 0x08FB: + sb.AppendLine("Device complies with SBP-2 T10/1155-D revision 04"); + + break; + case 0x08FC: + sb.AppendLine("Device complies with SBP-2 ANSI INCITS 325-1998"); + + break; + case 0x0900: + sb.AppendLine("Device complies with FCP-2 (no version claimed)"); + + break; + case 0x0901: + sb.AppendLine("Device complies with FCP-2 T10/1144-D revision 4"); + + break; + case 0x0915: + sb.AppendLine("Device complies with FCP-2 T10/1144-D revision 7"); + + break; + case 0x0916: + sb.AppendLine("Device complies with FCP-2 T10/1144-D revision 7a"); + + break; + case 0x0917: + sb.AppendLine("Device complies with FCP-2 ANSI INCITS 350-2003"); + + break; + case 0x0918: + sb.AppendLine("Device complies with FCP-2 T10/1144-D revision 8"); + + break; + case 0x0920: + sb.AppendLine("Device complies with SST (no version claimed)"); + + break; + case 0x0935: + sb.AppendLine("Device complies with SST T10/1380-D revision 8b"); + + break; + case 0x0940: + sb.AppendLine("Device complies with SRP (no version claimed)"); + + break; + case 0x0954: + sb.AppendLine("Device complies with SRP T10/1415-D revision 10"); + + break; + case 0x0955: + sb.AppendLine("Device complies with SRP T10/1415-D revision 16a"); + + break; + case 0x095C: + sb.AppendLine("Device complies with SRP ANSI INCITS 365-2002"); + + break; + case 0x0960: + sb.AppendLine("Device complies with iSCSI (no version claimed)"); + + break; + case 0x0961: + case 0x0962: + case 0x0963: + case 0x0964: + case 0x0965: + case 0x0966: + case 0x0967: + case 0x0968: + case 0x0969: + case 0x096A: + case 0x096B: + case 0x096C: + case 0x096D: + case 0x096E: + case 0x096F: + case 0x0970: + case 0x0971: + case 0x0972: + case 0x0973: + case 0x0974: + case 0x0975: + case 0x0976: + case 0x0977: + case 0x0978: + case 0x0979: + case 0x097A: + case 0x097B: + case 0x097C: + case 0x097D: + case 0x097E: + case 0x097F: + sb.AppendFormat("Device complies with iSCSI revision {0}", VersionDescriptor & 0x1F). + AppendLine(); + + break; + case 0x0980: + sb.AppendLine("Device complies with SBP-3 (no version claimed)"); + + break; + case 0x0982: + sb.AppendLine("Device complies with SBP-3 T10/1467-D revision 1f"); + + break; + case 0x0994: + sb.AppendLine("Device complies with SBP-3 T10/1467-D revision 3"); + + break; + case 0x099A: + sb.AppendLine("Device complies with SBP-3 T10/1467-D revision 4"); + + break; + case 0x099B: + sb.AppendLine("Device complies with SBP-3 T10/1467-D revision 5"); + + break; + case 0x099C: + sb.AppendLine("Device complies with SBP-3 ANSI INCITS 375-2004"); + + break; + case 0x09C0: + sb.AppendLine("Device complies with ADP (no version claimed)"); + + break; + case 0x09E0: + sb.AppendLine("Device complies with ADT (no version claimed)"); + + break; + case 0x09F9: + sb.AppendLine("Device complies with ADT T10/1557-D revision 11"); + + break; + case 0x09FA: + sb.AppendLine("Device complies with ADT T10/1557-D revision 14"); + + break; + case 0x09FD: + sb.AppendLine("Device complies with ADT ANSI INCITS 406-2005"); + + break; + case 0x0A00: + sb.AppendLine("Device complies with FCP-3 (no version claimed)"); + + break; + case 0x0A07: + sb.AppendLine("Device complies with FCP-3 T10/1560-D revision 3f"); + + break; + case 0x0A0F: + sb.AppendLine("Device complies with FCP-3 T10/1560-D revision 4"); + + break; + case 0x0A11: + sb.AppendLine("Device complies with FCP-3 ANSI INCITS 416-2006"); + + break; + case 0x0A1C: + sb.AppendLine("Device complies with FCP-3 ISO/IEC 14776-223"); + + break; + case 0x0A20: + sb.AppendLine("Device complies with ADT-2 (no version claimed)"); + + break; + case 0x0A22: + sb.AppendLine("Device complies with ADT-2 T10/1742-D revision 06"); + + break; + case 0x0A27: + sb.AppendLine("Device complies with ADT-2 T10/1742-D revision 08"); + + break; + case 0x0A28: + sb.AppendLine("Device complies with ADT-2 T10/1742-D revision 09"); + + break; + case 0x0A2B: + sb.AppendLine("Device complies with ADT-2 ANSI INCITS 472-2011"); + + break; + case 0x0A40: + sb.AppendLine("Device complies with FCP-4 (no version claimed)"); + + break; + case 0x0A42: + sb.AppendLine("Device complies with FCP-4 T10/1828-D revision 01"); + + break; + case 0x0A44: + sb.AppendLine("Device complies with FCP-4 T10/1828-D revision 02"); + + break; + case 0x0A45: + sb.AppendLine("Device complies with FCP-4 T10/1828-D revision 02b"); + + break; + case 0x0A46: + sb.AppendLine("Device complies with FCP-4 ANSI INCITS 481-2012"); + + break; + case 0x0A60: + sb.AppendLine("Device complies with ADT-3 (no version claimed)"); + + break; + case 0x0AA0: + sb.AppendLine("Device complies with SPI (no version claimed)"); + + break; + case 0x0AB9: + sb.AppendLine("Device complies with SPI T10/0855-D revision 15a"); + + break; + case 0x0ABA: + sb.AppendLine("Device complies with SPI ANSI INCITS 253-1995"); + + break; + case 0x0ABB: + sb.AppendLine("Device complies with SPI T10/0855-D revision 15a with SPI Amnd revision 3a"); + + break; + case 0x0ABC: + sb.AppendLine("Device complies with SPI ANSI INCITS 253-1995 with SPI Amnd ANSI INCITS 253/AM1-1998"); + + break; + case 0x0AC0: + sb.AppendLine("Device complies with Fast-20 (no version claimed)"); + + break; + case 0x0ADB: + sb.AppendLine("Device complies with Fast-20 T10/1071 revision 06"); + + break; + case 0x0ADC: + sb.AppendLine("Device complies with Fast-20 ANSI INCITS 277-1996"); + + break; + case 0x0AE0: + sb.AppendLine("Device complies with SPI-2 (no version claimed)"); + + break; + case 0x0AFB: + sb.AppendLine("Device complies with SPI-2 T10/1142-D revision 20b"); + + break; + case 0x0AFC: + sb.AppendLine("Device complies with SPI-2 ANSI INCITS 302-1999"); + + break; + case 0x0B00: + sb.AppendLine("Device complies with SPI-3 (no version claimed)"); + + break; + case 0x0B18: + sb.AppendLine("Device complies with SPI-3 T10/1302-D revision 10"); + + break; + case 0x0B19: + sb.AppendLine("Device complies with SPI-3 T10/1302-D revision 13a"); + + break; + case 0x0B1A: + sb.AppendLine("Device complies with SPI-3 T10/1302-D revision 14"); + + break; + case 0x0B1C: + sb.AppendLine("Device complies with SPI-3 ANSI INCITS 336-2000"); + + break; + case 0x0B20: + sb.AppendLine("Device complies with EPI (no version claimed)"); + + break; + case 0x0B3B: + sb.AppendLine("Device complies with EPI T10/1134 revision 16"); + + break; + case 0x0B3C: + sb.AppendLine("Device complies with EPI ANSI INCITS TR-23 1999"); + + break; + case 0x0B40: + sb.AppendLine("Device complies with SPI-4 (no version claimed)"); + + break; + case 0x0B54: + sb.AppendLine("Device complies with SPI-4 T10/1365-D revision 7"); + + break; + case 0x0B55: + sb.AppendLine("Device complies with SPI-4 T10/1365-D revision 9"); + + break; + case 0x0B56: + sb.AppendLine("Device complies with SPI-4 ANSI INCITS 362-2002"); + + break; + case 0x0B59: + sb.AppendLine("Device complies with SPI-4 T10/1365-D revision 10"); + + break; + case 0x0B60: + sb.AppendLine("Device complies with SPI-5 (no version claimed)"); + + break; + case 0x0B79: + sb.AppendLine("Device complies with SPI-5 T10/1525-D revision 3"); + + break; + case 0x0B7A: + sb.AppendLine("Device complies with SPI-5 T10/1525-D revision 5"); + + break; + case 0x0B7B: + sb.AppendLine("Device complies with SPI-5 T10/1525-D revision 6"); + + break; + case 0x0B7C: + sb.AppendLine("Device complies with SPI-5 ANSI INCITS 367-2003"); + + break; + case 0x0BE0: + sb.AppendLine("Device complies with SAS (no version claimed)"); + + break; + case 0x0BE1: + sb.AppendLine("Device complies with SAS T10/1562-D revision 01"); + + break; + case 0x0BF5: + sb.AppendLine("Device complies with SAS T10/1562-D revision 03"); + + break; + case 0x0BFA: + sb.AppendLine("Device complies with SAS T10/1562-D revision 04"); + + break; + case 0x0BFB: + sb.AppendLine("Device complies with SAS T10/1562-D revision 04"); + + break; + case 0x0BFC: + sb.AppendLine("Device complies with SAS T10/1562-D revision 05"); + + break; + case 0x0BFD: + sb.AppendLine("Device complies with SAS ANSI INCITS 376-2003"); + + break; + case 0x0C00: + sb.AppendLine("Device complies with SAS-1.1 (no version claimed)"); + + break; + case 0x0C07: + sb.AppendLine("Device complies with SAS-1.1 T10/1601-D revision 9"); + + break; + case 0x0C0F: + sb.AppendLine("Device complies with SAS-1.1 T10/1601-D revision 10"); + + break; + case 0x0C11: + sb.AppendLine("Device complies with SAS-1.1 ANSI INCITS 417-2006"); + + break; + case 0x0C12: + sb.AppendLine("Device complies with SAS-1.1 ISO/IEC 14776-151"); + + break; + case 0x0C20: + sb.AppendLine("Device complies with SAS-2 (no version claimed)"); + + break; + case 0x0C23: + sb.AppendLine("Device complies with SAS-2 T10/1760-D revision 14"); + + break; + case 0x0C27: + sb.AppendLine("Device complies with SAS-2 T10/1760-D revision 15"); + + break; + case 0x0C28: + sb.AppendLine("Device complies with SAS-2 T10/1760-D revision 16"); + + break; + case 0x0C2A: + sb.AppendLine("Device complies with SAS-2 ANSI INCITS 457-2010"); + + break; + case 0x0C40: + sb.AppendLine("Device complies with SAS-2.1 (no version claimed)"); + + break; + case 0x0C48: + sb.AppendLine("Device complies with SAS-2.1 T10/2125-D revision 04"); + + break; + case 0x0C4A: + sb.AppendLine("Device complies with SAS-2.1 T10/2125-D revision 06"); + + break; + case 0x0C4B: + sb.AppendLine("Device complies with SAS-2.1 T10/2125-D revision 07"); + + break; + case 0x0C4E: + sb.AppendLine("Device complies with SAS-2.1 ANSI INCITS 478-2011"); + + break; + case 0x0C4F: + sb.AppendLine("Device complies with SAS-2.1 ANSI INCITS 478-2011 w/ Amnd 1 ANSI INCITS 478/AM1-2014"); + + break; + case 0x0C52: + sb.AppendLine("Device complies with SAS-2.1 ISO/IEC 14776-153"); + + break; + case 0x0C60: + sb.AppendLine("Device complies with SAS-3 (no version claimed)"); + + break; + case 0x0C63: + sb.AppendLine("Device complies with SAS-3 T10/BSR INCITS 519 revision 05a"); + + break; + case 0x0C65: + sb.AppendLine("Device complies with SAS-3 T10/BSR INCITS 519 revision 06"); + + break; + case 0x0C68: + sb.AppendLine("Device complies with SAS-3 ANSI INCITS 519-2014"); + + break; + case 0x0C80: + sb.AppendLine("Device complies with SAS-4 (no version claimed)"); + + break; + case 0x0D20: + sb.AppendLine("Device complies with FC-PH (no version claimed)"); + + break; + case 0x0D3B: + sb.AppendLine("Device complies with FC-PH ANSI INCITS 230-1994"); + + break; + case 0x0D3C: + sb.AppendLine("Device complies with FC-PH ANSI INCITS 230-1994 with Amnd 1 ANSI INCITS 230/AM1-1996"); + + break; + case 0x0D40: + sb.AppendLine("Device complies with FC-AL (no version claimed)"); + + break; + case 0x0D5C: + sb.AppendLine("Device complies with FC-AL ANSI INCITS 272-1996"); + + break; + case 0x0D60: + sb.AppendLine("Device complies with FC-AL-2 (no version claimed)"); + + break; + case 0x0D61: + sb.AppendLine("Device complies with FC-AL-2 T11/1133-D revision 7.0"); + + break; + case 0x0D63: + sb.AppendLine("Device complies with FC-AL-2 ANSI INCITS 332-1999 with AM1-2003 & AM2-2006"); + + break; + case 0x0D64: + sb.AppendLine("Device complies with FC-AL-2 ANSI INCITS 332-1999 with Amnd 2 AM2-2006"); + + break; + case 0x0D65: + sb.AppendLine("Device complies with FC-AL-2 ISO/IEC 14165-122 with AM1 & AM2"); + + break; + case 0x0D7C: + sb.AppendLine("Device complies with FC-AL-2 ANSI INCITS 332-1999"); + + break; + case 0x0D7D: + sb.AppendLine("Device complies with FC-AL-2 ANSI INCITS 332-1999 with Amnd 1 AM1-2003"); + + break; + case 0x0D80: + sb.AppendLine("Device complies with FC-PH-3 (no version claimed)"); + + break; + case 0x0D9C: + sb.AppendLine("Device complies with FC-PH-3 ANSI INCITS 303-1998"); + + break; + case 0x0DA0: + sb.AppendLine("Device complies with FC-FS (no version claimed)"); + + break; + case 0x0DB7: + sb.AppendLine("Device complies with FC-FS T11/1331-D revision 1.2"); + + break; + case 0x0DB8: + sb.AppendLine("Device complies with FC-FS T11/1331-D revision 1.7"); + + break; + case 0x0DBC: + sb.AppendLine("Device complies with FC-FS ANSI INCITS 373-2003"); + + break; + case 0x0DBD: + sb.AppendLine("Device complies with FC-FS ISO/IEC 14165-251"); + + break; + case 0x0DC0: + sb.AppendLine("Device complies with FC-PI (no version claimed)"); + + break; + case 0x0DDC: + sb.AppendLine("Device complies with FC-PI ANSI INCITS 352-2002"); + + break; + case 0x0DE0: + sb.AppendLine("Device complies with FC-PI-2 (no version claimed)"); + + break; + case 0x0DE2: + sb.AppendLine("Device complies with FC-PI-2 T11/1506-D revision 5.0"); + + break; + case 0x0DE4: + sb.AppendLine("Device complies with FC-PI-2 ANSI INCITS 404-2006"); + + break; + case 0x0E00: + sb.AppendLine("Device complies with FC-FS-2 (no version claimed)"); + + break; + case 0x0E02: + sb.AppendLine("Device complies with FC-FS-2 ANSI INCITS 242-2007"); + + break; + case 0x0E03: + sb.AppendLine("Device complies with FC-FS-2 ANSI INCITS 242-2007 with AM1 ANSI INCITS 242/AM1-2007"); + + break; + case 0x0E20: + sb.AppendLine("Device complies with FC-LS (no version claimed)"); + + break; + case 0x0E21: + sb.AppendLine("Device complies with FC-LS T11/1620-D revision 1.62"); + + break; + case 0x0E29: + sb.AppendLine("Device complies with FC-LS ANSI INCITS 433-2007"); + + break; + case 0x0E40: + sb.AppendLine("Device complies with FC-SP (no version claimed)"); + + break; + case 0x0E42: + sb.AppendLine("Device complies with FC-SP T11/1570-D revision 1.6"); + + break; + case 0x0E45: + sb.AppendLine("Device complies with FC-SP ANSI INCITS 426-2007"); + + break; + case 0x0E60: + sb.AppendLine("Device complies with FC-PI-3 (no version claimed)"); + + break; + case 0x0E62: + sb.AppendLine("Device complies with FC-PI-3 T11/1625-D revision 2.0"); + + break; + case 0x0E68: + sb.AppendLine("Device complies with FC-PI-3 T11/1625-D revision 2.1"); + + break; + case 0x0E6A: + sb.AppendLine("Device complies with FC-PI-3 T11/1625-D revision 4.0"); + + break; + case 0x0E6E: + sb.AppendLine("Device complies with FC-PI-3 ANSI INCITS 460-2011"); + + break; + case 0x0E80: + sb.AppendLine("Device complies with FC-PI-4 (no version claimed)"); + + break; + case 0x0E82: + sb.AppendLine("Device complies with FC-PI-4 T11/1647-D revision 8.0"); + + break; + case 0x0E88: + sb.AppendLine("Device complies with FC-PI-4 ANSI INCITS 450-2009"); + + break; + case 0x0EA0: + sb.AppendLine("Device complies with FC 10GFC (no version claimed)"); + + break; + case 0x0EA2: + sb.AppendLine("Device complies with FC 10GFC ANSI INCITS 364-2003"); + + break; + case 0x0EA3: + sb.AppendLine("Device complies with FC 10GFC ISO/IEC 14165-116"); + + break; + case 0x0EA5: + sb.AppendLine("Device complies with FC 10GFC ISO/IEC 14165-116 with AM1"); + + break; + case 0x0EA6: + sb.AppendLine("Device complies with FC 10GFC ANSI INCITS 364-2003 with AM1 ANSI INCITS 364/AM1-2007"); + + break; + case 0x0EC0: + sb.AppendLine("Device complies with FC-SP-2 (no version claimed)"); + + break; + case 0x0EE0: + sb.AppendLine("Device complies with FC-FS-3 (no version claimed)"); + + break; + case 0x0EE2: + sb.AppendLine("Device complies with FC-FS-3 T11/1861-D revision 0.9"); + + break; + case 0x0EE7: + sb.AppendLine("Device complies with FC-FS-3 T11/1861-D revision 1.0"); + + break; + case 0x0EE9: + sb.AppendLine("Device complies with FC-FS-3 T11/1861-D revision 1.10"); + + break; + case 0x0EEB: + sb.AppendLine("Device complies with FC-FS-3 ANSI INCITS 470-2011"); + + break; + case 0x0F00: + sb.AppendLine("Device complies with FC-LS-2 (no version claimed)"); + + break; + case 0x0F03: + sb.AppendLine("Device complies with FC-LS-2 T11/2103-D revision 2.11"); + + break; + case 0x0F05: + sb.AppendLine("Device complies with FC-LS-2 T11/2103-D revision 2.21"); + + break; + case 0x0F07: + sb.AppendLine("Device complies with FC-LS-2 ANSI INCITS 477-2011"); + + break; + case 0x0F20: + sb.AppendLine("Device complies with FC-PI-5 (no version claimed)"); + + break; + case 0x0F27: + sb.AppendLine("Device complies with FC-PI-5 T11/2118-D revision 2.00"); + + break; + case 0x0F28: + sb.AppendLine("Device complies with FC-PI-5 T11/2118-D revision 3.00"); + + break; + case 0x0F2A: + sb.AppendLine("Device complies with FC-PI-5 T11/2118-D revision 6.00"); + + break; + case 0x0F2B: + sb.AppendLine("Device complies with FC-PI-5 T11/2118-D revision 6.10"); + + break; + case 0x0F2E: + sb.AppendLine("Device complies with FC-PI-5 ANSI INCITS 479-2011"); + + break; + case 0x0F40: + sb.AppendLine("Device complies with FC-PI-6 (no version claimed)"); + + break; + case 0x0F60: + sb.AppendLine("Device complies with FC-FS-4 (no version claimed)"); + + break; + case 0x0F80: + sb.AppendLine("Device complies with FC-LS-3 (no version claimed)"); + + break; + case 0x12A0: + sb.AppendLine("Device complies with FC-SCM (no version claimed)"); + + break; + case 0x12A3: + sb.AppendLine("Device complies with FC-SCM T11/1824DT revision 1.0"); + + break; + case 0x12A5: + sb.AppendLine("Device complies with FC-SCM T11/1824DT revision 1.1"); + + break; + case 0x12A7: + sb.AppendLine("Device complies with FC-SCM T11/1824DT revision 1.4"); + + break; + case 0x12AA: + sb.AppendLine("Device complies with FC-SCM INCITS TR-47 2012"); + + break; + case 0x12C0: + sb.AppendLine("Device complies with FC-DA-2 (no version claimed)"); + + break; + case 0x12C3: + sb.AppendLine("Device complies with FC-DA-2 T11/1870DT revision 1.04"); + + break; + case 0x12C5: + sb.AppendLine("Device complies with FC-DA-2 T11/1870DT revision 1.06"); + + break; + case 0x12C9: + sb.AppendLine("Device complies with FC-DA-2 INCITS TR-49 2012"); + + break; + case 0x12E0: + sb.AppendLine("Device complies with FC-DA (no version claimed)"); + + break; + case 0x12E2: + sb.AppendLine("Device complies with FC-DA T11/1513-DT revision 3.1"); + + break; + case 0x12E8: + sb.AppendLine("Device complies with FC-DA ANSI INCITS TR-36 2004"); + + break; + case 0x12E9: + sb.AppendLine("Device complies with FC-DA ISO/IEC 14165-341"); + + break; + case 0x1300: + sb.AppendLine("Device complies with FC-Tape (no version claimed)"); + + break; + case 0x1301: + sb.AppendLine("Device complies with FC-Tape T11/1315 revision 1.16"); + + break; + case 0x131B: + sb.AppendLine("Device complies with FC-Tape T11/1315 revision 1.17"); + + break; + case 0x131C: + sb.AppendLine("Device complies with FC-Tape ANSI INCITS TR-24 1999"); + + break; + case 0x1320: + sb.AppendLine("Device complies with FC-FLA (no version claimed)"); + + break; + case 0x133B: + sb.AppendLine("Device complies with FC-FLA T11/1235 revision 7"); + + break; + case 0x133C: + sb.AppendLine("Device complies with FC-FLA ANSI INCITS TR-20 1998"); + + break; + case 0x1340: + sb.AppendLine("Device complies with FC-PLDA (no version claimed)"); + + break; + case 0x135B: + sb.AppendLine("Device complies with FC-PLDA T11/1162 revision 2.1"); + + break; + case 0x135C: + sb.AppendLine("Device complies with FC-PLDA ANSI INCITS TR-19 1998"); + + break; + case 0x1360: + sb.AppendLine("Device complies with SSA-PH2 (no version claimed)"); + + break; + case 0x137B: + sb.AppendLine("Device complies with SSA-PH2 T10.1/1145-D revision 09c"); + + break; + case 0x137C: + sb.AppendLine("Device complies with SSA-PH2 ANSI INCITS 293-1996"); + + break; + case 0x1380: + sb.AppendLine("Device complies with SSA-PH3 (no version claimed)"); + + break; + case 0x139B: + sb.AppendLine("Device complies with SSA-PH3 T10.1/1146-D revision 05b"); + + break; + case 0x139C: + sb.AppendLine("Device complies with SSA-PH3 ANSI INCITS 307-1998"); + + break; + case 0x14A0: + sb.AppendLine("Device complies with IEEE 1394 (no version claimed)"); + + break; + case 0x14BD: + sb.AppendLine("Device complies with ANSI IEEE 1394-1995"); + + break; + case 0x14C0: + sb.AppendLine("Device complies with IEEE 1394a (no version claimed)"); + + break; + case 0x14E0: + sb.AppendLine("Device complies with IEEE 1394b (no version claimed)"); + + break; + case 0x15E0: + sb.AppendLine("Device complies with ATA/ATAPI-6 (no version claimed)"); + + break; + case 0x15FD: + sb.AppendLine("Device complies with ATA/ATAPI-6 ANSI INCITS 361-2002"); + + break; + case 0x1600: + sb.AppendLine("Device complies with ATA/ATAPI-7 (no version claimed)"); + + break; + case 0x1602: + sb.AppendLine("Device complies with ATA/ATAPI-7 T13/1532-D revision 3"); + + break; + case 0x161C: + sb.AppendLine("Device complies with ATA/ATAPI-7 ANSI INCITS 397-2005"); + + break; + case 0x161E: + sb.AppendLine("Device complies with ATA/ATAPI-7 ISO/IEC 24739"); + + break; + case 0x1620: + sb.AppendLine("Device complies with ATA/ATAPI-8 ATA8-AAM (no version claimed)"); + + break; + case 0x1621: + sb.AppendLine("Device complies with ATA/ATAPI-8 ATA8-APT Parallel Transport (no version claimed)"); + + break; + case 0x1622: + sb.AppendLine("Device complies with ATA/ATAPI-8 ATA8-AST Serial Transport (no version claimed)"); + + break; + case 0x1623: + sb.AppendLine("Device complies with ATA/ATAPI-8 ATA8-ACS ATA/ATAPI Command Set (no version claimed)"); + + break; + case 0x1628: + sb.AppendLine("Device complies with ATA/ATAPI-8 ATA8-AAM ANSI INCITS 451-2008"); + + break; + case 0x162A: + sb.AppendLine("Device complies with ATA/ATAPI-8 ATA8-ACS ANSI INCITS 452-2009 w/ Amendment 1"); + + break; + case 0x1728: + sb.AppendLine("Device complies with Universal Serial Bus Specification, Revision 1.1"); + + break; + case 0x1729: + sb.AppendLine("Device complies with Universal Serial Bus Specification, Revision 2.0"); + + break; + case 0x1730: + sb.AppendLine("Device complies with USB Mass Storage Class Bulk-Only Transport, Revision 1.0"); + + break; + case 0x1740: + sb.AppendLine("Device complies with UAS (no version claimed)"); + + break; + case 0x1743: + sb.AppendLine("Device complies with UAS T10/2095-D revision 02"); + + break; + case 0x1747: + sb.AppendLine("Device complies with UAS T10/2095-D revision 04"); + + break; + case 0x1748: + sb.AppendLine("Device complies with UAS ANSI INCITS 471-2010"); + + break; + case 0x1749: + sb.AppendLine("Device complies with UAS ISO/IEC 14776-251:2014"); + + break; + case 0x1761: + sb.AppendLine("Device complies with ACS-2 (no version claimed)"); + + break; + case 0x1762: + sb.AppendLine("Device complies with ACS-2 ANSI INCITS 482-2013"); + + break; + case 0x1765: + sb.AppendLine("Device complies with ACS-3 (no version claimed)"); + + break; + case 0x1780: + sb.AppendLine("Device complies with UAS-2 (no version claimed)"); + + break; + case 0x1EA0: + sb.AppendLine("Device complies with SAT (no version claimed)"); + + break; + case 0x1EA7: + sb.AppendLine("Device complies with SAT T10/1711-D revision 8"); + + break; + case 0x1EAB: + sb.AppendLine("Device complies with SAT T10/1711-D revision 9"); + + break; + case 0x1EAD: + sb.AppendLine("Device complies with SAT ANSI INCITS 431-2007"); + + break; + case 0x1EC0: + sb.AppendLine("Device complies with SAT-2 (no version claimed)"); + + break; + case 0x1EC4: + sb.AppendLine("Device complies with SAT-2 T10/1826-D revision 06"); + + break; + case 0x1EC8: + sb.AppendLine("Device complies with SAT-2 T10/1826-D revision 09"); + + break; + case 0x1ECA: + sb.AppendLine("Device complies with SAT-2 ANSI INCITS 465-2010"); + + break; + case 0x1EE0: + sb.AppendLine("Device complies with SAT-3 (no version claimed)"); + + break; + case 0x1EE2: + sb.AppendLine("Device complies with SAT-3 T10/BSR INCITS 517 revision 4"); + + break; + case 0x1EE4: + sb.AppendLine("Device complies with SAT-3 T10/BSR INCITS 517 revision 7"); + + break; + case 0x1EE8: + sb.AppendLine("Device complies with SAT-3 ANSI INCITS 517-2015"); + + break; + case 0x1F00: + sb.AppendLine("Device complies with SAT-4 (no version claimed)"); + + break; + case 0x20A0: + sb.AppendLine("Device complies with SPL (no version claimed)"); + + break; + case 0x20A3: + sb.AppendLine("Device complies with SPL T10/2124-D revision 6a"); + + break; + case 0x20A5: + sb.AppendLine("Device complies with SPL T10/2124-D revision 7"); + + break; + case 0x20A7: + sb.AppendLine("Device complies with SPL ANSI INCITS 476-2011"); + + break; + case 0x20A8: + sb.AppendLine("Device complies with SPL ANSI INCITS 476-2011 + SPL AM1 INCITS 476/AM1 2012"); + + break; + case 0x20AA: + sb.AppendLine("Device complies with SPL ISO/IEC 14776-261:2012"); + + break; + case 0x20C0: + sb.AppendLine("Device complies with SPL-2 (no version claimed)"); + + break; + case 0x20C2: + sb.AppendLine("Device complies with SPL-2 T10/BSR INCITS 505 revision 4"); + + break; + case 0x20C4: + sb.AppendLine("Device complies with SPL-2 T10/BSR INCITS 505 revision 5"); + + break; + case 0x20C8: + sb.AppendLine("Device complies with SPL-2 ANSI INCITS 505-2013"); + + break; + case 0x20E0: + sb.AppendLine("Device complies with SPL-3 (no version claimed)"); + + break; + case 0x20E4: + sb.AppendLine("Device complies with SPL-3 T10/BSR INCITS 492 revision 6"); + + break; + case 0x20E6: + sb.AppendLine("Device complies with SPL-3 T10/BSR INCITS 492 revision 7"); + + break; + case 0x20E8: + sb.AppendLine("Device complies with SPL-3 ANSI INCITS 492-2015"); + + break; + case 0x2100: + sb.AppendLine("Device complies with SPL-4 (no version claimed)"); + + break; + case 0x21E0: + sb.AppendLine("Device complies with SOP (no version claimed)"); + + break; + case 0x21E4: + sb.AppendLine("Device complies with SOP T10/BSR INCITS 489 revision 4"); + + break; + case 0x21E6: + sb.AppendLine("Device complies with SOP T10/BSR INCITS 489 revision 5"); + + break; + case 0x21E8: + sb.AppendLine("Device complies with SOP ANSI INCITS 489-2014"); + + break; + case 0x2200: + sb.AppendLine("Device complies with PQI (no version claimed)"); + + break; + case 0x2204: + sb.AppendLine("Device complies with PQI T10/BSR INCITS 490 revision 6"); + + break; + case 0x2206: + sb.AppendLine("Device complies with PQI T10/BSR INCITS 490 revision 7"); + + break; + case 0x2208: + sb.AppendLine("Device complies with PQI ANSI INCITS 490-2014"); + + break; + case 0x2220: + sb.AppendLine("Device complies with SOP-2 (no version claimed)"); + + break; + case 0x2240: + sb.AppendLine("Device complies with PQI-2 (no version claimed)"); + + break; + case 0xFFC0: + sb.AppendLine("Device complies with IEEE 1667 (no version claimed)"); + + break; + case 0xFFC1: + sb.AppendLine("Device complies with IEEE 1667-2006"); + + break; + case 0xFFC2: + sb.AppendLine("Device complies with IEEE 1667-2009"); + + break; + default: + sb.AppendFormat("Device complies with unknown standard code 0x{0:X4}", VersionDescriptor). + AppendLine(); + + break; + } + + #region Quantum vendor prettifying + if(response.QuantumPresent && + StringHandlers.CToString(response.VendorIdentification).ToLowerInvariant().Trim() == "quantum") + { + sb.AppendLine("Quantum vendor-specific information:"); + + switch(response.Qt_ProductFamily) + { + case 0: + sb.AppendLine("Product family is not specified"); + + break; + case 1: + sb.AppendLine("Product family is 2.6 GB"); + + break; + case 2: + sb.AppendLine("Product family is 6.0 GB"); + + break; + case 3: + sb.AppendLine("Product family is 10.0/20.0 GB"); + + break; + case 5: + sb.AppendLine("Product family is 20.0/40.0 GB"); + + break; + case 6: + sb.AppendLine("Product family is 15.0/30.0 GB"); + + break; + default: + sb.AppendFormat("Product family: {0}", response.Qt_ProductFamily).AppendLine(); + + break; + } + + sb.AppendFormat("Release firmware: {0}", response.Qt_ReleasedFirmware).AppendLine(); + + sb.AppendFormat("Firmware version: {0}.{1}", response.Qt_FirmwareMajorVersion, + response.Qt_FirmwareMinorVersion).AppendLine(); + + sb.AppendFormat("EEPROM format version: {0}.{1}", response.Qt_EEPROMFormatMajorVersion, + response.Qt_EEPROMFormatMinorVersion).AppendLine(); + + sb.AppendFormat("Firmware personality: {0}", response.Qt_FirmwarePersonality).AppendLine(); + sb.AppendFormat("Firmware subpersonality: {0}", response.Qt_FirmwareSubPersonality).AppendLine(); + + sb.AppendFormat("Tape directory format version: {0}", response.Qt_TapeDirectoryFormatVersion). + AppendLine(); + + sb.AppendFormat("Controller hardware version: {0}", response.Qt_ControllerHardwareVersion).AppendLine(); + sb.AppendFormat("Drive EEPROM version: {0}", response.Qt_DriveEEPROMVersion).AppendLine(); + sb.AppendFormat("Drive hardware version: {0}", response.Qt_DriveHardwareVersion).AppendLine(); + + sb.AppendFormat("Media loader firmware version: {0}", response.Qt_MediaLoaderFirmwareVersion). + AppendLine(); + + sb.AppendFormat("Media loader hardware version: {0}", response.Qt_MediaLoaderHardwareVersion). + AppendLine(); + + sb.AppendFormat("Media loader mechanical version: {0}", response.Qt_MediaLoaderMechanicalVersion). + AppendLine(); + + if(response.Qt_LibraryPresent) + sb.AppendLine("Library is present"); + + if(response.Qt_MediaLoaderPresent) + sb.AppendLine("Media loader is present"); + + sb.AppendFormat("Module revision: {0}", StringHandlers.CToString(response.Qt_ModuleRevision)). + AppendLine(); + } + #endregion Quantum vendor prettifying + + #region IBM vendor prettifying + if(response.IBMPresent && + StringHandlers.CToString(response.VendorIdentification).ToLowerInvariant().Trim() == "ibm") + { + sb.AppendLine("IBM vendor-specific information:"); + + if(response.IBM_PerformanceLimit == 0) + sb.AppendLine("Performance is not limited"); + else + sb.AppendFormat("Performance is limited using factor {0}", response.IBM_PerformanceLimit); + + if(response.IBM_AutDis) + sb.AppendLine("Automation is disabled"); + + sb.AppendFormat("IBM OEM Specific Field: {0}", response.IBM_OEMSpecific).AppendLine(); + } + #endregion IBM vendor prettifying + + #region HP vendor prettifying + if(response.HPPresent && + StringHandlers.CToString(response.VendorIdentification).ToLowerInvariant().Trim() == "hp") + { + sb.AppendLine("HP vendor-specific information:"); + + if(response.HP_WORM) + sb.AppendFormat("Device supports WORM version {0}", response.HP_WORMVersion).AppendLine(); + + byte[] OBDRSign = + { + 0x24, 0x44, 0x52, 0x2D, 0x31, 0x30 + }; + + if(OBDRSign.SequenceEqual(response.HP_OBDR)) + sb.AppendLine("Device supports Tape Disaster Recovery"); + } + #endregion HP vendor prettifying + + #region Seagate vendor prettifying + if((response.SeagatePresent || response.Seagate2Present || response.Seagate3Present) && + StringHandlers.CToString(response.VendorIdentification).ToLowerInvariant().Trim() == "seagate") + { + sb.AppendLine("Seagate vendor-specific information:"); + + if(response.SeagatePresent) + sb.AppendFormat("Drive serial number: {0}", + StringHandlers.CToString(response.Seagate_DriveSerialNumber)).AppendLine(); + + if(response.Seagate2Present) + sb.AppendFormat("Drive copyright: {0}", StringHandlers.CToString(response.Seagate_Copyright)). + AppendLine(); + + if(response.Seagate3Present) + sb.AppendFormat("Drive servo part number: {0}", + PrintHex.ByteArrayToHexArrayString(response.Seagate_ServoPROMPartNo, 40)). + AppendLine(); + } + #endregion Seagate vendor prettifying + + #region Kreon vendor prettifying + if(response.KreonPresent) + sb.AppendFormat("Drive is flashed with Kreon firmware {0}.", + StringHandlers.CToString(response.KreonVersion)).AppendLine(); + #endregion Kreon vendor prettifying + + #if DEBUG + if(response.DeviceTypeModifier != 0) + sb.AppendFormat("Vendor's device type modifier = 0x{0:X2}", response.DeviceTypeModifier).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved byte 5, bits 2 to 1 = 0x{0:X2}", response.Reserved2).AppendLine(); + + if(response.Reserved3 != 0) + sb.AppendFormat("Reserved byte 56, bits 7 to 4 = 0x{0:X2}", response.Reserved3).AppendLine(); + + if(response.Reserved4 != 0) + sb.AppendFormat("Reserved byte 57 = 0x{0:X2}", response.Reserved4).AppendLine(); + + if(response.Reserved5 != null) + { + sb.AppendLine("Reserved bytes 74 to 95"); + sb.AppendLine("============================================================"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.Reserved5, 60)); + sb.AppendLine("============================================================"); + } + + if(response.VendorSpecific != null && + response.IsHiMD) + if(response.KreonPresent) + { + byte[] vendor = new byte[7]; + Array.Copy(response.VendorSpecific, 11, vendor, 0, 7); + sb.AppendLine("Vendor-specific bytes 47 to 55"); + sb.AppendLine("============================================================"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(vendor, 60)); + sb.AppendLine("============================================================"); + } + else + { + sb.AppendLine("Vendor-specific bytes 36 to 55"); + sb.AppendLine("============================================================"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.VendorSpecific, 60)); + sb.AppendLine("============================================================"); + } + + if(response.IsHiMD) + { + sb.AppendLine("Hi-MD device."); + + if(response.HiMDSpecific != null) + { + sb.AppendLine("Hi-MD specific bytes 44 to 55"); + sb.AppendLine("============================================================"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.HiMDSpecific, 60)); + sb.AppendLine("============================================================"); + } + } + + if(response.VendorSpecific2 == null) + return sb.ToString(); + + sb.AppendFormat("Vendor-specific bytes 96 to {0}", response.AdditionalLength + 4).AppendLine(); + sb.AppendLine("============================================================"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.VendorSpecific2, 60)); + sb.AppendLine("============================================================"); + #endif + + return sb.ToString(); + } + + public static string Prettify(byte[] SCSIInquiryResponse) + { + CommonTypes.Structs.Devices.SCSI.Inquiry? decoded = + CommonTypes.Structs.Devices.SCSI.Inquiry.Decode(SCSIInquiryResponse); + + return Prettify(decoded); + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/MMC/AACS.cs b/Aaru.Decoders/SCSI/MMC/AACS.cs new file mode 100644 index 000000000..eb644e679 --- /dev/null +++ b/Aaru.Decoders/SCSI/MMC/AACS.cs @@ -0,0 +1,429 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : AACS.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes AACS structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Helpers; + +namespace Aaru.Decoders.SCSI.MMC +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class AACS + { + public static AACSVolumeIdentifier? DecodeAACSVolumeIdentifier(byte[] AACSVIResponse) + { + if(AACSVIResponse == null) + return null; + + var decoded = new AACSVolumeIdentifier(); + + decoded.VolumeIdentifier = new byte[AACSVIResponse.Length - 4]; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(AACSVIResponse, 0); + decoded.Reserved1 = AACSVIResponse[2]; + decoded.Reserved2 = AACSVIResponse[3]; + Array.Copy(AACSVIResponse, 4, decoded.VolumeIdentifier, 0, AACSVIResponse.Length - 4); + + return decoded; + } + + public static string PrettifyAACSVolumeIdentifier(AACSVolumeIdentifier? AACSVIResponse) + { + if(AACSVIResponse == null) + return null; + + AACSVolumeIdentifier response = AACSVIResponse.Value; + + var sb = new StringBuilder(); + + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + #endif + sb.AppendFormat("AACS Volume Identifier in hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.VolumeIdentifier, 80)); + + return sb.ToString(); + } + + public static string PrettifyAACSVolumeIdentifier(byte[] AACSVIResponse) + { + AACSVolumeIdentifier? decoded = DecodeAACSVolumeIdentifier(AACSVIResponse); + + return PrettifyAACSVolumeIdentifier(decoded); + } + + public static AACSMediaSerialNumber? DecodeAACSMediaSerialNumber(byte[] AACSMSNResponse) + { + if(AACSMSNResponse == null) + return null; + + var decoded = new AACSMediaSerialNumber(); + + decoded.MediaSerialNumber = new byte[AACSMSNResponse.Length - 4]; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(AACSMSNResponse, 0); + decoded.Reserved1 = AACSMSNResponse[2]; + decoded.Reserved2 = AACSMSNResponse[3]; + Array.Copy(AACSMSNResponse, 4, decoded.MediaSerialNumber, 0, AACSMSNResponse.Length - 4); + + return decoded; + } + + public static string PrettifyAACSMediaSerialNumber(AACSMediaSerialNumber? AACSMSNResponse) + { + if(AACSMSNResponse == null) + return null; + + AACSMediaSerialNumber response = AACSMSNResponse.Value; + + var sb = new StringBuilder(); + + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + #endif + sb.AppendFormat("AACS Media Serial Number in hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.MediaSerialNumber, 80)); + + return sb.ToString(); + } + + public static string PrettifyAACSMediaSerialNumber(byte[] AACSMSNResponse) + { + AACSMediaSerialNumber? decoded = DecodeAACSMediaSerialNumber(AACSMSNResponse); + + return PrettifyAACSMediaSerialNumber(decoded); + } + + public static AACSMediaIdentifier? DecodeAACSMediaIdentifier(byte[] AACSMIResponse) + { + if(AACSMIResponse == null) + return null; + + var decoded = new AACSMediaIdentifier(); + + decoded.MediaIdentifier = new byte[AACSMIResponse.Length - 4]; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(AACSMIResponse, 0); + decoded.Reserved1 = AACSMIResponse[2]; + decoded.Reserved2 = AACSMIResponse[3]; + Array.Copy(AACSMIResponse, 4, decoded.MediaIdentifier, 0, AACSMIResponse.Length - 4); + + return decoded; + } + + public static string PrettifyAACSMediaIdentifier(AACSMediaIdentifier? AACSMIResponse) + { + if(AACSMIResponse == null) + return null; + + AACSMediaIdentifier response = AACSMIResponse.Value; + + var sb = new StringBuilder(); + + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + #endif + sb.AppendFormat("AACS Media Identifier in hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.MediaIdentifier, 80)); + + return sb.ToString(); + } + + public static string PrettifyAACSMediaIdentifier(byte[] AACSMIResponse) + { + AACSMediaIdentifier? decoded = DecodeAACSMediaIdentifier(AACSMIResponse); + + return PrettifyAACSMediaIdentifier(decoded); + } + + public static AACSMediaKeyBlock? DecodeAACSMediaKeyBlock(byte[] AACSMKBResponse) + { + if(AACSMKBResponse == null) + return null; + + var decoded = new AACSMediaKeyBlock(); + + decoded.MediaKeyBlockPacks = new byte[AACSMKBResponse.Length - 4]; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(AACSMKBResponse, 0); + decoded.Reserved = AACSMKBResponse[2]; + decoded.TotalPacks = AACSMKBResponse[3]; + Array.Copy(AACSMKBResponse, 4, decoded.MediaKeyBlockPacks, 0, AACSMKBResponse.Length - 4); + + return decoded; + } + + public static string PrettifyAACSMediaKeyBlock(AACSMediaKeyBlock? AACSMKBResponse) + { + if(AACSMKBResponse == null) + return null; + + AACSMediaKeyBlock response = AACSMKBResponse.Value; + + var sb = new StringBuilder(); + + #if DEBUG + if(response.Reserved != 0) + sb.AppendFormat("Reserved = 0x{0:X2}", response.Reserved).AppendLine(); + #endif + sb.AppendFormat("Total number of media key blocks available to transfer {0}", response.TotalPacks). + AppendLine(); + + sb.AppendFormat("AACS Media Key Blocks in hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.MediaKeyBlockPacks, 80)); + + return sb.ToString(); + } + + public static string PrettifyAACSMediaKeyBlock(byte[] AACSMKBResponse) + { + AACSMediaKeyBlock? decoded = DecodeAACSMediaKeyBlock(AACSMKBResponse); + + return PrettifyAACSMediaKeyBlock(decoded); + } + + public static AACSDataKeys? DecodeAACSDataKeys(byte[] AACSDKResponse) + { + if(AACSDKResponse == null) + return null; + + var decoded = new AACSDataKeys(); + + decoded.DataKeys = new byte[AACSDKResponse.Length - 4]; + + decoded.DataLength = BigEndianBitConverter.ToUInt16(AACSDKResponse, 0); + decoded.Reserved1 = AACSDKResponse[2]; + decoded.Reserved2 = AACSDKResponse[3]; + Array.Copy(AACSDKResponse, 4, decoded.DataKeys, 0, AACSDKResponse.Length - 4); + + return decoded; + } + + public static string PrettifyAACSDataKeys(AACSDataKeys? AACSDKResponse) + { + if(AACSDKResponse == null) + return null; + + AACSDataKeys response = AACSDKResponse.Value; + + var sb = new StringBuilder(); + + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + #endif + sb.AppendFormat("AACS Data Keys in hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.DataKeys, 80)); + + return sb.ToString(); + } + + public static string PrettifyAACSDataKeys(byte[] AACSDKResponse) + { + AACSDataKeys? decoded = DecodeAACSDataKeys(AACSDKResponse); + + return PrettifyAACSDataKeys(decoded); + } + + public static AACSLBAExtentsResponse? DecodeAACSLBAExtents(byte[] AACSLBAExtsResponse) + { + if(AACSLBAExtsResponse == null) + return null; + + var decoded = new AACSLBAExtentsResponse + { + DataLength = BigEndianBitConverter.ToUInt16(AACSLBAExtsResponse, 0), + Reserved = AACSLBAExtsResponse[2], + MaxLBAExtents = AACSLBAExtsResponse[3] + }; + + if((AACSLBAExtsResponse.Length - 4) % 16 != 0) + return decoded; + + decoded.Extents = new AACSLBAExtent[(AACSLBAExtsResponse.Length - 4) / 16]; + + for(int i = 0; i < (AACSLBAExtsResponse.Length - 4) / 16; i++) + { + decoded.Extents[i].Reserved = new byte[8]; + Array.Copy(AACSLBAExtsResponse, 0 + (i * 16) + 4, decoded.Extents[i].Reserved, 0, 8); + decoded.Extents[i].StartLBA = BigEndianBitConverter.ToUInt32(AACSLBAExtsResponse, 8 + (i * 16) + 4); + decoded.Extents[i].LBACount = BigEndianBitConverter.ToUInt32(AACSLBAExtsResponse, 12 + (i * 16) + 4); + } + + return decoded; + } + + public static string PrettifyAACSLBAExtents(AACSLBAExtentsResponse? AACSLBAExtsResponse) + { + if(AACSLBAExtsResponse == null) + return null; + + AACSLBAExtentsResponse response = AACSLBAExtsResponse.Value; + + var sb = new StringBuilder(); + + if(response.MaxLBAExtents == 0) + sb.AppendLine(response.DataLength > 2 ? "Drive can store 256 LBA Extents" + : "Drive cannot store LBA Extents"); + else + sb.AppendFormat("Drive can store {0} LBA Extents", response.MaxLBAExtents).AppendLine(); + + for(int i = 0; i < response.Extents.Length; i++) + sb.AppendFormat("LBA Extent {0} starts at LBA {1} and goes for {2} sectors", i, + response.Extents[i].StartLBA, response.Extents[i].LBACount); + + return sb.ToString(); + } + + public static string PrettifyAACSLBAExtents(byte[] AACSLBAExtsResponse) + { + AACSLBAExtentsResponse? decoded = DecodeAACSLBAExtents(AACSLBAExtsResponse); + + return PrettifyAACSLBAExtents(decoded); + } + + public struct AACSVolumeIdentifier + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to end AACS volume identifier data + public byte[] VolumeIdentifier; + } + + public struct AACSMediaSerialNumber + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to end AACS media serial number + public byte[] MediaSerialNumber; + } + + public struct AACSMediaIdentifier + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to end AACS media identifier data + public byte[] MediaIdentifier; + } + + public struct AACSMediaKeyBlock + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved; + /// Byte 3 Number of MKB packs available to transfer + public byte TotalPacks; + /// Bytes 4 to end AACS media key block packs + public byte[] MediaKeyBlockPacks; + } + + public struct AACSDataKeys + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to end AACS data keys + public byte[] DataKeys; + } + + public struct AACSLBAExtentsResponse + { + /// Bytes 0 to 1 Data Length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved; + /// + /// Byte 3 Number of LBA extents the drive can store. if(MaxLBAExtents == 0 && DataLength > 2), 256 + /// extents can be stored + /// + public byte MaxLBAExtents; + /// Bytes 4 to end LBA Extents + public AACSLBAExtent[] Extents; + } + + public struct AACSLBAExtent + { + /// Bytes 0 to 7 Reserved + public byte[] Reserved; + /// Bytes 8 to 11 Start LBA of extent + public uint StartLBA; + /// Bytes 12 to 15 Extent length + public uint LBACount; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/MMC/CPRM.cs b/Aaru.Decoders/SCSI/MMC/CPRM.cs new file mode 100644 index 000000000..b716e30d7 --- /dev/null +++ b/Aaru.Decoders/SCSI/MMC/CPRM.cs @@ -0,0 +1,116 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CPRM.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes CPRM structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Helpers; + +namespace Aaru.Decoders.SCSI.MMC +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class CPRM + { + public static CPRMMediaKeyBlock? DecodeCPRMMediaKeyBlock(byte[] CPRMMKBResponse) + { + if(CPRMMKBResponse == null) + return null; + + var decoded = new CPRMMediaKeyBlock + { + MKBPackData = new byte[CPRMMKBResponse.Length - 4], + DataLength = BigEndianBitConverter.ToUInt16(CPRMMKBResponse, 0), + Reserved = CPRMMKBResponse[2], + TotalPacks = CPRMMKBResponse[3] + }; + + Array.Copy(CPRMMKBResponse, 4, decoded.MKBPackData, 0, CPRMMKBResponse.Length - 4); + + return decoded; + } + + public static string PrettifyCPRMMediaKeyBlock(CPRMMediaKeyBlock? CPRMMKBResponse) + { + if(CPRMMKBResponse == null) + return null; + + CPRMMediaKeyBlock response = CPRMMKBResponse.Value; + + var sb = new StringBuilder(); + + #if DEBUG + if(response.Reserved != 0) + sb.AppendFormat("Reserved = 0x{0:X2}", response.Reserved).AppendLine(); + #endif + sb.AppendFormat("Total number of CPRM Media Key Blocks available to transfer: {0}", response.TotalPacks). + AppendLine(); + + sb.AppendFormat("CPRM Media Key Blocks in hex follows:"); + sb.AppendLine(PrintHex.ByteArrayToHexArrayString(response.MKBPackData, 80)); + + return sb.ToString(); + } + + public static string PrettifyCPRMMediaKeyBlock(byte[] CPRMMKBResponse) + { + CPRMMediaKeyBlock? decoded = DecodeCPRMMediaKeyBlock(CPRMMKBResponse); + + return PrettifyCPRMMediaKeyBlock(decoded); + } + + public struct CPRMMediaKeyBlock + { + /// Bytes 0 to 1 Data Length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved; + /// Byte 3 Number of MKB packs available to transfer + public byte TotalPacks; + /// Byte 4 MKB Packs + public byte[] MKBPackData; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/MMC/DiscInformation.cs b/Aaru.Decoders/SCSI/MMC/DiscInformation.cs new file mode 100644 index 000000000..34a0331bf --- /dev/null +++ b/Aaru.Decoders/SCSI/MMC/DiscInformation.cs @@ -0,0 +1,466 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : DiscInformation.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes MMC GET DISC INFORMATION structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI.MMC +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class DiscInformation + { + public static StandardDiscInformation? Decode000b(byte[] response) + { + if(response.Length < 32) + return null; + + if((response[2] & 0xE0) != 0) + return null; + + var decoded = new StandardDiscInformation + { + DataLength = (ushort)((response[0] << 8) + response[1]) + }; + + if(decoded.DataLength + 2 != response.Length) + return null; + + decoded.DataType = (byte)((response[2] & 0xE0) >> 5); + decoded.Erasable |= (response[2] & 0x10) == 0x10; + decoded.LastSessionStatus = (byte)((response[2] & 0x0C) >> 2); + decoded.DiscStatus = (byte)(response[2] & 0x03); + decoded.FirstTrackNumber = response[3]; + decoded.Sessions = (ushort)((response[9] << 8) + response[4]); + decoded.FirstTrackLastSession = (ushort)((response[10] << 8) + response[5]); + decoded.LastTrackLastSession = (ushort)((response[11] << 8) + response[6]); + + decoded.DID_V |= (response[7] & 0x80) == 0x80; + decoded.DBC_V |= (response[7] & 0x40) == 0x40; + decoded.URU |= (response[7] & 0x20) == 0x20; + decoded.DAC_V |= (response[7] & 0x10) == 0x10; + decoded.Reserved |= (response[7] & 0x08) == 0x08; + decoded.Dbit |= (response[7] & 0x04) == 0x04; + decoded.BGFormatStatus = (byte)(response[7] & 0x03); + + decoded.DiscIdentification = + (uint)((response[12] << 24) + (response[13] << 16) + (response[14] << 8) + response[15]); + + decoded.LastSessionLeadInStartLBA = + (uint)((response[16] << 24) + (response[17] << 16) + (response[18] << 8) + response[19]); + + decoded.LastPossibleLeadOutStartLBA = + (uint)((response[20] << 24) + (response[21] << 16) + (response[22] << 8) + response[23]); + + byte[] temp = new byte[8]; + Array.Copy(response, 24, temp, 0, 8); + Array.Reverse(temp); + decoded.DiscBarcode = BitConverter.ToUInt64(temp, 0); + + if(response.Length < 34) + return null; + + decoded.DiscApplicationCode = response[32]; + decoded.OPCTablesNumber = response[33]; + + if(decoded.OPCTablesNumber <= 0 || + response.Length != (decoded.OPCTablesNumber * 8) + 34) + return decoded; + + decoded.OPCTables = new OPCTable[decoded.OPCTablesNumber]; + + for(int i = 0; i < decoded.OPCTablesNumber; i++) + { + decoded.OPCTables[i].Speed = (ushort)((response[34 + (i * 8) + 0] << 16) + response[34 + (i * 8) + 1]); + + decoded.OPCTables[i].OPCValues = new byte[6]; + Array.Copy(response, 34 + (i * 8) + 2, decoded.OPCTables[i].OPCValues, 0, 6); + } + + return decoded; + } + + public static string Prettify000b(StandardDiscInformation? information) + { + if(information?.DataType != 0) + return null; + + var sb = new StringBuilder(); + + switch(information.Value.DiscType) + { + case 0x00: + sb.AppendLine("Disc type declared as CD-DA or CD-ROM"); + + break; + case 0x10: + sb.AppendLine("Disc type declared as CD-i"); + + break; + case 0x20: + sb.AppendLine("Disc type declared as CD-ROM XA"); + + break; + case 0xFF: + sb.AppendLine("Disc type is undefined"); + + break; + default: + sb.AppendFormat("Unknown disc type {0:X2}h", information.Value.DiscType).AppendLine(); + + break; + } + + switch(information.Value.DiscStatus) + { + case 0: + sb.AppendLine("Disc is empty"); + + break; + case 1: + sb.AppendLine("Disc is incomplete"); + + break; + case 2: + sb.AppendLine("Disc is finalized"); + + break; + } + + if(information.Value.Erasable) + sb.AppendLine("Disc is erasable"); + + switch(information.Value.LastSessionStatus) + { + case 0: + sb.AppendLine("Last session is empty"); + + break; + case 1: + sb.AppendLine("Last session is incomplete"); + + break; + case 2: + sb.AppendLine("Last session is damaged"); + + break; + case 3: + sb.AppendLine("Last session is complete"); + + break; + } + + switch(information.Value.BGFormatStatus) + { + case 1: + sb.AppendLine("Media was being formatted in the background but it is stopped and incomplete"); + + break; + case 2: + sb.AppendLine("Media is currently being formatted in the background"); + + break; + case 3: + sb.AppendLine("Media background formatting has completed"); + + break; + } + + if(information.Value.Dbit) + sb.AppendLine("MRW is dirty"); + + sb.AppendFormat("First track on disc is track {0}", information.Value.FirstTrackNumber).AppendLine(); + sb.AppendFormat("Disc has {0} sessions", information.Value.Sessions).AppendLine(); + + sb.AppendFormat("First track in last session is track {0}", information.Value.FirstTrackLastSession). + AppendLine(); + + sb.AppendFormat("Last track in last session is track {0}", information.Value.LastTrackLastSession). + AppendLine(); + + sb.AppendFormat("Last session Lead-In address is {0} (as LBA) or {1:X2}:{2:X2}:{3:X2}", + information.Value.LastSessionLeadInStartLBA, + (information.Value.LastSessionLeadInStartLBA & 0xFF0000) >> 16, + (information.Value.LastSessionLeadInStartLBA & 0xFF00) >> 8, + information.Value.LastSessionLeadInStartLBA & 0xFF).AppendLine(); + + sb.AppendFormat("Last possible Lead-Out address is {0} (as LBA) or {1:X2}:{2:X2}:{3:X2}", + information.Value.LastPossibleLeadOutStartLBA, + (information.Value.LastPossibleLeadOutStartLBA & 0xFF0000) >> 16, + (information.Value.LastPossibleLeadOutStartLBA & 0xFF00) >> 8, + information.Value.LastPossibleLeadOutStartLBA & 0xFF).AppendLine(); + + sb.AppendLine(information.Value.URU ? "Disc is defined for unrestricted use" + : "Disc is defined for restricted use"); + + if(information.Value.DID_V) + sb.AppendFormat("Disc ID: {0:X6}", information.Value.DiscIdentification & 0x00FFFFFF).AppendLine(); + + if(information.Value.DBC_V) + sb.AppendFormat("Disc barcode: {0:X16}", information.Value.DiscBarcode).AppendLine(); + + if(information.Value.DAC_V) + sb.AppendFormat("Disc application code: {0}", information.Value.DiscApplicationCode).AppendLine(); + + if(information.Value.OPCTables == null) + return sb.ToString(); + + foreach(OPCTable table in information.Value.OPCTables) + sb.AppendFormat("OPC values for {0}Kbit/sec.: {1}, {2}, {3}, {4}, {5}, {6}", table.Speed, + table.OPCValues[0], table.OPCValues[1], table.OPCValues[2], table.OPCValues[3], + table.OPCValues[4], table.OPCValues[5]).AppendLine(); + + return sb.ToString(); + } + + public static TrackResourcesInformation? Decode001b(byte[] response) + { + if(response.Length != 12) + return null; + + if((response[2] & 0xE0) != 0x20) + return null; + + var decoded = new TrackResourcesInformation + { + DataLength = (ushort)((response[0] << 8) + response[1]) + }; + + if(decoded.DataLength + 2 != response.Length) + return null; + + decoded.DataType = (byte)((response[2] & 0xE0) >> 5); + decoded.MaxTracks = (ushort)((response[4] << 8) + response[5]); + decoded.AssignedTracks = (ushort)((response[6] << 8) + response[7]); + decoded.MaxAppendableTracks = (ushort)((response[8] << 8) + response[9]); + decoded.AppendableTracks = (ushort)((response[10] << 8) + response[11]); + + return decoded; + } + + public static string Prettify001b(TrackResourcesInformation? information) + { + if(information?.DataType != 1) + return null; + + var sb = new StringBuilder(); + + sb.AppendFormat("{0} maximum possible tracks on the disc", information.Value.MaxTracks).AppendLine(); + sb.AppendFormat("{0} assigned tracks on the disc", information.Value.AssignedTracks).AppendLine(); + + sb.AppendFormat("{0} maximum possible appendable tracks on the disc", information.Value.AppendableTracks). + AppendLine(); + + sb.AppendFormat("{0} current appendable tracks on the disc", information.Value.MaxAppendableTracks). + AppendLine(); + + return sb.ToString(); + } + + public static POWResourcesInformation? Decode010b(byte[] response) + { + if(response.Length != 16) + return null; + + if((response[2] & 0xE0) != 0x40) + return null; + + var decoded = new POWResourcesInformation + { + DataLength = (ushort)((response[0] << 8) + response[1]) + }; + + if(decoded.DataLength + 2 != response.Length) + return null; + + decoded.DataType = (byte)((response[2] & 0xE0) >> 5); + + decoded.RemainingPOWReplacements = + (ushort)((response[4] << 24) + (response[5] << 16) + (response[6] << 8) + response[7]); + + decoded.RemainingPOWReallocation = + (ushort)((response[8] << 24) + (response[9] << 16) + (response[10] << 8) + response[11]); + + decoded.RemainingPOWUpdates = + (ushort)((response[12] << 24) + (response[13] << 16) + (response[14] << 8) + response[15]); + + return decoded; + } + + public static string Prettify010b(POWResourcesInformation? information) + { + if(information?.DataType != 1) + return null; + + var sb = new StringBuilder(); + + sb.AppendFormat("{0} remaining POW replacements", information.Value.RemainingPOWReplacements).AppendLine(); + + sb.AppendFormat("{0} remaining POW reallocation map entries", information.Value.RemainingPOWReallocation). + AppendLine(); + + sb.AppendFormat("{0} remaining POW updates", information.Value.RemainingPOWUpdates).AppendLine(); + + return sb.ToString(); + } + + public static string Prettify(byte[] response) + { + if(response == null) + return null; + + if(response.Length < 12) + return null; + + switch(response[2] & 0xE0) + { + case 0x00: return Prettify000b(Decode000b(response)); + case 0x20: return Prettify001b(Decode001b(response)); + case 0x40: return Prettify010b(Decode010b(response)); + } + + return null; + } + + public struct StandardDiscInformation + { + /// Bytes 0 to 1 32 + OPCTablesNumber*8 + public ushort DataLength; + /// Byte 2, bits 7 to 5 000b + public byte DataType; + /// Byte 2, bit 4 If set, disc is erasable + public bool Erasable; + /// Byte 2, bits 3 to 2 Status of last session + public byte LastSessionStatus; + /// Byte 2, bits 1 to 0 Status of disc + public byte DiscStatus; + /// Byte 3 Number of logical track that contains LBA 0 + public byte FirstTrackNumber; + /// Byte 9 (MSB) and byte 4 (LSB) Number of sessions + public ushort Sessions; + /// Byte 10 (MSB) and byte 5 (LSB) Number of first track in last session + public ushort FirstTrackLastSession; + /// Byte 11 (MSB) and byte 6 (LSB) Number of last track in last session + public ushort LastTrackLastSession; + /// Byte 7, bit 7 If set, DiscIdentification is valid + public bool DID_V; + /// Byte 7, bit 6 If set, DiscBarcode is valid + public bool DBC_V; + /// Byte 7, bit 5 If set, disc is unrestricted + public bool URU; + /// Byte 7, bit 4 If set DiscApplicationCode is valid + public bool DAC_V; + /// Byte 7, bit 3 Reserved + public bool Reserved; + /// Byte 7, bit 2 Copy of dirty bit from MRW status + public bool Dbit; + /// Byte 7, bits 1 to 0 Background format status + public byte BGFormatStatus; + /// Byte 8 Disc type code + public byte DiscType; + /// Bytes 12 to 15 Disc identification number from PMA + public uint DiscIdentification; + /// Bytes 16 to 19 Last Session Lead-in Start Address (MSF for CD, LBA for others) + public uint LastSessionLeadInStartLBA; + /// Bytes 20 to 23 Last Possible Lead-out Start Address (MSF for CD, LBA for others) + public uint LastPossibleLeadOutStartLBA; + /// Bytes 24 to 31 Disc barcode + public ulong DiscBarcode; + /// Byte 32 Disc application code + public byte DiscApplicationCode; + /// Byte 33 How many OPC tables are + public byte OPCTablesNumber; + /// Bytes 34 to end OPC tables (8 bytes each) + public OPCTable[] OPCTables; + } + + public struct OPCTable + { + /// Bytes 0 to 1 kilobytes/sec this OPC table applies to + public ushort Speed; + /// Bytes 2 to 7 OPC values + public byte[] OPCValues; + } + + public struct TrackResourcesInformation + { + /// Bytes 0 to 1 10 + public ushort DataLength; + /// Byte 2, bits 7 to 5 001b + public byte DataType; + /// Byte 2, bits 4 to 0 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to 5 Maximum possible number of the tracks on the disc + public ushort MaxTracks; + /// Bytes 6 to 7 Number of the assigned tracks on the disc + public ushort AssignedTracks; + /// Bytes 8 to 9 Maximum possible number of appendable tracks on the disc + public ushort MaxAppendableTracks; + /// Bytes 10 to 11 Current number of appendable tracks on the disc + public ushort AppendableTracks; + } + + public struct POWResourcesInformation + { + /// Bytes 0 to 1 14 + public ushort DataLength; + /// Byte 2, bits 7 to 5 010b + public byte DataType; + /// Byte 2, bits 4 to 0 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Bytes 4 to 7 Remaining POW replacements + public uint RemainingPOWReplacements; + /// Bytes 8 to 11 Remaining POW reallocation map entries + public uint RemainingPOWReallocation; + /// Bytes 12 to 15 Number of remaining POW updates + public uint RemainingPOWUpdates; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/MMC/Enums.cs b/Aaru.Decoders/SCSI/MMC/Enums.cs new file mode 100644 index 000000000..eefbb8345 --- /dev/null +++ b/Aaru.Decoders/SCSI/MMC/Enums.cs @@ -0,0 +1,77 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Enums.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Contains various SCSI MMC enumerations. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.Decoders.SCSI.MMC +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal")] + public enum FormatLayerTypeCodes : ushort + { + CDLayer = 0x0008, DVDLayer = 0x0010, BDLayer = 0x0040, + HDDVDLayer = 0x0050 + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal")] + public enum SessionStatusCodes : byte + { + Empty = 0x00, Incomplete = 0x01, ReservedOrDamaged = 0x02, + Complete = 0x03 + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal")] + public enum DiscStatusCodes : byte + { + Empty = 0x00, Incomplete = 0x01, Finalized = 0x02, + Others = 0x03 + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal")] + public enum BGFormatStatusCodes : byte + { + NoFormattable = 0x00, IncompleteBackgroundFormat = 0x01, BackgroundFormatInProgress = 0x02, + FormatComplete = 0x03 + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal")] + public enum DiscTypeCodes : byte + { + /// Also valid for CD-DA, DVD and BD + CDROM = 0x00, CDi = 0x10, CDROMXA = 0x20, Undefined = 0xFF + } + + public enum LayerJumpRecordingStatus : byte + { + Incremental = 0, Unspecified = 1, Manual = 2, + RegularInterval = 3 + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/MMC/Features.cs b/Aaru.Decoders/SCSI/MMC/Features.cs new file mode 100644 index 000000000..184b6a053 --- /dev/null +++ b/Aaru.Decoders/SCSI/MMC/Features.cs @@ -0,0 +1,4893 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Features.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MMC feature structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.CommonTypes.Structs.Devices.SCSI; +using Aaru.Helpers; + +// ReSharper disable MemberCanBePrivate.Global + +namespace Aaru.Decoders.SCSI.MMC +{ + /// MMC Feature enumeration + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum FeatureNumber : ushort + { + /// Lists all profiles + ProfileList = 0x0000, + /// Mandatory behaviour + Core = 0x0001, + /// Operational changes + Morphing = 0x0002, + /// Removable medium + Removable = 0x0003, + /// Ability to control write protection status + WriteProtect = 0x0004, + /// Ability to read sectors with random addressing + RandomRead = 0x0010, + /// Reads on OSTA Multi-Read + MultiRead = 0x001D, + /// Able to read CD structures + CDRead = 0x001E, + /// Able to read DVD structures + DVDRead = 0x001F, + /// Ability to write sectors with random addressing + RandomWrite = 0x0020, + /// Ability to sequentially write + IncrementalWrite = 0x0021, + /// Support for media that requires erase before write + SectorErasable = 0x0022, + /// Supports formatting media + Formattable = 0x0023, + /// Ability to provide defect-free space + HardwareDefectMgmt = 0x0024, + /// Supports for write-once media in random order + WriteOnce = 0x0025, + /// Supports for media that shall be written from blocking boundaries + RestrictedOverwrite = 0x0026, + /// Supports high speed CD-RW + CDRWCAV = 0x0027, + /// Read and optionally write MRW + MRW = 0x0028, + /// Ability to control RECOVERED ERROR reporting + EnDefectReport = 0x0029, + /// Ability to recognize, read and optionally write DVD+RW + DVDRWPlus = 0x002A, + /// Ability to read DVD+R + DVDRPlus = 0x002B, RigidOverWrite = 0x002C, + /// Ability to write CD in Track-at-Once + CDTAO = 0x002D, + /// Ability to write CD in Session-at-Once or RAW + CDMastering = 0x002E, + /// Ability to write DVD structures + DVDRWrite = 0x002F, + /// Ability to read DDCD + DDCD = 0x0030, + /// Ability to write DDCD-R + DDCDR = 0x0031, + /// Ability to write DDCD-RW + DDCDRW = 0x0032, + /// Ability to record in layer jump mode + LayerJump = 0x0033, + /// Ability to perform Layer Jump recording on Rigid Restricted Overwrite + LJRigid = 0x0034, + /// Ability to stop the long immediate operation + StopLong = 0x0035, + /// Ability to report CD-RW media sub-types supported for write + CDRWMediaWrite = 0x0037, + /// Logical block overwrite service on BD-R formatted as SRM+POW + BDRPOW = 0x0038, + /// Ability to read DVD+RW DL + DVDRWDLPlus = 0x003A, + /// Ability to read DVD+R DL + DVDRDLPlus = 0x003B, + /// Ability to read BD discs + BDRead = 0x0040, + /// Ability to write BD discs + BDWrite = 0x0041, + /// Timely, Safe Recording + TSR = 0x0042, + /// Ability to read HD DVD + HDDVDRead = 0x0050, + /// Ability to write HD DVD + HDDVDWrite = 0x0051, + /// Ability to write HD DVD-RW fragmented + HDDVDRWFragment = 0x0052, + /// Supports some Hybrid Discs + Hybrid = 0x0080, + /// Host and device directed power management + PowerMgmt = 0x0100, + /// Supports S.M.A.R.T. + SMART = 0x0101, + /// Single machanism multiple disc changer + Changer = 0x0102, + /// Ability to play CD audio to an analogue output + CDAudioExt = 0x0103, + /// Ability to accept new microcode + MicrocodeUpgrade = 0x0104, + /// Ability to respond to all commands within a specific time + Timeout = 0x0105, + /// Supports DVD CSS/CPPM + CSS = 0x0106, + /// Ability to read and write using host requested performance parameters + RTS = 0x0107, + /// Drive has a unique identifier + DriveSerial = 0x0108, + /// Ability to return unique Media Serial Number + MediaSerial = 0x0109, + /// Ability to read and/or write DCBs + DCBs = 0x010A, + /// Supports DVD CPRM + CPRM = 0x010B, + /// Firmware creation date report + FirmwareInfo = 0x010C, + /// Ability to decode and optionally encode AACS + AACS = 0x010D, + /// Ability to perform DVD CSS managed recording + CSSManagedRec = 0x010E, + /// Ability to decode and optionally encode VCPS + VCPS = 0x0110, + /// Supports SecurDisc + SecurDisc = 0x0113, + /// TCG Optical Security Subsystem Class + OSSC = 0x0142 + } + + /// MMC Profile enumeration + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum ProfileNumber : ushort + { + /// Not to use + Reserved = 0x0000, + /// Non-removable disk profile + NonRemovable = 0x0001, + /// Rewritable with removable media + Removable = 0x0002, + /// Magneto-Optical with sector erase + MOErasable = 0x0003, + /// Optical write once + OpticalWORM = 0x0004, + /// Advance Storage - Magneto-Optical + ASMO = 0x0005, + /// Read-only Compact Disc + CDROM = 0x0008, + /// Write-once Compact Disc + CDR = 0x0009, + /// Re-writable Compact Disc + CDRW = 0x000A, + /// Read-only DVD + DVDROM = 0x0010, + /// Write-once sequentially recorded DVD-R + DVDRSeq = 0x0011, + /// DVD-RAM + DVDRAM = 0x0012, + /// Restricted overwrite DVD-RW + DVDRWRes = 0x0013, + /// Sequential recording DVD-RW + DVDRWSeq = 0x0014, + /// Sequential recording DVD-R DL + DVDRDLSeq = 0x0015, + /// Layer jump recording DVD-R DL + DVDRDLJump = 0x0016, + /// DVD-RW DL + DVDRWDL = 0x0017, + /// DVD-Download + DVDDownload = 0x0018, + /// DVD+RW + DVDRWPlus = 0x001A, + /// DVD+R + DVDRPlus = 0x001B, + /// DDCD-ROM + DDCDROM = 0x0020, + /// DDCD-R + DDCDR = 0x0021, + /// DDCD-RW + DDCDRW = 0x0022, + /// DVD+RW DL + DVDRWDLPlus = 0x002A, + /// DVD+R DL + DVDRDLPlus = 0x002B, + /// BD-ROM + BDROM = 0x0040, + /// BD-R SRM + BDRSeq = 0x0041, + /// BD-R RRM + BDRRdm = 0x0042, + /// BD-RE + BDRE = 0x0043, + /// HD DVD-ROM + HDDVDROM = 0x0050, + /// HD DVD-R + HDDVDR = 0x0051, + /// HD DVD-RAM + HDDVDRAM = 0x0052, + /// HD DVD-RW + HDDVDRW = 0x0053, + /// HD DVD-R DL + HDDVDRDL = 0x0058, + /// HD DVD-RW DL + HDDVDRWDL = 0x005A, + /// HDBurn CD-ROM + HDBURNROM = 0x0080, + /// HDBurn CD-R + HDBURNR = 0x0081, + /// HDBurn CD-RW + HDBURNRW = 0x0082, + /// Drive does not conform to any profiles + Unconforming = 0xFFFF + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Profile + { + public ProfileNumber Number; + public bool Current; + } + + /// Profile List Feature (0000h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0000 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// All supported profiles + public Profile[] Profiles; + } + + /// Core Feature (0001h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0001 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Currently in-use physical interface standard + public PhysicalInterfaces PhysicalInterfaceStandard; + /// Supports EVPD, Page Code and 16-bit Allocation Length as defined in SPC-3 + public bool INQ2; + /// Supports Device Busy Event + public bool DBE; + } + + /// Morphing Feature (0002h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0002 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Supports Operational Change Request/Nofitication Class Events of GET EVENT/STATUS NOTIFICATION + public bool OCEvent; + /// Supports asynchronous GET EVENT/STATUS NOTIFICATION + public bool Async; + } + + /// Removable Medium Feature (0003h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0003 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Mechanism type + public byte LoadingMechanismType; + /// Drive is able to load the medium + public bool Load; + /// Device can eject medium + public bool Eject; + /// Device starts in medium ejection/insertion allow + public bool PreventJumper; + /// Reports Device Busy Class events during medium loading/unloading + public bool DBML; + /// Medium is currently locked + public bool Lock; + } + + /// Write Protect Feature (0004h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0004 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Drive can read/write Disc Write Protect PAC on BD-R/-RE media + public bool DWP; + /// Supports reading/writing Write Inhibit DCB on DVD+RW media. + public bool WDCB; + /// Supports PWP status + public bool SPWP; + /// Supports SWPP bit of mode page 1Dh + public bool SSWPP; + } + + /// Random Readable Feature (0010h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0010 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Bytes per logical block + public uint LogicalBlockSize; + /// Number of logical blocks per device readable unit + public ushort Blocking; + /// Read/Write Error Recovery page is present + public bool PP; + } + + /// Multi-Read Feature (001Dh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_001D + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + } + + /// CD Read Feature (001Eh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_001E + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Supports DAP bit in READ CD and READ CD MSF + public bool DAP; + /// Supports C2 Error Pointers + public bool C2; + /// Can read CD-Text with READ TOC/PMA/ATIP + public bool CDText; + } + + /// DVD Read Feature (001Fh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_001F + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Compliant with DVD Multi Drive Read-only specifications + public bool MULTI110; + /// Supports reading all DVD-RW DL + public bool DualRW; + /// Supports reading all DVD-R DL including remapping + public bool DualR; + } + + /// Random Writable Feature (0020h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0020 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Last logical block address + public uint LastLBA; + /// Bytes per logical block + public uint LogicalBlockSize; + /// Number of logical blocks per device readable unit + public ushort Blocking; + /// Read/Write Error Recovery page is present + public bool PP; + } + + /// Incremental Streaming Writable Feature (0021h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0021 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Bitmask of supported data types + public ushort DataTypeSupported; + /// Can report Track Resources Information of READ DISC INFORMATION + public bool TRIO; + /// Supports Address Mode in RESERVE TRACK + public bool ARSV; + /// Zero loss linking + public bool BUF; + /// Logical blocks per link + public byte[] LinkSizes; + } + + /// Sector Erasable Feature (0022h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0022 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + } + + /// Formattable Feature (0023h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0023 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Supports formatting BD-RE without spare area + public bool RENoSA; + /// Supports expansion of the spare area on BD-RE + public bool Expand; + /// Supports FORMAT type 30h sub-type 11b + public bool QCert; + /// Supports FORMAT type 30h sub-type 10b + public bool Cert; + /// Supports FORMAT type 18h + public bool FRF; + /// Supports FORMAT type 00h/32h sub-type 10b on BD-R + public bool RRM; + } + + /// Hardware Defect Management Feature (0024h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0024 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Supports READ DISC STRUCTURE with Format Code 0Ah (Spare Area Information) + public bool SSA; + } + + /// Write Once Feature (0025h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0025 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Bytes per logical block + public uint LogicalBlockSize; + /// Number of logical blocks per device readable unit + public ushort Blocking; + /// Read/Write Error Recovery page is present + public bool PP; + } + + /// Restricted Overwrite Feature (0026h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0026 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + } + + /// CD-RW CAV Write Feature (0027h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0027 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + } + + /// MRW Feature (0028h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0028 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Can read DVD+MRW discs + public bool DVDPRead; + /// Can write DVD+MRW discs + public bool DVDPWrite; + /// Can format and write to CD-MRW discs + public bool Write; + } + + /// Enhanced Defect Reporting Feature (0029h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0029 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Supports DRT-DM + public bool DRTDM; + /// Maximum number of DBI cache zones device can handle separately + public byte DBICacheZones; + /// Number of entries in worst case to case DBI overflow + public ushort Entries; + } + + /// DVD+RW Feature (002Ah) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_002A + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Can format DVD+RW discs + public bool Write; + /// FORMAT UNIT supports quick start formatting + public bool QuickStart; + /// Drive only supports read compatibility stop + public bool CloseOnly; + } + + /// DVD+R Feature (002Bh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_002B + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Can write DVD+R + public bool Write; + } + + /// Rigid Restricted Overwrite Feature (002Ch) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_002C + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Can generate Defect Status Data during formatting + public bool DSDG; + /// Can read Defect Status Data recorded on medium + public bool DSDR; + /// Supports writing on an intermediate state Session and quick formatting + public bool Intermediate; + /// Supports BLANK command types 00h and 01h + public bool Blank; + } + + /// CD Track at Once Feature (002Dh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_002D + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Supports zero loss linking + public bool BUF; + /// Supports writing R-W subchannels in raw mode + public bool RWRaw; + /// Supports writing R-W subchannels in packed mode + public bool RWPack; + /// Can perform test writes + public bool TestWrite; + /// Supports overwriting a TAO track with another + public bool CDRW; + /// Can write R-W subchannels with user provided data + public bool RWSubchannel; + /// Bitmask of supported data types + public ushort DataTypeSupported; + } + + /// CD Mastering (Session at Once) Feature (002Eh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_002E + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Supports zero loss linking + public bool BUF; + /// Can write in Session at Once + public bool SAO; + /// Can write multi-session in RAW + public bool RAWMS; + /// Can write in RAW + public bool RAW; + /// Can perform test writes + public bool TestWrite; + /// Can overwrite previously recorded data + public bool CDRW; + /// Can write R-W subchannels with user provided data + public bool RW; + /// Maximum length of a Cue Sheet for Session at Once + public uint MaxCueSheet; + } + + /// DVD-R/-RW Write Feature (002Fh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_002F + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Buffer Under-run protection + public bool BUF; + /// Supports writing DVD-R DL + public bool RDL; + /// Test write + public bool TestWrite; + /// Can write and erase DVD-RW + public bool DVDRW; + } + + /// Double Density CD Read Feature (0030h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0030 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + } + + /// Double Density CD-R Write Feature (0031h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0031 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Test write + public bool TestWrite; + } + + /// Double Density CD-RW Write Feature (0032h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0032 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Supports quick formatting + public bool Intermediate; + /// Supports BLANK command + public bool Blank; + } + + /// Layer Jump Recording Feature (0033h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0033 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + public byte[] LinkSizes; + } + + /// Stop Long Operation Feature (0035h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0035 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + } + + /// CD-RW Media Write Support Feature (0037h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0037 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Bitmask of supported CD-RW media sub-types + public byte SubtypeSupport; + } + + /// BD-R Pseudo-Overwrite (POW) Feature (0038h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0038 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + } + + /// DVD+RW Dual Layer Feature (003Ah) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_003A + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Can format DVD+RW DL discs + public bool Write; + /// FORMAT UNIT supports quick start formatting + public bool QuickStart; + /// Drive only supports read compatibility stop + public bool CloseOnly; + } + + /// DVD+R Dual Layer Feature (003Bh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_003B + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Can format DVD+R DL discs + public bool Write; + /// FORMAT UNIT supports quick start formatting + public bool QuickStart; + /// Drive only supports read compatibility stop + public bool CloseOnly; + } + + /// BD Read Feature (0040h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0040 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Can read BCA + public bool BCA; + /// Supports reading BD-RE Ver.2 + public bool RE2; + /// Supports reading BD-RE Ver.1 + public bool RE1; + /// Obsolete + public bool OldRE; + /// Supports reading BD-R Ver.1 + public bool R; + /// Obsolete + public bool OldR; + /// Supports reading BD-ROM Ver.1 + public bool ROM; + /// Obsolete + public bool OldROM; + } + + /// BD Write Feature (0041h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0041 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Supports verify not required + public bool SVNR; + /// Supports writing BD-RE Ver.2 + public bool RE2; + /// Supports writing BD-RE Ver.1 + public bool RE1; + /// Obsolete + public bool OldRE; + /// Supports writing BD-R Ver.1 + public bool R; + /// Obsolete + public bool OldR; + } + + /// TSR Feature (0042h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0042 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + } + + /// HD DVD Read Feature (0050h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0050 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Can read HD DVD-R + public bool HDDVDR; + /// Can read HD DVD-RAM + public bool HDDVDRAM; + } + + /// HD DVD Write Feature (0051h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0051 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Can write HD DVD-R + public bool HDDVDR; + /// Can write HD DVD-RAM + public bool HDDVDRAM; + } + + /// Hybrid Disc Feature (0080h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0080 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Reset immunity + public bool RI; + } + + /// Power Management Feature (0100h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0100 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + } + + /// S.M.A.R.T. Feature (0101h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0101 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Mode Page 1Ch is present + public bool PP; + } + + /// Embedded Changer Feature (0102h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0102 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Side change capable + public bool SCC; + /// Supports Disc Present + public bool SDP; + /// Number of slots - 1 + public byte HighestSlotNumber; + } + + /// CD Audio External Play Feature (0103h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0103 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Supports SCAN command + public bool Scan; + /// Separate Channel Mute + public bool SCM; + /// Separate Volume + public bool SV; + /// Number of volume levels + public ushort VolumeLevels; + } + + /// Microcode Upgrade Feature (0104h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0104 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Supports validating 5-bit mode field of READ BUFFER and WRITE BUFFER commands. + public bool M5; + } + + /// Time-Out Feature (0105h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0105 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Supports G3Enable bit and Group3 Timeout field in Mode Page 1Dh + public bool Group3; + /// Indicates a unit of block length, in sectors, corresponding to increase a unit of Group 3 time unit + public ushort UnitLength; + } + + /// DVD-CSS Feature (0106h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0106 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// CSS version + public byte CSSVersion; + } + + /// Real Time Streaming Feature (0107h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0107 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Supports Set Minimum Performance bit in SET STREAMING + public bool SMP; + /// Supports READ BUFFER CAPACITY with block bit set + public bool RBCB; + /// Supports SET CD SPEED + public bool SCS; + /// Has Mode Page 2Ah with Speed Performance Descriptors + public bool MP2A; + /// Supports type 03h of GET PERFORMANCE + public bool WSPD; + /// Supports stream recording + public bool SW; + } + + /// Drive serial number (0108h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0108 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Drive serial number + public string Serial; + } + + /// Media Serial Number Feature (0109h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0109 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + } + + /// Disc Control Blocks Feature (010Ah) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_010A + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + public uint[] DCBs; + } + + /// DVD CPRM Feature (010Bh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_010B + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// CPRM version + public byte CPRMVersion; + } + + /// Firmware Information Feature (010Ch) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_010C + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + public ushort Century; + public ushort Year; + public ushort Month; + public ushort Day; + public ushort Hour; + public ushort Minute; + public ushort Second; + } + + /// AACS Feature (010Dh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_010D + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Drive supports reading drive certificate + public bool RDC; + /// Drive can read media key block of CPRM + public bool RMC; + /// Drive can write bus encrypted blocks + public bool WBE; + /// Drive supports bus encryption + public bool BEC; + /// Drive supports generating the binding nonce + public bool BNG; + /// Blocks required to store the binding nonce for the media + public byte BindNonceBlocks; + /// Maximum number of AGIDs supported concurrently + public byte AGIDs; + /// AACS version + public byte AACSVersion; + } + + /// DVD CSS Managed Recording Feature (010Eh) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_010E + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Maximum number of Scramble Extent information entries in a single SEND DISC STRUCTURE + public byte MaxScrambleExtent; + } + + /// SecurDisc Feature (0113h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0113 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + } + + /// OSSC Feature (0142h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0142 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + /// Supports PSA updates on write-once media + public bool PSAU; + /// Supports linked OSPBs + public bool LOSPB; + /// Restricted to recording only OSSC disc format + public bool ME; + public ushort[] Profiles; + } + + /// VCPS Feature (0110h) + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct Feature_0110 + { + /// Feature version + public byte Version; + /// Feature is persistent + public bool Persistent; + /// Feature is currently in use + public bool Current; + } + + public static class Features + { + public static Feature_0000? Decode_0000(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 4) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0000) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0000(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + int offset = 4; + List listProfiles = new List(); + + while(offset < feature.Length) + { + var prof = new Profile + { + Number = (ProfileNumber)((feature[offset] << 8) + feature[offset + 1]) + }; + + prof.Current |= (feature[offset + 2] & 0x01) == 0x01; + listProfiles.Add(prof); + offset += 4; + } + + decoded.Profiles = listProfiles.ToArray(); + + return decoded; + } + + public static Feature_0001? Decode_0001(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0001) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0001(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.PhysicalInterfaceStandard = + (PhysicalInterfaces)((feature[4] << 24) + (feature[5] << 16) + (feature[6] << 8) + feature[7]); + + if(decoded.Version >= 1 && + feature.Length >= 12) + decoded.DBE |= (feature[8] & 0x01) == 0x01; + + if(decoded.Version >= 2 && + feature.Length >= 12) + decoded.INQ2 |= (feature[8] & 0x02) == 0x02; + + return decoded; + } + + public static Feature_0002? Decode_0002(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0002) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0002(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.Async |= (feature[4] & 0x01) == 0x01; + + if(decoded.Version >= 1) + decoded.OCEvent |= (feature[4] & 0x02) == 0x02; + + return decoded; + } + + public static Feature_0003? Decode_0003(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0003) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0003(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.LoadingMechanismType = (byte)((feature[4] & 0xE0) >> 5); + decoded.Eject |= (feature[4] & 0x08) == 0x08; + decoded.PreventJumper |= (feature[4] & 0x04) == 0x04; + decoded.Lock |= (feature[4] & 0x01) == 0x01; + + if(decoded.Version < 2) + return decoded; + + decoded.Load |= (feature[4] & 0x10) == 0x10; + decoded.DBML |= (feature[4] & 0x02) == 0x02; + + return decoded; + } + + public static Feature_0004? Decode_0004(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0004) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0004(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.SPWP |= (feature[4] & 0x02) == 0x02; + decoded.SSWPP |= (feature[4] & 0x01) == 0x01; + + if(decoded.Version >= 1) + decoded.WDCB |= (feature[4] & 0x04) == 0x04; + + if(decoded.Version >= 2) + decoded.DWP |= (feature[4] & 0x08) == 0x08; + + return decoded; + } + + public static Feature_0010? Decode_0010(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 12) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0010) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0010(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.LogicalBlockSize = (uint)((feature[4] << 24) + (feature[5] << 16) + (feature[6] << 8) + feature[7]); + + decoded.Blocking = (ushort)((feature[8] << 8) + feature[9]); + + decoded.PP |= (feature[10] & 0x01) == 0x01; + + return decoded; + } + + public static Feature_001D? Decode_001D(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 4) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x001D) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_001D(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + return decoded; + } + + public static Feature_001E? Decode_001E(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x001E) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_001E(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + if(decoded.Version >= 1) + { + decoded.C2 |= (feature[4] & 0x02) == 0x02; + decoded.CDText |= (feature[4] & 0x01) == 0x01; + } + + if(decoded.Version >= 2) + decoded.DAP |= (feature[4] & 0x80) == 0x80; + + return decoded; + } + + public static Feature_001F? Decode_001F(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 4) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x001F) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_001F(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + if(decoded.Version >= 2 && + feature.Length >= 8) + { + decoded.MULTI110 |= (feature[4] & 0x01) == 0x01; + decoded.DualR |= (feature[6] & 0x01) == 0x01; + } + + // TODO: Check this + if(decoded.Version >= 2 && + feature.Length >= 8) + decoded.DualRW |= (feature[6] & 0x02) == 0x02; + + return decoded; + } + + public static Feature_0020? Decode_0020(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 16) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0020) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0020(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + if(decoded.Version < 1) + return decoded; + + decoded.LastLBA = (uint)((feature[4] << 24) + (feature[5] << 16) + (feature[6] << 8) + feature[7]); + + decoded.LogicalBlockSize = + (uint)((feature[8] << 24) + (feature[9] << 16) + (feature[10] << 8) + feature[11]); + + decoded.Blocking = (ushort)((feature[12] << 8) + feature[13]); + decoded.PP |= (feature[14] & 0x01) == 0x01; + + return decoded; + } + + public static Feature_0021? Decode_0021(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0021) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0021(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + if(decoded.Version >= 1) + { + decoded.DataTypeSupported = (ushort)((feature[4] << 8) + feature[5]); + decoded.BUF |= (feature[6] & 0x01) == 0x01; + decoded.LinkSizes = new byte[feature[7]]; + + if(feature.Length > feature[7] + 8) + Array.Copy(feature, 8, decoded.LinkSizes, 0, feature[7]); + } + + if(decoded.Version < 3) + return decoded; + + decoded.TRIO |= (feature[6] & 0x04) == 0x04; + decoded.ARSV |= (feature[6] & 0x02) == 0x02; + + return decoded; + } + + public static Feature_0022? Decode_0022(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 4) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0022) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0022(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + return decoded; + } + + public static Feature_0023? Decode_0023(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 4) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0023) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0023(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + if(decoded.Version >= 1 && + feature.Length >= 12) + { + decoded.RENoSA |= (feature[4] & 0x08) == 0x08; + decoded.Expand |= (feature[4] & 0x04) == 0x04; + decoded.QCert |= (feature[4] & 0x02) == 0x02; + decoded.Cert |= (feature[4] & 0x01) == 0x01; + decoded.RRM |= (feature[8] & 0x01) == 0x01; + } + + if(decoded.Version >= 2 && + feature.Length >= 12) + decoded.FRF |= (feature[4] & 0x80) == 0x80; + + return decoded; + } + + public static Feature_0024? Decode_0024(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 4) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0024) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0024(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + if(decoded.Version >= 1 && + feature.Length >= 8) + decoded.SSA |= (feature[4] & 0x80) == 0x80; + + return decoded; + } + + public static Feature_0025? Decode_0025(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 12) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0025) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0025(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.LogicalBlockSize = (uint)((feature[4] << 24) + (feature[5] << 16) + (feature[6] << 8) + feature[7]); + + decoded.Blocking = (ushort)((feature[8] << 8) + feature[9]); + + decoded.PP |= (feature[10] & 0x01) == 0x01; + + return decoded; + } + + public static Feature_0026? Decode_0026(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 4) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0026) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0026(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + return decoded; + } + + public static Feature_0027? Decode_0027(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0027) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0027(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + return decoded; + } + + public static Feature_0028? Decode_0028(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0028) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0028(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.Write |= (feature[4] & 0x01) == 0x01; + + if(decoded.Version < 1) + return decoded; + + decoded.DVDPWrite |= (feature[4] & 0x04) == 0x04; + decoded.DVDPRead |= (feature[4] & 0x02) == 0x02; + + return decoded; + } + + public static Feature_0029? Decode_0029(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0029) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0029(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.DRTDM |= (feature[4] & 0x01) == 0x01; + decoded.DBICacheZones = feature[5]; + decoded.Entries = (ushort)((feature[6] << 8) + feature[7]); + + return decoded; + } + + public static Feature_002A? Decode_002A(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x002A) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_002A(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.Write |= (feature[4] & 0x01) == 0x01; + decoded.CloseOnly |= (feature[5] & 0x01) == 0x01; + + if(decoded.Version >= 1) + decoded.QuickStart |= (feature[5] & 0x02) == 0x02; + + return decoded; + } + + public static Feature_002B? Decode_002B(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x002B) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_002B(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.Write |= (feature[4] & 0x01) == 0x01; + + return decoded; + } + + public static Feature_002C? Decode_002C(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x002C) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_002C(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.DSDG |= (feature[4] & 0x08) == 0x08; + decoded.DSDR |= (feature[4] & 0x04) == 0x04; + decoded.Intermediate |= (feature[4] & 0x02) == 0x02; + decoded.Blank |= (feature[4] & 0x01) == 0x01; + + return decoded; + } + + public static Feature_002D? Decode_002D(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x002D) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_002D(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.TestWrite |= (feature[4] & 0x04) == 0x04; + decoded.CDRW |= (feature[4] & 0x02) == 0x02; + decoded.RWSubchannel |= (feature[4] & 0x01) == 0x01; + decoded.DataTypeSupported = (ushort)((feature[6] << 8) + feature[7]); + + if(decoded.Version < 2) + return decoded; + + decoded.BUF |= (feature[4] & 0x40) == 0x40; + decoded.RWRaw |= (feature[4] & 0x10) == 0x10; + decoded.RWPack |= (feature[4] & 0x08) == 0x08; + + return decoded; + } + + public static Feature_002E? Decode_002E(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x002E) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_002E(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.SAO |= (feature[4] & 0x20) == 0x20; + decoded.RAWMS |= (feature[4] & 0x10) == 0x10; + decoded.RAW |= (feature[4] & 0x08) == 0x08; + decoded.TestWrite |= (feature[4] & 0x04) == 0x04; + decoded.CDRW |= (feature[4] & 0x02) == 0x02; + decoded.RW |= (feature[4] & 0x01) == 0x01; + decoded.MaxCueSheet = (uint)((feature[5] << 16) + (feature[6] << 8) + feature[7]); + + if(decoded.Version >= 1) + decoded.BUF |= (feature[4] & 0x40) == 0x40; + + return decoded; + } + + public static Feature_002F? Decode_002F(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x002F) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_002F(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.BUF |= (feature[4] & 0x40) == 0x40; + decoded.TestWrite |= (feature[4] & 0x04) == 0x04; + + if(decoded.Version >= 1) + decoded.DVDRW |= (feature[4] & 0x02) == 0x02; + + if(decoded.Version >= 2) + decoded.RDL |= (feature[4] & 0x08) == 0x08; + + return decoded; + } + + public static Feature_0030? Decode_0030(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 4) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0030) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0030(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + return decoded; + } + + public static Feature_0031? Decode_0031(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0031) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0031(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.TestWrite |= (feature[4] & 0x04) == 0x04; + + return decoded; + } + + public static Feature_0032? Decode_0032(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0032) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0032(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.Intermediate |= (feature[4] & 0x02) == 0x02; + decoded.Blank |= (feature[4] & 0x01) == 0x01; + + return decoded; + } + + public static Feature_0033? Decode_0033(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0033) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0033(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + if(feature[7] <= 0 || + feature.Length <= feature[7] + 8) + return decoded; + + decoded.LinkSizes = new byte[feature[7]]; + Array.Copy(feature, 8, decoded.LinkSizes, 0, feature[7]); + + return decoded; + } + + public static Feature_0035? Decode_0035(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 4) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0035) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0035(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + return decoded; + } + + public static Feature_0037? Decode_0037(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0037) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0037(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.SubtypeSupport = feature[5]; + + return decoded; + } + + public static Feature_0038? Decode_0038(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0038) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0038(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + return decoded; + } + + public static Feature_003A? Decode_003A(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x003A) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_003A(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.Write |= (feature[4] & 0x01) == 0x01; + decoded.QuickStart |= (feature[5] & 0x02) == 0x02; + decoded.CloseOnly |= (feature[5] & 0x01) == 0x01; + + return decoded; + } + + public static Feature_003B? Decode_003B(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x003B) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_003B(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.Write |= (feature[4] & 0x01) == 0x01; + + return decoded; + } + + public static Feature_0040? Decode_0040(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 32) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0040) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0040(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.OldRE |= (feature[9] & 0x01) == 0x01; + decoded.OldR |= (feature[17] & 0x01) == 0x01; + decoded.OldROM |= (feature[25] & 0x01) == 0x01; + + if(decoded.Version < 1) + return decoded; + + decoded.BCA |= (feature[4] & 0x01) == 0x01; + decoded.RE2 |= (feature[9] & 0x04) == 0x04; + decoded.RE1 |= (feature[9] & 0x02) == 0x02; + decoded.R |= (feature[17] & 0x02) == 0x02; + decoded.ROM |= (feature[25] & 0x02) == 0x02; + + return decoded; + } + + public static Feature_0041? Decode_0041(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 24) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0041) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0041(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.SVNR |= (feature[4] & 0x01) == 0x01; + decoded.OldRE |= (feature[9] & 0x01) == 0x01; + decoded.OldR |= (feature[17] & 0x01) == 0x01; + + if(decoded.Version < 1) + return decoded; + + decoded.RE2 |= (feature[9] & 0x04) == 0x04; + decoded.RE1 |= (feature[9] & 0x02) == 0x02; + decoded.R |= (feature[17] & 0x02) == 0x02; + + return decoded; + } + + public static Feature_0042? Decode_0042(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 4) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0042) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0042(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + return decoded; + } + + public static Feature_0050? Decode_0050(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0050) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0050(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.HDDVDR |= (feature[4] & 0x01) == 0x01; + decoded.HDDVDRAM |= (feature[6] & 0x01) == 0x01; + + return decoded; + } + + public static Feature_0051? Decode_0051(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0051) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0051(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.HDDVDR |= (feature[4] & 0x01) == 0x01; + decoded.HDDVDRAM |= (feature[6] & 0x01) == 0x01; + + return decoded; + } + + public static Feature_0080? Decode_0080(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0080) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0080(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.RI |= (feature[4] & 0x01) == 0x01; + + return decoded; + } + + public static Feature_0100? Decode_0100(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 4) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0100) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0100(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + return decoded; + } + + public static Feature_0101? Decode_0101(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0101) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0101(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.PP |= (feature[4] & 0x01) == 0x01; + + return decoded; + } + + public static Feature_0102? Decode_0102(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 4) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0102) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0102(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.SCC |= (feature[4] & 0x10) == 0x10; + decoded.SDP |= (feature[4] & 0x04) == 0x04; + decoded.HighestSlotNumber = (byte)(feature[7] & 0x1F); + + return decoded; + } + + public static Feature_0103? Decode_0103(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0103) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0103(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.Scan |= (feature[4] & 0x04) == 0x04; + decoded.SCM |= (feature[4] & 0x02) == 0x02; + decoded.SV |= (feature[4] & 0x01) == 0x01; + decoded.VolumeLevels = (ushort)((feature[6] << 8) + feature[7]); + + return decoded; + } + + public static Feature_0104? Decode_0104(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 4) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0104) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0104(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + if(decoded.Version >= 1 && + feature.Length >= 8) + decoded.M5 |= (feature[4] & 0x01) == 0x01; + + return decoded; + } + + public static Feature_0105? Decode_0105(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 4) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0105) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0105(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + if(decoded.Version < 1 || + feature.Length < 8) + return decoded; + + decoded.Group3 |= (feature[4] & 0x01) == 0x01; + decoded.UnitLength = (ushort)((feature[6] << 8) + feature[7]); + + return decoded; + } + + public static Feature_0106? Decode_0106(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0106) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0106(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.CSSVersion = feature[7]; + + return decoded; + } + + public static Feature_0107? Decode_0107(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 4) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0107) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0107(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + if(decoded.Version >= 3 && + feature.Length >= 8) + { + decoded.RBCB |= (feature[4] & 0x10) == 0x10; + decoded.SCS |= (feature[4] & 0x08) == 0x08; + decoded.MP2A |= (feature[4] & 0x04) == 0x04; + decoded.WSPD |= (feature[4] & 0x02) == 0x02; + decoded.SW |= (feature[4] & 0x01) == 0x01; + } + + if(decoded.Version < 5 || + feature.Length < 8) + return decoded; + + decoded.SMP |= (feature[4] & 0x20) == 0x20; + decoded.RBCB |= (feature[4] & 0x10) == 0x10; + + return decoded; + } + + public static Feature_0108? Decode_0108(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 4) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0108) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0108(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + byte[] serial = new byte[feature.Length]; + Array.Copy(feature, 4, serial, 0, feature.Length - 4); + decoded.Serial = StringHandlers.CToString(serial).Trim(); + + return decoded; + } + + public static Feature_0109? Decode_0109(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 4) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0109) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0109(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + return decoded; + } + + public static Feature_010A? Decode_010A(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x010A) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_010A(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.DCBs = new uint[feature[3] / 4]; + + for(int i = 0; i < decoded.DCBs.Length; i++) + decoded.DCBs[i] = (uint)((feature[0 + 4 + (i * 4)] << 24) + (feature[1 + 4 + (i * 4)] << 16) + + (feature[2 + 4 + (i * 4)] << 8) + feature[3 + 4 + (i * 4)]); + + return decoded; + } + + public static Feature_010B? Decode_010B(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 4) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x010B) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_010B(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.CPRMVersion = feature[7]; + + return decoded; + } + + public static Feature_010C? Decode_010C(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 20) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x010C) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_010C(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.Century = (ushort)((feature[4] << 8) + feature[5]); + decoded.Year = (ushort)((feature[6] << 8) + feature[7]); + decoded.Month = (ushort)((feature[8] << 8) + feature[9]); + decoded.Day = (ushort)((feature[10] << 8) + feature[11]); + decoded.Hour = (ushort)((feature[12] << 8) + feature[13]); + decoded.Minute = (ushort)((feature[14] << 8) + feature[15]); + decoded.Second = (ushort)((feature[16] << 8) + feature[17]); + + return decoded; + } + + public static Feature_010D? Decode_010D(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x010D) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_010D(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.BNG |= (feature[4] & 0x01) == 0x01; + decoded.BindNonceBlocks = feature[5]; + decoded.AGIDs = (byte)(feature[6] & 0x0F); + decoded.AACSVersion = feature[7]; + + if(decoded.Version < 2) + return decoded; + + decoded.RDC |= (feature[4] & 0x10) == 0x10; + decoded.RMC |= (feature[4] & 0x08) == 0x08; + decoded.WBE |= (feature[4] & 0x04) == 0x04; + decoded.BEC |= (feature[4] & 0x02) == 0x02; + + return decoded; + } + + public static Feature_010E? Decode_010E(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x010E) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_010E(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.MaxScrambleExtent = feature[4]; + + return decoded; + } + + public static Feature_0110? Decode_0110(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 8) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0110) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0110(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + return decoded; + } + + public static Feature_0113? Decode_0113(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 4) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0113) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0113(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + return decoded; + } + + public static Feature_0142? Decode_0142(byte[] feature) + { + if(feature == null) + return null; + + if(feature.Length < 6) + return null; + + ushort number = (ushort)((feature[0] << 8) + feature[1]); + + if(number != 0x0142) + return null; + + if(feature[3] + 4 != feature.Length) + return null; + + var decoded = new Feature_0142(); + + decoded.Current |= (feature[2] & 0x01) == 0x01; + decoded.Persistent |= (feature[2] & 0x02) == 0x02; + decoded.Version = (byte)((feature[2] & 0x3C) >> 2); + + decoded.PSAU |= (feature[4] & 0x80) == 0x80; + decoded.LOSPB |= (feature[4] & 0x40) == 0x40; + decoded.ME |= (feature[4] & 0x01) == 0x01; + decoded.Profiles = new ushort[feature[5]]; + + if((feature[5] * 2) + 6 != feature.Length) + return decoded; + + for(int i = 0; i < feature[5]; i++) + decoded.Profiles[i] = (ushort)((feature[0 + 6 + (2 * i)] << 8) + feature[1 + 6 + (2 * i)]); + + return decoded; + } + + public static string Prettify_0000(Feature_0000? feature) + { + if(!feature.HasValue) + return null; + + Feature_0000 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("MMC Supported Profiles:"); + + if(ftr.Profiles == null) + return sb.ToString(); + + foreach(Profile prof in ftr.Profiles) + { + switch(prof.Number) + { + case ProfileNumber.Reserved: + sb.Append("\tDrive reported a reserved profile number"); + + break; + case ProfileNumber.NonRemovable: + sb.Append("\tDrive supports non-removable changeable media"); + + break; + case ProfileNumber.Removable: + sb.Append("\tDrive supports rewritable and removable media"); + + break; + case ProfileNumber.MOErasable: + sb.Append("\tDrive supports Magnet-Optical media"); + + break; + case ProfileNumber.OpticalWORM: + sb.Append("\tDrive supports optical write-once media"); + + break; + case ProfileNumber.ASMO: + sb.Append("\tDrive supports Advanced Storage - Magneto-Optical"); + + break; + case ProfileNumber.CDROM: + sb.Append("\tDrive supports CD-ROM"); + + break; + case ProfileNumber.CDR: + sb.Append("\tDrive supports CD-R"); + + break; + case ProfileNumber.CDRW: + sb.Append("\tDrive supports CD-RW"); + + break; + case ProfileNumber.DVDROM: + sb.Append("\tDrive supports DVD-ROM"); + + break; + case ProfileNumber.DVDRSeq: + sb.Append("\tDrive supports DVD-R"); + + break; + case ProfileNumber.DVDRAM: + sb.Append("\tDrive supports DVD-RAM"); + + break; + case ProfileNumber.DVDRWRes: + sb.Append("\tDrive supports restricted overwrite DVD-RW"); + + break; + case ProfileNumber.DVDRWSeq: + sb.Append("\tDrive supports sequentially recorded DVD-RW"); + + break; + case ProfileNumber.DVDRDLSeq: + sb.Append("\tDrive supports sequentially recorded DVD-R DL"); + + break; + case ProfileNumber.DVDRDLJump: + sb.Append("\tDrive supports layer jump recorded DVD-R DL"); + + break; + case ProfileNumber.DVDRWDL: + sb.Append("\tDrive supports DVD-RW DL"); + + break; + case ProfileNumber.DVDDownload: + sb.Append("\tDrive supports DVD-Download"); + + break; + case ProfileNumber.DVDRWPlus: + sb.Append("\tDrive supports DVD+RW"); + + break; + case ProfileNumber.DVDRPlus: + sb.Append("\tDrive supports DVD+R"); + + break; + case ProfileNumber.DDCDROM: + sb.Append("\tDrive supports DDCD-ROM"); + + break; + case ProfileNumber.DDCDR: + sb.Append("\tDrive supports DDCD-R"); + + break; + case ProfileNumber.DDCDRW: + sb.Append("\tDrive supports DDCD-RW"); + + break; + case ProfileNumber.DVDRWDLPlus: + sb.Append("\tDrive supports DVD+RW DL"); + + break; + case ProfileNumber.DVDRDLPlus: + sb.Append("\tDrive supports DVD+R DL"); + + break; + case ProfileNumber.BDROM: + sb.Append("\tDrive supports BD-ROM"); + + break; + case ProfileNumber.BDRSeq: + sb.Append("\tDrive supports BD-R SRM"); + + break; + case ProfileNumber.BDRRdm: + sb.Append("\tDrive supports BD-R RRM"); + + break; + case ProfileNumber.BDRE: + sb.Append("\tDrive supports BD-RE"); + + break; + case ProfileNumber.HDDVDROM: + sb.Append("\tDrive supports HD DVD-ROM"); + + break; + case ProfileNumber.HDDVDR: + sb.Append("\tDrive supports HD DVD-R"); + + break; + case ProfileNumber.HDDVDRAM: + sb.Append("\tDrive supports HD DVD-RAM"); + + break; + case ProfileNumber.HDDVDRW: + sb.Append("\tDrive supports HD DVD-RW"); + + break; + case ProfileNumber.HDDVDRDL: + sb.Append("\tDrive supports HD DVD-R DL"); + + break; + case ProfileNumber.HDDVDRWDL: + sb.Append("\tDrive supports HD DVD-RW DL"); + + break; + case ProfileNumber.HDBURNROM: + sb.Append("\tDrive supports HDBurn CD-ROM"); + + break; + case ProfileNumber.HDBURNR: + sb.Append("\tDrive supports HDBurn CD-R"); + + break; + case ProfileNumber.HDBURNRW: + sb.Append("\tDrive supports HDBurn CD-RW"); + + break; + case ProfileNumber.Unconforming: + sb.Append("\tDrive is not conforming to any profile"); + + break; + default: + sb.AppendFormat("\tDrive informs of unknown profile 0x{0:X4}", (ushort)prof.Number); + + break; + } + + if(prof.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); + } + + return sb.ToString(); + } + + public static string Prettify_0001(Feature_0001? feature) + { + if(!feature.HasValue) + return null; + + Feature_0001 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("MMC Core Feature:"); + sb.Append("\tDrive uses "); + + switch(ftr.PhysicalInterfaceStandard) + { + case PhysicalInterfaces.Unspecified: + sb.AppendLine("an unspecified physical interface"); + + break; + case PhysicalInterfaces.SCSI: + sb.AppendLine("SCSI interface"); + + break; + case PhysicalInterfaces.ATAPI: + sb.AppendLine("ATAPI interface"); + + break; + case PhysicalInterfaces.IEEE1394: + sb.AppendLine("IEEE-1394 interface"); + + break; + case PhysicalInterfaces.IEEE1394A: + sb.AppendLine("IEEE-1394A interface"); + + break; + case PhysicalInterfaces.FC: + sb.AppendLine("Fibre Channel interface"); + + break; + case PhysicalInterfaces.IEEE1394B: + sb.AppendLine("IEEE-1394B interface"); + + break; + case PhysicalInterfaces.SerialATAPI: + sb.AppendLine("Serial ATAPI interface"); + + break; + case PhysicalInterfaces.USB: + sb.AppendLine("USB interface"); + + break; + case PhysicalInterfaces.Vendor: + sb.AppendLine("a vendor unique interface"); + + break; + default: + sb.AppendFormat("an unknown interface with code {0}", (uint)ftr.PhysicalInterfaceStandard). + AppendLine(); + + break; + } + + if(ftr.DBE) + sb.AppendLine("\tDrive supports Device Busy events"); + + if(ftr.INQ2) + sb.AppendLine("\tDrive supports EVPD, Page Code and 16-bit Allocation Length as described in SPC-3"); + + return sb.ToString(); + } + + public static string Prettify_0002(Feature_0002? feature) + { + if(!feature.HasValue) + return null; + + Feature_0002 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("MMC Morphing:"); + + sb.AppendLine(ftr.Async ? "\tDrive supports polling and asynchronous GET EVENT STATUS NOTIFICATION" + : "\tDrive supports only polling GET EVENT STATUS NOTIFICATION"); + + if(ftr.OCEvent) + sb.AppendLine("\tDrive supports operational change request / notification class events"); + + return sb.ToString(); + } + + public static string Prettify_0003(Feature_0003? feature) + { + if(!feature.HasValue) + return null; + + Feature_0003 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("MMC Removable Medium:"); + + switch(ftr.LoadingMechanismType) + { + case 0: + sb.AppendLine("\tDrive uses media caddy"); + + break; + case 1: + sb.AppendLine("\tDrive uses a tray"); + + break; + case 2: + sb.AppendLine("\tDrive is pop-up"); + + break; + case 4: + sb.AppendLine("\tDrive is a changer with individually changeable discs"); + + break; + case 5: + sb.AppendLine("\tDrive is a changer using cartridges"); + + break; + default: + sb.AppendFormat("\tDrive uses unknown loading mechanism type {0}", ftr.LoadingMechanismType). + AppendLine(); + + break; + } + + if(ftr.Lock) + sb.AppendLine("\tDrive can lock media"); + + if(ftr.PreventJumper) + sb.AppendLine("\tDrive power ups locked"); + + if(ftr.Eject) + sb.AppendLine("\tDrive can eject media"); + + if(ftr.Load) + sb.AppendLine("\tDrive can load media"); + + if(ftr.DBML) + sb.AppendLine("\tDrive reports Device Busy Class events during medium loading/unloading"); + + return sb.ToString(); + } + + public static string Prettify_0004(Feature_0004? feature) + { + if(!feature.HasValue) + return null; + + Feature_0004 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("MMC Write Protect:"); + + if(ftr.DWP) + sb.AppendLine("\tDrive supports reading/writing the Disc Write Protect PAC on BD-R/-RE media"); + + if(ftr.WDCB) + sb.AppendLine("\tDrive supports writing the Write Inhibit DCB on DVD+RW media"); + + if(ftr.SPWP) + sb.AppendLine("\tDrive supports set/release of PWP status"); + + if(ftr.SSWPP) + sb.AppendLine("\tDrive supports the SWPP bit of the Timeout and Protect mode page"); + + return sb.ToString(); + } + + public static string Prettify_0010(Feature_0010? feature) + { + if(!feature.HasValue) + return null; + + Feature_0010 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.Append("MMC Random Readable"); + + if(ftr.Current) + sb.Append(" (current)"); + + sb.AppendLine(":"); + + if(ftr.PP) + sb.AppendLine("\tDrive shall report Read/Write Error Recovery mode page"); + + if(ftr.LogicalBlockSize > 0) + sb.AppendFormat("\t{0} bytes per logical block", ftr.LogicalBlockSize).AppendLine(); + + if(ftr.Blocking > 1) + sb.AppendFormat("\t{0} logical blocks per media readable unit", ftr.Blocking).AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_001D(Feature_001D? feature) => + !feature.HasValue ? null + : "Drive claims capability to read all CD formats according to OSTA Multi-Read Specification\n"; + + public static string Prettify_001E(Feature_001E? feature) + { + if(!feature.HasValue) + return null; + + Feature_001E ftr = feature.Value; + var sb = new StringBuilder(); + + sb.Append("MMC CD Read"); + + if(ftr.Current) + sb.Append(" (current)"); + + sb.AppendLine(":"); + + if(ftr.DAP) + sb.AppendLine("\tDrive supports the DAP bit in the READ CD and READ CD MSF commands"); + + if(ftr.C2) + sb.AppendLine("\tDrive supports C2 Error Pointers"); + + if(ftr.CDText) + sb.AppendLine("\tDrive can return CD-Text from Lead-In"); + + return sb.ToString(); + } + + public static string Prettify_001F(Feature_001F? feature) + { + if(!feature.HasValue) + return null; + + Feature_001F ftr = feature.Value; + var sb = new StringBuilder(); + + sb.Append("MMC DVD Read"); + + if(ftr.Current) + sb.Append(" (current)"); + + sb.AppendLine(":"); + sb.AppendLine("\tDrive can read DVD media"); + + if(ftr.DualR) + sb.AppendLine("\tDrive can read DVD-R DL from all recording modes"); + + if(ftr.DualRW) + sb.AppendLine("\tDrive can read DVD-RW DL from all recording modes"); + + if(ftr.MULTI110) + sb.AppendLine("\tDrive conforms to DVD Multi Drive Read-only Specifications"); + + return sb.ToString(); + } + + public static string Prettify_0020(Feature_0020? feature) + { + if(!feature.HasValue) + return null; + + Feature_0020 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.Append("MMC Random Writable:"); + + if(ftr.Current) + sb.Append(" (current)"); + + sb.AppendLine(":"); + + if(ftr.PP) + sb.AppendLine("\tDrive shall report Read/Write Error Recovery mode page"); + + if(ftr.LogicalBlockSize > 0) + sb.AppendFormat("\t{0} bytes per logical block", ftr.LogicalBlockSize).AppendLine(); + + if(ftr.Blocking > 1) + sb.AppendFormat("\t{0} logical blocks per media writable unit", ftr.Blocking).AppendLine(); + + if(ftr.LastLBA > 0) + sb.AppendFormat("\tLast adressable logical block is {0}", ftr.LastLBA).AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_0021(Feature_0021? feature) + { + if(!feature.HasValue) + return null; + + Feature_0021 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("MMC Incremental Streaming Writable:"); + + if(ftr.DataTypeSupported > 0) + { + sb.Append("\tDrive supports data block types:"); + + if((ftr.DataTypeSupported & 0x0001) == 0x0001) + sb.Append(" 0"); + + if((ftr.DataTypeSupported & 0x0002) == 0x0002) + sb.Append(" 1"); + + if((ftr.DataTypeSupported & 0x0004) == 0x0004) + sb.Append(" 2"); + + if((ftr.DataTypeSupported & 0x0008) == 0x0008) + sb.Append(" 3"); + + if((ftr.DataTypeSupported & 0x0010) == 0x0010) + sb.Append(" 4"); + + if((ftr.DataTypeSupported & 0x0020) == 0x0020) + sb.Append(" 5"); + + if((ftr.DataTypeSupported & 0x0040) == 0x0040) + sb.Append(" 6"); + + if((ftr.DataTypeSupported & 0x0080) == 0x0080) + sb.Append(" 7"); + + if((ftr.DataTypeSupported & 0x0100) == 0x0100) + sb.Append(" 8"); + + if((ftr.DataTypeSupported & 0x0200) == 0x0200) + sb.Append(" 9"); + + if((ftr.DataTypeSupported & 0x0400) == 0x0400) + sb.Append(" 10"); + + if((ftr.DataTypeSupported & 0x0800) == 0x0800) + sb.Append(" 11"); + + if((ftr.DataTypeSupported & 0x1000) == 0x1000) + sb.Append(" 12"); + + if((ftr.DataTypeSupported & 0x2000) == 0x2000) + sb.Append(" 13"); + + if((ftr.DataTypeSupported & 0x4000) == 0x4000) + sb.Append(" 14"); + + if((ftr.DataTypeSupported & 0x8000) == 0x8000) + sb.Append(" 15"); + + sb.AppendLine(); + } + + if(ftr.TRIO) + sb.AppendLine("\tDrive claims support to report Track Resources Information"); + + if(ftr.ARSV) + sb.AppendLine("\tDrive supports address mode reservation on the RESERVE TRACK command"); + + if(ftr.BUF) + sb.AppendLine("\tDrive is capable of zero loss linking"); + + return sb.ToString(); + } + + public static string Prettify_0022(Feature_0022? feature) => + !feature.HasValue ? null : "Drive supports media that require erasing before writing\n"; + + public static string Prettify_0023(Feature_0023? feature) + { + if(!feature.HasValue) + return null; + + Feature_0023 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("MMC Formattable:"); + sb.AppendLine("\tDrive can format media into logical blocks"); + + if(ftr.RENoSA) + sb.AppendLine("\tDrive can format BD-RE with no spares allocated"); + + if(ftr.Expand) + sb.AppendLine("\tDrive can expand the spare area on a formatted BD-RE disc"); + + if(ftr.QCert) + sb.AppendLine("\tDrive can format BD-RE discs with quick certification"); + + if(ftr.Cert) + sb.AppendLine("\tDrive can format BD-RE discs with full certification"); + + if(ftr.FRF) + sb.AppendLine("\tDrive can fast re-format BD-RE discs"); + + if(ftr.RRM) + sb.AppendLine("\tDrive can format BD-R discs with RRM format"); + + return sb.ToString(); + } + + public static string Prettify_0024(Feature_0024? feature) + { + if(!feature.HasValue) + return null; + + Feature_0024 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("MMC Hardware Defect Management:"); + sb.AppendLine("\tDrive shall be able to provide a defect-free contiguous address space"); + + if(ftr.SSA) + sb.AppendLine("\tDrive can return Spare Area Information"); + + return sb.ToString(); + } + + public static string Prettify_0025(Feature_0025? feature) + { + if(!feature.HasValue) + return null; + + Feature_0025 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.Append("MMC Write Once"); + + if(ftr.Current) + sb.Append(" (current)"); + + sb.AppendLine(":"); + + if(ftr.PP) + sb.AppendLine("\tDrive shall report Read/Write Error Recovery mode page"); + + if(ftr.LogicalBlockSize > 0) + sb.AppendFormat("\t{0} bytes per logical block", ftr.LogicalBlockSize).AppendLine(); + + if(ftr.Blocking > 1) + sb.AppendFormat("\t{0} logical blocks per media writable unit", ftr.Blocking).AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_0026(Feature_0026? feature) => + !feature.HasValue ? null + : "Drive shall have the ability to overwrite logical blocks only in fixed sets at a time\n"; + + public static string Prettify_0027(Feature_0027? feature) + { + if(!feature.HasValue) + return null; + + Feature_0027 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.Append("Drive can write High-Speed CD-RW"); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_0028(Feature_0028? feature) + { + if(!feature.HasValue) + return null; + + Feature_0028 ftr = feature.Value; + var sb = new StringBuilder(); + + if(ftr.Write && + ftr.DVDPRead && + ftr.DVDPWrite) + sb.Append("Drive can read and write CD-MRW and DVD+MRW"); + else if(ftr.DVDPRead && + ftr.DVDPWrite) + sb.Append("Drive can read and write DVD+MRW"); + else if(ftr.Write && + ftr.DVDPRead) + sb.Append("Drive and read DVD+MRW and read and write CD-MRW"); + else if(ftr.Write) + sb.Append("Drive can read and write CD-MRW"); + else if(ftr.DVDPRead) + sb.Append("Drive can read CD-MRW and DVD+MRW"); + else + sb.Append("Drive can read CD-MRW"); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_0029(Feature_0029? feature) + { + if(!feature.HasValue) + return null; + + Feature_0029 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("MMC Enhanced Defect Reporting Feature:"); + + sb.AppendLine(ftr.DRTDM ? "\tDrive supports DRT-DM mode" : "\tDrive supports Persistent-DM mode"); + + if(ftr.DBICacheZones > 0) + sb.AppendFormat("\tDrive has {0} DBI cache zones", ftr.DBICacheZones).AppendLine(); + + if(ftr.Entries > 0) + sb.AppendFormat("\tDrive has {0} DBI entries", ftr.Entries).AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_002A(Feature_002A? feature) + { + if(!feature.HasValue) + return null; + + Feature_002A ftr = feature.Value; + var sb = new StringBuilder(); + + if(ftr.Write) + { + sb.Append("Drive can read and write DVD+RW"); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); + + sb.AppendLine(ftr.CloseOnly ? "\tDrive supports only the read compatibility stop" + : "\tDrive supports both forms of background format stopping"); + + if(ftr.QuickStart) + sb.AppendLine("\tDrive can do a quick start formatting"); + } + else + { + sb.Append("Drive can read DVD+RW"); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); + } + + return sb.ToString(); + } + + public static string Prettify_002B(Feature_002B? feature) + { + if(!feature.HasValue) + return null; + + Feature_002B ftr = feature.Value; + var sb = new StringBuilder(); + + if(ftr.Write) + { + sb.Append("Drive can read and write DVD+R"); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); + } + else + { + sb.Append("Drive can read DVD+R"); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); + } + + return sb.ToString(); + } + + public static string Prettify_002C(Feature_002C? feature) + { + if(!feature.HasValue) + return null; + + Feature_002C ftr = feature.Value; + var sb = new StringBuilder(); + + sb.Append("MMC Rigid Restricted Overwrite"); + sb.AppendLine(ftr.Current ? " (current):" : ":"); + + if(ftr.Blank) + sb.AppendLine("\tDrive supports the BLANK command"); + + if(ftr.Intermediate) + sb.AppendLine("\tDrive supports writing on an intermediate state session and quick formatting"); + + if(ftr.DSDR) + sb.AppendLine("\tDrive can read Defect Status data recorded on the medium"); + + if(ftr.DSDG) + sb.AppendLine("\tDrive can generate Defect Status data during formatting"); + + return sb.ToString(); + } + + public static string Prettify_002D(Feature_002D? feature) + { + if(!feature.HasValue) + return null; + + Feature_002D ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("Drive can write CDs in Track at Once Mode:"); + + if(ftr.RWSubchannel) + { + sb.AppendLine("\tDrive can write user provided data in the R-W subchannels"); + + if(ftr.RWRaw) + sb.AppendLine("\tDrive accepts RAW R-W subchannel data"); + + if(ftr.RWPack) + sb.AppendLine("\tDrive accepts Packed R-W subchannel data"); + } + + if(ftr.CDRW) + sb.AppendLine("\tDrive can overwrite a TAO track with another in CD-RWs"); + + if(ftr.TestWrite) + sb.AppendLine("\tDrive can do a test writing"); + + if(ftr.BUF) + sb.AppendLine("\tDrive supports zero loss linking"); + + if(ftr.DataTypeSupported <= 0) + return sb.ToString(); + + sb.Append("\tDrive supports data block types:"); + + if((ftr.DataTypeSupported & 0x0001) == 0x0001) + sb.Append(" 0"); + + if((ftr.DataTypeSupported & 0x0002) == 0x0002) + sb.Append(" 1"); + + if((ftr.DataTypeSupported & 0x0004) == 0x0004) + sb.Append(" 2"); + + if((ftr.DataTypeSupported & 0x0008) == 0x0008) + sb.Append(" 3"); + + if((ftr.DataTypeSupported & 0x0010) == 0x0010) + sb.Append(" 4"); + + if((ftr.DataTypeSupported & 0x0020) == 0x0020) + sb.Append(" 5"); + + if((ftr.DataTypeSupported & 0x0040) == 0x0040) + sb.Append(" 6"); + + if((ftr.DataTypeSupported & 0x0080) == 0x0080) + sb.Append(" 7"); + + if((ftr.DataTypeSupported & 0x0100) == 0x0100) + sb.Append(" 8"); + + if((ftr.DataTypeSupported & 0x0200) == 0x0200) + sb.Append(" 9"); + + if((ftr.DataTypeSupported & 0x0400) == 0x0400) + sb.Append(" 10"); + + if((ftr.DataTypeSupported & 0x0800) == 0x0800) + sb.Append(" 11"); + + if((ftr.DataTypeSupported & 0x1000) == 0x1000) + sb.Append(" 12"); + + if((ftr.DataTypeSupported & 0x2000) == 0x2000) + sb.Append(" 13"); + + if((ftr.DataTypeSupported & 0x4000) == 0x4000) + sb.Append(" 14"); + + if((ftr.DataTypeSupported & 0x8000) == 0x8000) + sb.Append(" 15"); + + sb.AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_002E(Feature_002E? feature) + { + if(!feature.HasValue) + return null; + + Feature_002E ftr = feature.Value; + var sb = new StringBuilder(); + + if(ftr.SAO && + !ftr.RAW) + sb.AppendLine("Drive can write CDs in Session at Once Mode:"); + else if(!ftr.SAO && + ftr.RAW) + sb.AppendLine("Drive can write CDs in raw Mode:"); + else + sb.AppendLine("Drive can write CDs in Session at Once and in Raw Modes:"); + + if(ftr.RAW && + ftr.RAWMS) + sb.AppendLine("\tDrive can write multi-session CDs in raw mode"); + + if(ftr.RW) + sb.AppendLine("\tDrive can write user provided data in the R-W subchannels"); + + if(ftr.CDRW) + sb.AppendLine("\tDrive can write CD-RWs"); + + if(ftr.TestWrite) + sb.AppendLine("\tDrive can do a test writing"); + + if(ftr.BUF) + sb.AppendLine("\tDrive supports zero loss linking"); + + if(ftr.MaxCueSheet > 0) + sb.AppendFormat("\tDrive supports a maximum of {0} bytes in a single cue sheet", ftr.MaxCueSheet). + AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_002F(Feature_002F? feature) + { + if(!feature.HasValue) + return null; + + Feature_002F ftr = feature.Value; + var sb = new StringBuilder(); + + if(ftr.DVDRW && + ftr.RDL) + sb.AppendLine("Drive supports writing DVD-R, DVD-RW and DVD-R DL"); + else if(ftr.RDL) + sb.AppendLine("Drive supports writing DVD-R and DVD-R DL"); + else if(ftr.DVDRW) + sb.AppendLine("Drive supports writing DVD-R and DVD-RW"); + else + sb.AppendLine("Drive supports writing DVD-R"); + + if(ftr.TestWrite) + sb.AppendLine("\tDrive can do a test writing"); + + if(ftr.BUF) + sb.AppendLine("\tDrive supports zero loss linking"); + + return sb.ToString(); + } + + public static string Prettify_0030(Feature_0030? feature) => + !feature.HasValue ? null : "Drive can read DDCDs\n"; + + public static string Prettify_0031(Feature_0031? feature) + { + if(!feature.HasValue) + return null; + + Feature_0031 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("Drive supports writing DDCD-R"); + + if(ftr.TestWrite) + sb.AppendLine("\tDrive can do a test writing"); + + return sb.ToString(); + } + + public static string Prettify_0032(Feature_0032? feature) + { + if(!feature.HasValue) + return null; + + Feature_0032 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("Drive supports writing DDCD-RW"); + + if(ftr.Blank) + sb.AppendLine("\tDrive supports the BLANK command"); + + if(ftr.Intermediate) + sb.AppendLine("\tDrive supports quick formatting"); + + return sb.ToString(); + } + + public static string Prettify_0033(Feature_0033? feature) + { + if(!feature.HasValue) + return null; + + Feature_0033 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("MMC Layer Jump Recording:"); + + if(ftr.LinkSizes == null) + return sb.ToString(); + + foreach(byte link in ftr.LinkSizes) + sb.AppendFormat("\tCurrent media has a {0} bytes link available", link).AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_0035(Feature_0035? feature) => + !feature.HasValue ? null : "Drive can stop a long immediate operation\n"; + + public static string Prettify_0037(Feature_0037? feature) + { + if(!feature.HasValue) + return null; + + Feature_0037 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("Drive can write CD-RW"); + + if(ftr.SubtypeSupport <= 0) + return sb.ToString(); + + sb.Append("\tDrive supports CD-RW subtypes"); + + if((ftr.SubtypeSupport & 0x01) == 0x01) + sb.Append(" 0"); + + if((ftr.SubtypeSupport & 0x02) == 0x02) + sb.Append(" 1"); + + if((ftr.SubtypeSupport & 0x04) == 0x04) + sb.Append(" 2"); + + if((ftr.SubtypeSupport & 0x08) == 0x08) + sb.Append(" 3"); + + if((ftr.SubtypeSupport & 0x10) == 0x10) + sb.Append(" 4"); + + if((ftr.SubtypeSupport & 0x20) == 0x20) + sb.Append(" 5"); + + if((ftr.SubtypeSupport & 0x40) == 0x40) + sb.Append(" 6"); + + if((ftr.SubtypeSupport & 0x80) == 0x80) + sb.Append(" 7"); + + sb.AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_0038(Feature_0038? feature) => + !feature.HasValue ? null : "Drive can write BD-R on Pseudo-OVerwrite SRM mode\n"; + + public static string Prettify_003A(Feature_003A? feature) + { + if(!feature.HasValue) + return null; + + Feature_003A ftr = feature.Value; + var sb = new StringBuilder(); + + if(ftr.Write) + { + sb.Append("Drive can read and write DVD+RW DL"); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); + + sb.AppendLine(ftr.CloseOnly ? "\tDrive supports only the read compatibility stop" + : "\tDrive supports both forms of background format stopping"); + + if(ftr.QuickStart) + sb.AppendLine("\tDrive can do a quick start formatting"); + } + else + { + sb.Append("Drive can read DVD+RW DL"); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); + } + + return sb.ToString(); + } + + public static string Prettify_003B(Feature_003B? feature) + { + if(!feature.HasValue) + return null; + + Feature_003B ftr = feature.Value; + var sb = new StringBuilder(); + + if(ftr.Write) + { + sb.Append("Drive can read and write DVD+R DL"); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); + } + else + { + sb.Append("Drive can read DVD+R DL"); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); + } + + return sb.ToString(); + } + + public static string Prettify_0040(Feature_0040? feature) + { + if(!feature.HasValue) + return null; + + Feature_0040 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.Append("MMC BD Read"); + sb.AppendLine(ftr.Current ? " (current):" : ":"); + + if(ftr.OldROM) + sb.AppendLine("\tDrive can read BD-ROM pre-1.0"); + + if(ftr.ROM) + sb.AppendLine("\tDrive can read BD-ROM Ver.1"); + + if(ftr.OldR) + sb.AppendLine("\tDrive can read BD-R pre-1.0"); + + if(ftr.R) + sb.AppendLine("\tDrive can read BD-R Ver.1"); + + if(ftr.OldRE) + sb.AppendLine("\tDrive can read BD-RE pre-1.0"); + + if(ftr.RE1) + sb.AppendLine("\tDrive can read BD-RE Ver.1"); + + if(ftr.RE2) + sb.AppendLine("\tDrive can read BD-RE Ver.2"); + + if(ftr.BCA) + sb.AppendLine("\tDrive can read BD's Burst Cutting Area"); + + return sb.ToString(); + } + + public static string Prettify_0041(Feature_0041? feature) + { + if(!feature.HasValue) + return null; + + Feature_0041 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.Append("MMC BD Write"); + sb.AppendLine(ftr.Current ? " (current):" : ":"); + + if(ftr.OldR) + sb.AppendLine("\tDrive can write BD-R pre-1.0"); + + if(ftr.R) + sb.AppendLine("\tDrive can write BD-R Ver.1"); + + if(ftr.OldRE) + sb.AppendLine("\tDrive can write BD-RE pre-1.0"); + + if(ftr.RE1) + sb.AppendLine("\tDrive can write BD-RE Ver.1"); + + if(ftr.RE2) + sb.AppendLine("\tDrive can write BD-RE Ver.2"); + + if(ftr.SVNR) + sb.AppendLine("\tDrive supports write without verify requirement"); + + return sb.ToString(); + } + + public static string Prettify_0042(Feature_0042? feature) => + !feature.HasValue ? null + : "Drive is able to detect and report defective writable unit and behave accordinly\n"; + + public static string Prettify_0050(Feature_0050? feature) + { + if(!feature.HasValue) + return null; + + Feature_0050 ftr = feature.Value; + var sb = new StringBuilder(); + + if(ftr.HDDVDR && + ftr.HDDVDRAM) + sb.Append("Drive can read HD DVD-ROM, HD DVD-RW, HD DVD-R and HD DVD-RAM"); + else if(ftr.HDDVDR) + sb.Append("Drive can read HD DVD-ROM, HD DVD-RW and HD DVD-R"); + else if(ftr.HDDVDRAM) + sb.Append("Drive can read HD DVD-ROM, HD DVD-RW and HD DVD-RAM"); + else + sb.Append("Drive can read HD DVD-ROM and HD DVD-RW"); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_0051(Feature_0051? feature) + { + if(!feature.HasValue) + return null; + + Feature_0051 ftr = feature.Value; + var sb = new StringBuilder(); + + if(ftr.HDDVDR && + ftr.HDDVDRAM) + sb.Append("Drive can write HD DVD-RW, HD DVD-R and HD DVD-RAM"); + else if(ftr.HDDVDR) + sb.Append("Drive can write HD DVD-RW and HD DVD-R"); + else if(ftr.HDDVDRAM) + sb.Append("Drive can write HD DVD-RW and HD DVD-RAM"); + else + sb.Append("Drive can write HD DVD-RW"); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_0080(Feature_0080? feature) + { + if(!feature.HasValue) + return null; + + Feature_0080 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.Append("Drive is able to access Hybrid discs"); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); + + if(ftr.RI) + sb.AppendLine("\tDrive is able to maintain the online format layer through reset and power cycling"); + + return sb.ToString(); + } + + public static string Prettify_0100(Feature_0100? feature) => + !feature.HasValue ? null : "Drive is able to perform host and drive directed power management\n"; + + public static string Prettify_0101(Feature_0101? feature) + { + if(!feature.HasValue) + return null; + + Feature_0101 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("Drive supports S.M.A.R.T."); + + if(ftr.PP) + sb.AppendLine("\tDrive supports the Informational Exceptions Control mode page 1Ch"); + + return sb.ToString(); + } + + public static string Prettify_0102(Feature_0102? feature) + { + if(!feature.HasValue) + return null; + + Feature_0102 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("MMC Embedded Changer:"); + + if(ftr.SCC) + sb.AppendLine("\tDrive can change disc side"); + + if(ftr.SDP) + sb.AppendLine("\tDrive is able to report slots contents after a reset or change"); + + sb.AppendFormat("\tDrive has {0} slots", ftr.HighestSlotNumber + 1).AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_0103(Feature_0103? feature) + { + if(!feature.HasValue) + return null; + + Feature_0103 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("Drive has an analogue audio output"); + + if(ftr.Scan) + sb.AppendLine("\tDrive supports the SCAN command"); + + if(ftr.SCM) + sb.AppendLine("\tDrive is able to mute channels separately"); + + if(ftr.SV) + sb.AppendLine("\tDrive supports separate volume per channel"); + + sb.AppendFormat("\tDrive has {0} volume levels", ftr.VolumeLevels + 1).AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_0104(Feature_0104? feature) + { + if(!feature.HasValue) + return null; + + Feature_0104 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("Drive supports Microcode Upgrade"); + + if(ftr.M5) + sb.AppendLine("Drive supports validating the 5-bit Mode of the READ BUFFER and WRITE BUFFER commands"); + + return sb.ToString(); + } + + public static string Prettify_0105(Feature_0105? feature) + { + if(!feature.HasValue) + return null; + + Feature_0105 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("Drive supports Timeout & Protect mode page 1Dh"); + + if(!ftr.Group3) + return sb.ToString(); + + sb.AppendLine("\tDrive supports the Group3 in Timeout & Protect mode page 1Dh"); + + if(ftr.UnitLength > 0) + sb.AppendFormat("\tDrive has {0} increase of Group 3 time unit", ftr.UnitLength).AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_0106(Feature_0106? feature) + { + if(!feature.HasValue) + return null; + + Feature_0106 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendFormat("Drive supports DVD CSS/CPPM version {0}", ftr.CSSVersion); + + if(ftr.Current) + sb.AppendLine(" and current disc is encrypted"); + else + sb.AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_0107(Feature_0107? feature) + { + if(!feature.HasValue) + return null; + + Feature_0107 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("MMC Real Time Streaming:"); + + if(ftr.SMP) + sb.AppendLine("\tDrive supports Set Minimum Performance with the SET STREAMING command"); + + if(ftr.RBCB) + sb.AppendLine("\tDrive supports the block bit in the READ BUFFER CAPACITY command"); + + if(ftr.SCS) + sb.AppendLine("\tDrive supports the SET CD SPEED command"); + + if(ftr.MP2A) + sb.AppendLine("\tDrive supports the Write Speed Performance Descriptor Blocks in the MMC mode page 2Ah"); + + if(ftr.WSPD) + sb.AppendLine("\tDrive supports the Write Speed data of GET PERFORMANCE and the WRC field of SET STREAMING"); + + if(ftr.SW) + sb.AppendLine("\tDrive supports stream recording"); + + return sb.ToString(); + } + + public static string Prettify_0108(Feature_0108? feature) + { + if(!feature.HasValue) + return null; + + Feature_0108 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendFormat("Drive serial number: {0}", ftr.Serial).AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_0109(Feature_0109? feature) => + !feature.HasValue ? null : "Drive is able to read media serial number\n"; + + public static string Prettify_010A(Feature_010A? feature) + { + if(!feature.HasValue) + return null; + + Feature_010A ftr = feature.Value; + var sb = new StringBuilder(); + + if(ftr.DCBs == null) + return sb.ToString(); + + foreach(uint dcb in ftr.DCBs) + sb.AppendFormat("Drive supports DCB {0:X8}h", dcb).AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_010B(Feature_010B? feature) + { + if(!feature.HasValue) + return null; + + Feature_010B ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendFormat("Drive supports DVD CPRM version {0}", ftr.CPRMVersion); + + if(ftr.Current) + sb.AppendLine(" and current disc is or can be encrypted"); + else + sb.AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_010C(Feature_010C? feature) + { + if(!feature.HasValue) + return null; + + Feature_010C ftr = feature.Value; + var sb = new StringBuilder(); + + byte[] temp = new byte[4]; + temp[0] = (byte)((ftr.Century & 0xFF00) >> 8); + temp[1] = (byte)(ftr.Century & 0xFF); + temp[2] = (byte)((ftr.Year & 0xFF00) >> 8); + temp[3] = (byte)(ftr.Year & 0xFF); + string syear = Encoding.ASCII.GetString(temp); + temp = new byte[2]; + temp[0] = (byte)((ftr.Month & 0xFF00) >> 8); + temp[1] = (byte)(ftr.Month & 0xFF); + string smonth = Encoding.ASCII.GetString(temp); + temp = new byte[2]; + temp[0] = (byte)((ftr.Day & 0xFF00) >> 8); + temp[1] = (byte)(ftr.Day & 0xFF); + string sday = Encoding.ASCII.GetString(temp); + temp = new byte[2]; + temp[0] = (byte)((ftr.Hour & 0xFF00) >> 8); + temp[1] = (byte)(ftr.Hour & 0xFF); + string shour = Encoding.ASCII.GetString(temp); + temp = new byte[2]; + temp[0] = (byte)((ftr.Minute & 0xFF00) >> 8); + temp[1] = (byte)(ftr.Minute & 0xFF); + string sminute = Encoding.ASCII.GetString(temp); + temp = new byte[2]; + temp[0] = (byte)((ftr.Second & 0xFF00) >> 8); + temp[1] = (byte)(ftr.Second & 0xFF); + string ssecond = Encoding.ASCII.GetString(temp); + + try + { + var fwDate = new DateTime(int.Parse(syear), int.Parse(smonth), int.Parse(sday), int.Parse(shour), + int.Parse(sminute), int.Parse(ssecond), DateTimeKind.Utc); + + sb.AppendFormat("Drive firmware is dated {0}", fwDate).AppendLine(); + } + #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body + catch + { + // ignored + } + #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body + + return sb.ToString(); + } + + public static string Prettify_010D(Feature_010D? feature) + { + if(!feature.HasValue) + return null; + + Feature_010D ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendFormat("Drive supports AACS version {0}", ftr.AACSVersion); + + if(ftr.Current) + sb.AppendLine(" and current disc is encrypted"); + else + sb.AppendLine(); + + if(ftr.RDC) + sb.AppendLine("\tDrive supports reading the Drive Certificate"); + + if(ftr.RMC) + sb.AppendLine("\tDrive supports reading Media Key Block of CPRM"); + + if(ftr.WBE) + sb.AppendLine("\tDrive supports writing with bus encryption"); + + if(ftr.BEC) + sb.AppendLine("\tDrive supports bus encryption"); + + if(ftr.BNG) + { + sb.AppendLine("\tDrive supports generating the binding nonce"); + + if(ftr.BindNonceBlocks > 0) + sb.AppendFormat("\t{0} media blocks are required for the binding nonce", ftr.BindNonceBlocks). + AppendLine(); + } + + if(ftr.AGIDs > 0) + sb.AppendFormat("\tDrive supports {0} AGIDs concurrently", ftr.AGIDs).AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_010E(Feature_010E? feature) + { + if(!feature.HasValue) + return null; + + Feature_010E ftr = feature.Value; + var sb = new StringBuilder(); + + sb.Append("Drive supports DVD-Download"); + + if(ftr.Current) + sb.AppendLine(" (current)"); + else + sb.AppendLine(); + + if(ftr.MaxScrambleExtent > 0) + sb.AppendFormat("\tMaximum {0} scranble extent information entries", ftr.MaxScrambleExtent). + AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_0110(Feature_0110? feature) + { + if(!feature.HasValue) + return null; + + Feature_0110 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine(ftr.Current ? "Drive and currently inserted media support VCPS" : "Drive supports VCPS"); + + return sb.ToString(); + } + + public static string Prettify_0113(Feature_0113? feature) + { + if(!feature.HasValue) + return null; + + Feature_0113 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine(ftr.Current ? "Drive and currently inserted media support SecurDisc" + : "Drive supports SecurDisc"); + + return sb.ToString(); + } + + public static string Prettify_0142(Feature_0142? feature) + { + if(!feature.HasValue) + return null; + + Feature_0142 ftr = feature.Value; + var sb = new StringBuilder(); + + sb.AppendLine("Drive supports the Trusted Computing Group Optical Security Subsystem Class"); + + if(ftr.Current) + sb.AppendLine("\tCurrent media is initialized with TCG OSSC"); + + if(ftr.PSAU) + sb.AppendLine("\tDrive supports PSA updates on write-once media"); + + if(ftr.LOSPB) + sb.AppendLine("\tDrive supports linked OSPBs"); + + if(ftr.ME) + sb.AppendLine("\tDrive will only record on the OSSC Disc Format"); + + if(ftr.Profiles == null) + return sb.ToString(); + + for(int i = 0; i < ftr.Profiles.Length; i++) + sb.AppendFormat("\tProfile {0}: {1}", i, ftr.Profiles[i]).AppendLine(); + + return sb.ToString(); + } + + public static string Prettify_0000(byte[] feature) => Prettify_0000(Decode_0000(feature)); + + public static string Prettify_0001(byte[] feature) => Prettify_0001(Decode_0001(feature)); + + public static string Prettify_0002(byte[] feature) => Prettify_0002(Decode_0002(feature)); + + public static string Prettify_0003(byte[] feature) => Prettify_0003(Decode_0003(feature)); + + public static string Prettify_0004(byte[] feature) => Prettify_0004(Decode_0004(feature)); + + public static string Prettify_0010(byte[] feature) => Prettify_0010(Decode_0010(feature)); + + public static string Prettify_001D(byte[] feature) => Prettify_001D(Decode_001D(feature)); + + public static string Prettify_001E(byte[] feature) => Prettify_001E(Decode_001E(feature)); + + public static string Prettify_001F(byte[] feature) => Prettify_001F(Decode_001F(feature)); + + public static string Prettify_0020(byte[] feature) => Prettify_0020(Decode_0020(feature)); + + public static string Prettify_0021(byte[] feature) => Prettify_0021(Decode_0021(feature)); + + public static string Prettify_0022(byte[] feature) => Prettify_0022(Decode_0022(feature)); + + public static string Prettify_0023(byte[] feature) => Prettify_0023(Decode_0023(feature)); + + public static string Prettify_0024(byte[] feature) => Prettify_0024(Decode_0024(feature)); + + public static string Prettify_0025(byte[] feature) => Prettify_0025(Decode_0025(feature)); + + public static string Prettify_0026(byte[] feature) => Prettify_0026(Decode_0026(feature)); + + public static string Prettify_0027(byte[] feature) => Prettify_0027(Decode_0027(feature)); + + public static string Prettify_0028(byte[] feature) => Prettify_0028(Decode_0028(feature)); + + public static string Prettify_0029(byte[] feature) => Prettify_0029(Decode_0029(feature)); + + public static string Prettify_002A(byte[] feature) => Prettify_002A(Decode_002A(feature)); + + public static string Prettify_002B(byte[] feature) => Prettify_002B(Decode_002B(feature)); + + public static string Prettify_002C(byte[] feature) => Prettify_002C(Decode_002C(feature)); + + public static string Prettify_002D(byte[] feature) => Prettify_002D(Decode_002D(feature)); + + public static string Prettify_002E(byte[] feature) => Prettify_002E(Decode_002E(feature)); + + public static string Prettify_002F(byte[] feature) => Prettify_002F(Decode_002F(feature)); + + public static string Prettify_0030(byte[] feature) => Prettify_0030(Decode_0030(feature)); + + public static string Prettify_0031(byte[] feature) => Prettify_0031(Decode_0031(feature)); + + public static string Prettify_0032(byte[] feature) => Prettify_0032(Decode_0032(feature)); + + public static string Prettify_0033(byte[] feature) => Prettify_0033(Decode_0033(feature)); + + public static string Prettify_0035(byte[] feature) => Prettify_0035(Decode_0035(feature)); + + public static string Prettify_0037(byte[] feature) => Prettify_0037(Decode_0037(feature)); + + public static string Prettify_0038(byte[] feature) => Prettify_0038(Decode_0038(feature)); + + public static string Prettify_003A(byte[] feature) => Prettify_003A(Decode_003A(feature)); + + public static string Prettify_003B(byte[] feature) => Prettify_003B(Decode_003B(feature)); + + public static string Prettify_0040(byte[] feature) => Prettify_0040(Decode_0040(feature)); + + public static string Prettify_0041(byte[] feature) => Prettify_0041(Decode_0041(feature)); + + public static string Prettify_0042(byte[] feature) => Prettify_0042(Decode_0042(feature)); + + public static string Prettify_0050(byte[] feature) => Prettify_0050(Decode_0050(feature)); + + public static string Prettify_0051(byte[] feature) => Prettify_0051(Decode_0051(feature)); + + public static string Prettify_0080(byte[] feature) => Prettify_0080(Decode_0080(feature)); + + public static string Prettify_0100(byte[] feature) => Prettify_0100(Decode_0100(feature)); + + public static string Prettify_0101(byte[] feature) => Prettify_0101(Decode_0101(feature)); + + public static string Prettify_0102(byte[] feature) => Prettify_0102(Decode_0102(feature)); + + public static string Prettify_0103(byte[] feature) => Prettify_0103(Decode_0103(feature)); + + public static string Prettify_0104(byte[] feature) => Prettify_0104(Decode_0104(feature)); + + public static string Prettify_0105(byte[] feature) => Prettify_0105(Decode_0105(feature)); + + public static string Prettify_0106(byte[] feature) => Prettify_0106(Decode_0106(feature)); + + public static string Prettify_0107(byte[] feature) => Prettify_0107(Decode_0107(feature)); + + public static string Prettify_0108(byte[] feature) => Prettify_0108(Decode_0108(feature)); + + public static string Prettify_0109(byte[] feature) => Prettify_0109(Decode_0109(feature)); + + public static string Prettify_010A(byte[] feature) => Prettify_010A(Decode_010A(feature)); + + public static string Prettify_010B(byte[] feature) => Prettify_010B(Decode_010B(feature)); + + public static string Prettify_010C(byte[] feature) => Prettify_010C(Decode_010C(feature)); + + public static string Prettify_010D(byte[] feature) => Prettify_010D(Decode_010D(feature)); + + public static string Prettify_010E(byte[] feature) => Prettify_010E(Decode_010E(feature)); + + public static string Prettify_0110(byte[] feature) => Prettify_0110(Decode_0110(feature)); + + public static string Prettify_0113(byte[] feature) => Prettify_0113(Decode_0113(feature)); + + public static string Prettify_0142(byte[] feature) => Prettify_0142(Decode_0142(feature)); + + public static SeparatedFeatures Separate(byte[] response) + { + var dec = new SeparatedFeatures + { + DataLength = (uint)((response[0] << 24) + (response[1] << 16) + (response[2] << 8) + response[4]), + CurrentProfile = (ushort)((response[6] << 8) + response[7]) + }; + + uint offset = 8; + List descLst = new List(); + + while(offset + 4 < response.Length) + { + var desc = new FeatureDescriptor + { + Code = (ushort)((response[offset + 0] << 8) + response[offset + 1]), + Data = new byte[response[offset + 3] + 4] + }; + + if(desc.Data.Length + offset > response.Length) + desc.Data = new byte[response.Length - offset]; + + Array.Copy(response, offset, desc.Data, 0, desc.Data.Length); + offset += (uint)desc.Data.Length; + + descLst.Add(desc); + } + + dec.Descriptors = descLst.ToArray(); + + return dec; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct FeatureDescriptor + { + public ushort Code; + public byte[] Data; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct SeparatedFeatures + { + public uint DataLength; + public ushort CurrentProfile; + public FeatureDescriptor[] Descriptors; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/MMC/Hybrid.cs b/Aaru.Decoders/SCSI/MMC/Hybrid.cs new file mode 100644 index 000000000..8eb167955 --- /dev/null +++ b/Aaru.Decoders/SCSI/MMC/Hybrid.cs @@ -0,0 +1,196 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Hybrid.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MMC hybrid structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Helpers; + +namespace Aaru.Decoders.SCSI.MMC +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class Hybrid + { + public static RecognizedFormatLayers? DecodeFormatLayers(byte[] FormatLayersResponse) + { + if(FormatLayersResponse == null) + return null; + + if(FormatLayersResponse.Length < 8) + return null; + + var decoded = new RecognizedFormatLayers + { + DataLength = BigEndianBitConverter.ToUInt16(FormatLayersResponse, 0), + Reserved1 = FormatLayersResponse[2], + Reserved2 = FormatLayersResponse[3], + NumberOfLayers = FormatLayersResponse[4], + Reserved3 = (byte)((FormatLayersResponse[5] & 0xC0) >> 6), + DefaultFormatLayer = (byte)((FormatLayersResponse[5] & 0x30) >> 4), + Reserved4 = (byte)((FormatLayersResponse[5] & 0x0C) >> 2), + OnlineFormatLayer = (byte)(FormatLayersResponse[5] & 0x03), + FormatLayers = new ushort[(FormatLayersResponse.Length - 6) / 2] + }; + + for(int i = 0; i < (FormatLayersResponse.Length - 6) / 2; i++) + decoded.FormatLayers[i] = BigEndianBitConverter.ToUInt16(FormatLayersResponse, (i * 2) + 6); + + return decoded; + } + + public static string PrettifyFormatLayers(RecognizedFormatLayers? FormatLayersResponse) + { + if(FormatLayersResponse == null) + return null; + + RecognizedFormatLayers response = FormatLayersResponse.Value; + + var sb = new StringBuilder(); + + sb.AppendFormat("{0} format layers recognized", response.NumberOfLayers); + + for(int i = 0; i < response.FormatLayers.Length; i++) + switch(response.FormatLayers[i]) + { + case (ushort)FormatLayerTypeCodes.BDLayer: + { + sb.AppendFormat("Layer {0} is of type Blu-ray", i).AppendLine(); + + if(response.DefaultFormatLayer == i) + sb.AppendLine("This is the default layer."); + + if(response.OnlineFormatLayer == i) + sb.AppendLine("This is the layer actually in use."); + + break; + } + + case (ushort)FormatLayerTypeCodes.CDLayer: + { + sb.AppendFormat("Layer {0} is of type CD", i).AppendLine(); + + if(response.DefaultFormatLayer == i) + sb.AppendLine("This is the default layer."); + + if(response.OnlineFormatLayer == i) + sb.AppendLine("This is the layer actually in use."); + + break; + } + + case (ushort)FormatLayerTypeCodes.DVDLayer: + { + sb.AppendFormat("Layer {0} is of type DVD", i).AppendLine(); + + if(response.DefaultFormatLayer == i) + sb.AppendLine("This is the default layer."); + + if(response.OnlineFormatLayer == i) + sb.AppendLine("This is the layer actually in use."); + + break; + } + + case (ushort)FormatLayerTypeCodes.HDDVDLayer: + { + sb.AppendFormat("Layer {0} is of type HD DVD", i).AppendLine(); + + if(response.DefaultFormatLayer == i) + sb.AppendLine("This is the default layer."); + + if(response.OnlineFormatLayer == i) + sb.AppendLine("This is the layer actually in use."); + + break; + } + + default: + { + sb.AppendFormat("Layer {0} is of unknown type 0x{1:X4}", i, response.FormatLayers[i]). + AppendLine(); + + if(response.DefaultFormatLayer == i) + sb.AppendLine("This is the default layer."); + + if(response.OnlineFormatLayer == i) + sb.AppendLine("This is the layer actually in use."); + + break; + } + } + + return sb.ToString(); + } + + public static string PrettifyFormatLayers(byte[] FormatLayersResponse) + { + RecognizedFormatLayers? decoded = DecodeFormatLayers(FormatLayersResponse); + + return PrettifyFormatLayers(decoded); + } + + public struct RecognizedFormatLayers + { + /// Bytes 0 to 1 Data Length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4 Number of format layers in hybrid disc identified by drive + public byte NumberOfLayers; + /// Byte 5, bits 7 to 6 Reserved + public byte Reserved3; + /// Byte 5, bits 5 to 4 Layer no. used when disc is inserted + public byte DefaultFormatLayer; + /// Byte 5, bits 3 to 2 Reserved + public byte Reserved4; + /// Byte 5, bits 1 to 0 Layer no. currently in use + public byte OnlineFormatLayer; + /// Bytes 6 to end Recognized format layers + public ushort[] FormatLayers; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/MMC/TrackInformation.cs b/Aaru.Decoders/SCSI/MMC/TrackInformation.cs new file mode 100644 index 000000000..b8b8aafd0 --- /dev/null +++ b/Aaru.Decoders/SCSI/MMC/TrackInformation.cs @@ -0,0 +1,110 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : TrackInformation.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.Decoders.SCSI.MMC +{ + public class TrackInformation + { + public bool Blank; + public bool Copy; + public bool Damage; + public ushort DataLength; + public byte DataMode; + public uint FixedPacketSize; + public bool FP; + public uint FreeBlocks; + public uint LastLayerJumpAddress; + public uint LastRecordedAddress; + public LayerJumpRecordingStatus LayerJumpRecordingStatus; + public ushort LogicalTrackNumber; + public uint LogicalTrackSize; + public uint LogicalTrackStartAddress; + public bool LraV; + public uint NextLayerJumpAddress; + public uint NextWritableAddress; + public bool NwaV; + public bool Packet; + public uint ReadCompatibilityLba; + public bool RT; + public ushort SessionNumber; + public byte TrackMode; + + public static TrackInformation Decode(byte[] response) + { + if(response.Length < 32) + return null; + + var decoded = new TrackInformation + { + DataLength = (ushort)((response[0] << 8) + response[1]), + LogicalTrackNumber = response[2], + SessionNumber = response[3], + LayerJumpRecordingStatus = (LayerJumpRecordingStatus)(response[5] >> 6), + Damage = (response[5] & 0x20) == 0x20, + Copy = (response[5] & 0x10) == 0x10, + TrackMode = (byte)(response[5] & 0xF), + RT = (response[6] & 0x80) == 0x80, + Blank = (response[6] & 0x40) == 0x40, + Packet = (response[6] & 0x20) == 0x20, + FP = (response[6] & 0x10) == 0x10, + DataMode = (byte)(response[6] & 0xF), + LraV = (response[7] & 0x02) == 0x02, + NwaV = (response[7] & 0x01) == 0x01, + LogicalTrackStartAddress = + (uint)((response[8] << 24) + (response[9] << 16) + (response[10] << 8) + response[11]), + NextWritableAddress = + (uint)((response[12] << 24) + (response[13] << 16) + (response[14] << 8) + response[15]), + FreeBlocks = (uint)((response[16] << 24) + (response[17] << 16) + (response[18] << 8) + response[19]), + FixedPacketSize = + (uint)((response[20] << 24) + (response[21] << 16) + (response[22] << 8) + response[23]), + LogicalTrackSize = + (uint)((response[24] << 24) + (response[25] << 16) + (response[26] << 8) + response[27]), + LastRecordedAddress = + (uint)((response[28] << 24) + (response[29] << 16) + (response[30] << 8) + response[31]) + }; + + if(response.Length < 48) + return decoded; + + decoded.LogicalTrackNumber += (ushort)(response[32] << 8); + + decoded.SessionNumber += (ushort)(response[33] << 8); + + decoded.ReadCompatibilityLba = + (uint)((response[36] << 24) + (response[37] << 16) + (response[38] << 8) + response[39]); + + decoded.NextLayerJumpAddress = + (uint)((response[40] << 24) + (response[41] << 16) + (response[42] << 8) + response[43]); + + decoded.LastLayerJumpAddress = + (uint)((response[44] << 24) + (response[45] << 16) + (response[46] << 8) + response[47]); + + return decoded; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/MMC/WriteProtect.cs b/Aaru.Decoders/SCSI/MMC/WriteProtect.cs new file mode 100644 index 000000000..f8cbcbc32 --- /dev/null +++ b/Aaru.Decoders/SCSI/MMC/WriteProtect.cs @@ -0,0 +1,157 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : WriteProtect.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MMC write protection structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Helpers; + +namespace Aaru.Decoders.SCSI.MMC +{ + // Information from the following standards: + // ANSI X3.304-1997 + // T10/1048-D revision 9.0 + // T10/1048-D revision 10a + // T10/1228-D revision 7.0c + // T10/1228-D revision 11a + // T10/1363-D revision 10g + // T10/1545-D revision 1d + // T10/1545-D revision 5 + // T10/1545-D revision 5a + // T10/1675-D revision 2c + // T10/1675-D revision 4 + // T10/1836-D revision 2g + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class WriteProtect + { + public static WriteProtectionStatus? DecodeWriteProtectionStatus(byte[] WPSResponse) + { + if(WPSResponse == null) + return null; + + var decoded = new WriteProtectionStatus + { + DataLength = BigEndianBitConverter.ToUInt16(WPSResponse, 0), + Reserved1 = WPSResponse[2], + Reserved2 = WPSResponse[3], + Reserved3 = (byte)((WPSResponse[4] & 0xF0) >> 4), + MSWI = Convert.ToBoolean(WPSResponse[4] & 0x08), + CWP = Convert.ToBoolean(WPSResponse[4] & 0x04), + PWP = Convert.ToBoolean(WPSResponse[4] & 0x02), + SWPP = Convert.ToBoolean(WPSResponse[4] & 0x01), + Reserved4 = WPSResponse[5], + Reserved5 = WPSResponse[6], + Reserved6 = WPSResponse[7] + }; + + return decoded; + } + + public static string PrettifyWriteProtectionStatus(WriteProtectionStatus? WPSResponse) + { + if(WPSResponse == null) + return null; + + WriteProtectionStatus response = WPSResponse.Value; + + var sb = new StringBuilder(); + + if(response.MSWI) + sb.AppendLine("Writing inhibited by media specific reason"); + + if(response.CWP) + sb.AppendLine("Cartridge sets write protection"); + + if(response.PWP) + sb.AppendLine("Media surface sets write protection"); + + if(response.SWPP) + sb.AppendLine("Software write protection is set until power down"); + + #if DEBUG + if(response.Reserved1 != 0) + sb.AppendFormat("Reserved1 = 0x{0:X2}", response.Reserved1).AppendLine(); + + if(response.Reserved2 != 0) + sb.AppendFormat("Reserved2 = 0x{0:X2}", response.Reserved2).AppendLine(); + + if(response.Reserved3 != 0) + sb.AppendFormat("Reserved3 = 0x{0:X2}", response.Reserved3).AppendLine(); + + if(response.Reserved4 != 0) + sb.AppendFormat("Reserved4 = 0x{0:X2}", response.Reserved4).AppendLine(); + + if(response.Reserved5 != 0) + sb.AppendFormat("Reserved5 = 0x{0:X2}", response.Reserved5).AppendLine(); + + if(response.Reserved6 != 0) + sb.AppendFormat("Reserved6 = 0x{0:X2}", response.Reserved6).AppendLine(); + #endif + + return sb.ToString(); + } + + public static string PrettifyWriteProtectionStatus(byte[] WPSResponse) + { + WriteProtectionStatus? decoded = DecodeWriteProtectionStatus(WPSResponse); + + return PrettifyWriteProtectionStatus(decoded); + } + + public struct WriteProtectionStatus + { + /// Bytes 0 to 1 Data Length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + /// Byte 4, bits 7 to 4 Reserved + public byte Reserved3; + /// Byte 4, bit 3 Writing inhibited by media specific reason + public bool MSWI; + /// Byte 4, bit 2 Cartridge sets write protection + public bool CWP; + /// Byte 4, bit 1 Media surface sets write protection + public bool PWP; + /// Byte 4, bit 0 Software write protection until power down + public bool SWPP; + /// Byte 5 Reserved + public byte Reserved4; + /// Byte 6 Reserved + public byte Reserved5; + /// Byte 7 Reserved + public byte Reserved6; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/00_SFF.cs b/Aaru.Decoders/SCSI/Modes/00_SFF.cs new file mode 100644 index 000000000..251b648c8 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/00_SFF.cs @@ -0,0 +1,117 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 00_SFF.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 00h: Drive Operation Mode page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x00: Drive Operation Mode page + /// Drive Operation Mode page Page code 0x00 4 bytes in INF-8070 + public struct ModePage_00_SFF + { + /// Parameters can be saved + public bool PS; + /// Select LUN Mode + public bool SLM; + /// Select LUN for rewritable + public bool SLR; + /// Disable verify for WRITE + public bool DVW; + /// Disable deferred error + public bool DDE; + } + + public static ModePage_00_SFF? DecodeModePage_00_SFF(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x00) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 4) + return null; + + var decoded = new ModePage_00_SFF(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + + decoded.SLM |= (pageResponse[2] & 0x80) == 0x80; + decoded.SLR |= (pageResponse[2] & 0x40) == 0x40; + decoded.DVW |= (pageResponse[2] & 0x20) == 0x20; + + decoded.DDE |= (pageResponse[3] & 0x10) == 0x10; + + return decoded; + } + + public static string PrettifyModePage_00_SFF(byte[] pageResponse) => + PrettifyModePage_00_SFF(DecodeModePage_00_SFF(pageResponse)); + + public static string PrettifyModePage_00_SFF(ModePage_00_SFF? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_00_SFF page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Drive Operation Mode page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.DVW) + sb.AppendLine("\tVerifying after writing is disabled"); + + if(page.DDE) + sb.AppendLine("\tDrive will abort when a writing error is detected"); + + if(!page.SLM) + return sb.ToString(); + + sb.Append("\tDrive has two LUNs with rewritable being "); + sb.AppendLine(page.SLR ? "LUN 1" : "LUN 0"); + + return sb.ToString(); + } + #endregion Mode Page 0x00: Drive Operation Mode page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/01.cs b/Aaru.Decoders/SCSI/Modes/01.cs new file mode 100644 index 000000000..77ec41b18 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/01.cs @@ -0,0 +1,229 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 01.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes and encodes SCSI MODE PAGE 01h: Read-write error recovery page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + public static byte[] EncodeModePage_01(ModePage_01 page) + { + byte[] pg = new byte[8]; + + pg[0] = 0x01; + pg[1] = 6; + + if(page.PS) + pg[0] += 0x80; + + if(page.AWRE) + pg[2] += 0x80; + + if(page.ARRE) + pg[2] += 0x40; + + if(page.TB) + pg[2] += 0x20; + + if(page.RC) + pg[2] += 0x10; + + if(page.EER) + pg[2] += 0x08; + + if(page.PER) + pg[2] += 0x04; + + if(page.DTE) + pg[2] += 0x02; + + if(page.DCR) + pg[2] += 0x01; + + pg[3] = page.ReadRetryCount; + pg[4] = page.CorrectionSpan; + pg[5] = (byte)page.HeadOffsetCount; + pg[6] = (byte)page.DataStrobeOffsetCount; + + // This is from a newer version of SCSI unknown what happen for drives expecting an 8 byte page + /* + pg[8] = page.WriteRetryCount; + if (page.LBPERE) + pg[7] += 0x80; + pg[10] = (byte)((page.RecoveryTimeLimit & 0xFF00) << 8); + pg[11] = (byte)(page.RecoveryTimeLimit & 0xFF);*/ + + return pg; + } + + #region Mode Page 0x01: Read-write error recovery page + /// Disconnect-reconnect page Page code 0x01 12 bytes in SCSI-2, SBC-1, SBC-2 + public struct ModePage_01 + { + /// Parameters can be saved + public bool PS; + /// Automatic Write Reallocation Enabled + public bool AWRE; + /// Automatic Read Reallocation Enabled + public bool ARRE; + /// Transfer block + public bool TB; + /// Read continuous + public bool RC; + /// Enable early recovery + public bool EER; + /// Post error reporting + public bool PER; + /// Disable transfer on error + public bool DTE; + /// Disable correction + public bool DCR; + /// How many times to retry a read operation + public byte ReadRetryCount; + /// How many bits of largest data burst error is maximum to apply error correction on it + public byte CorrectionSpan; + /// Offset to move the heads + public sbyte HeadOffsetCount; + /// Incremental position to which the recovered data strobe shall be adjusted + public sbyte DataStrobeOffsetCount; + /// How many times to retry a write operation + public byte WriteRetryCount; + /// Maximum time in ms to use in data error recovery procedures + public ushort RecoveryTimeLimit; + + /// Logical block provisioning error reporting is enabled + public bool LBPERE; + } + + public static ModePage_01? DecodeModePage_01(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x01) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 8) + return null; + + var decoded = new ModePage_01(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.AWRE |= (pageResponse[2] & 0x80) == 0x80; + decoded.ARRE |= (pageResponse[2] & 0x40) == 0x40; + decoded.TB |= (pageResponse[2] & 0x20) == 0x20; + decoded.RC |= (pageResponse[2] & 0x10) == 0x10; + decoded.EER |= (pageResponse[2] & 0x08) == 0x08; + decoded.PER |= (pageResponse[2] & 0x04) == 0x04; + decoded.DTE |= (pageResponse[2] & 0x02) == 0x02; + decoded.DCR |= (pageResponse[2] & 0x01) == 0x01; + + decoded.ReadRetryCount = pageResponse[3]; + decoded.CorrectionSpan = pageResponse[4]; + decoded.HeadOffsetCount = (sbyte)pageResponse[5]; + decoded.DataStrobeOffsetCount = (sbyte)pageResponse[6]; + + if(pageResponse.Length < 12) + return decoded; + + decoded.WriteRetryCount = pageResponse[8]; + decoded.RecoveryTimeLimit = (ushort)((pageResponse[10] << 8) + pageResponse[11]); + decoded.LBPERE |= (pageResponse[7] & 0x80) == 0x80; + + return decoded; + } + + public static string PrettifyModePage_01(byte[] pageResponse) => + PrettifyModePage_01(DecodeModePage_01(pageResponse)); + + public static string PrettifyModePage_01(ModePage_01? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_01 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Read-write error recovery page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.AWRE) + sb.AppendLine("\tAutomatic write reallocation is enabled"); + + if(page.ARRE) + sb.AppendLine("\tAutomatic read reallocation is enabled"); + + if(page.TB) + sb.AppendLine("\tData not recovered within limits shall be transferred back before a CHECK CONDITION"); + + if(page.RC) + sb.AppendLine("\tDrive will transfer the entire requested length without delaying to perform error recovery"); + + if(page.EER) + sb.AppendLine("\tDrive will use the most expedient form of error recovery first"); + + if(page.PER) + sb.AppendLine("\tDrive shall report recovered errors"); + + if(page.DTE) + sb.AppendLine("\tTransfer will be terminated upon error detection"); + + if(page.DCR) + sb.AppendLine("\tError correction is disabled"); + + if(page.ReadRetryCount > 0) + sb.AppendFormat("\tDrive will repeat read operations {0} times", page.ReadRetryCount).AppendLine(); + + if(page.WriteRetryCount > 0) + sb.AppendFormat("\tDrive will repeat write operations {0} times", page.WriteRetryCount).AppendLine(); + + if(page.RecoveryTimeLimit > 0) + sb.AppendFormat("\tDrive will employ a maximum of {0} ms to recover data", page.RecoveryTimeLimit). + AppendLine(); + + if(page.LBPERE) + sb.AppendLine("Logical block provisioning error reporting is enabled"); + + return sb.ToString(); + } + #endregion Mode Page 0x01: Read-write error recovery page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/01_MMC.cs b/Aaru.Decoders/SCSI/Modes/01_MMC.cs new file mode 100644 index 000000000..86b71ed2b --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/01_MMC.cs @@ -0,0 +1,234 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 01_MMC.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 01h: Read error recovery page for MultiMedia Devices. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + public static byte[] EncodeModePage_01_MMC(ModePage_01_MMC page) + { + byte[] pg = new byte[12]; + + pg[0] = 0x01; + pg[1] = 10; + + if(page.PS) + pg[0] += 0x80; + + pg[2] = page.Parameter; + pg[3] = page.ReadRetryCount; + + // This is from a newer version of SCSI unknown what happen for drives expecting an 8 byte page + + pg[8] = page.WriteRetryCount; + pg[10] = (byte)((page.RecoveryTimeLimit & 0xFF00) << 8); + pg[11] = (byte)(page.RecoveryTimeLimit & 0xFF); + + return pg; + } + + #region Mode Page 0x01: Read error recovery page for MultiMedia Devices + /// + /// Read error recovery page for MultiMedia Devices Page code 0x01 8 bytes in SCSI-2, MMC-1 12 bytes in MMC-2, + /// MMC-3 + /// + public struct ModePage_01_MMC + { + /// Parameters can be saved + public bool PS; + /// Error recovery parameter + public byte Parameter; + /// How many times to retry a read operation + public byte ReadRetryCount; + /// How many times to retry a write operation + public byte WriteRetryCount; + /// Maximum time in ms to use in data error recovery procedures + public ushort RecoveryTimeLimit; + } + + public static ModePage_01_MMC? DecodeModePage_01_MMC(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x01) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 8) + return null; + + var decoded = new ModePage_01_MMC(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.Parameter = pageResponse[2]; + decoded.ReadRetryCount = pageResponse[3]; + + if(pageResponse.Length < 12) + return decoded; + + decoded.WriteRetryCount = pageResponse[8]; + decoded.RecoveryTimeLimit = (ushort)((pageResponse[10] << 8) + pageResponse[11]); + + return decoded; + } + + public static string PrettifyModePage_01_MMC(byte[] pageResponse) => + PrettifyModePage_01_MMC(DecodeModePage_01_MMC(pageResponse)); + + public static string PrettifyModePage_01_MMC(ModePage_01_MMC? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_01_MMC page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Read error recovery page for MultiMedia Devices:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.ReadRetryCount > 0) + sb.AppendFormat("\tDrive will repeat read operations {0} times", page.ReadRetryCount).AppendLine(); + + string AllUsed = "\tAll available recovery procedures will be used.\n"; + string CIRCRetriesUsed = "\tOnly retries and CIRC are used.\n"; + string RetriesUsed = "\tOnly retries are used.\n"; + string RecoveredNotReported = "\tRecovered errors will not be reported.\n"; + string RecoveredReported = "\tRecovered errors will be reported.\n"; + string RecoveredAbort = "\tRecovered errors will be reported and aborted with CHECK CONDITION.\n"; + string UnrecECCAbort = "\tUnrecovered ECC errors will return CHECK CONDITION."; + string UnrecCIRCAbort = "\tUnrecovered CIRC errors will return CHECK CONDITION."; + string UnrecECCNotAbort = "\tUnrecovered ECC errors will not abort the transfer."; + string UnrecCIRCNotAbort = "\tUnrecovered CIRC errors will not abort the transfer."; + + string UnrecECCAbortData = "\tUnrecovered ECC errors will return CHECK CONDITION and the uncorrected data."; + + string UnrecCIRCAbortData = + "\tUnrecovered CIRC errors will return CHECK CONDITION and the uncorrected data."; + + switch(page.Parameter) + { + case 0x00: + sb.AppendLine(AllUsed + RecoveredNotReported + UnrecECCAbort); + + break; + case 0x01: + sb.AppendLine(CIRCRetriesUsed + RecoveredNotReported + UnrecCIRCAbort); + + break; + case 0x04: + sb.AppendLine(AllUsed + RecoveredReported + UnrecECCAbort); + + break; + case 0x05: + sb.AppendLine(CIRCRetriesUsed + RecoveredReported + UnrecCIRCAbort); + + break; + case 0x06: + sb.AppendLine(AllUsed + RecoveredAbort + UnrecECCAbort); + + break; + case 0x07: + sb.AppendLine(RetriesUsed + RecoveredAbort + UnrecCIRCAbort); + + break; + case 0x10: + sb.AppendLine(AllUsed + RecoveredNotReported + UnrecECCNotAbort); + + break; + case 0x11: + sb.AppendLine(CIRCRetriesUsed + RecoveredNotReported + UnrecCIRCNotAbort); + + break; + case 0x14: + sb.AppendLine(AllUsed + RecoveredReported + UnrecECCNotAbort); + + break; + case 0x15: + sb.AppendLine(CIRCRetriesUsed + RecoveredReported + UnrecCIRCNotAbort); + + break; + case 0x20: + sb.AppendLine(AllUsed + RecoveredNotReported + UnrecECCAbortData); + + break; + case 0x21: + sb.AppendLine(CIRCRetriesUsed + RecoveredNotReported + UnrecCIRCAbortData); + + break; + case 0x24: + sb.AppendLine(AllUsed + RecoveredReported + UnrecECCAbortData); + + break; + case 0x25: + sb.AppendLine(CIRCRetriesUsed + RecoveredReported + UnrecCIRCAbortData); + + break; + case 0x26: + sb.AppendLine(AllUsed + RecoveredAbort + UnrecECCAbortData); + + break; + case 0x27: + sb.AppendLine(RetriesUsed + RecoveredAbort + UnrecCIRCAbortData); + + break; + case 0x30: goto case 0x10; + case 0x31: goto case 0x11; + case 0x34: goto case 0x14; + case 0x35: goto case 0x15; + default: + sb.AppendFormat("Unknown recovery parameter 0x{0:X2}", page.Parameter).AppendLine(); + + break; + } + + if(page.WriteRetryCount > 0) + sb.AppendFormat("\tDrive will repeat write operations {0} times", page.WriteRetryCount).AppendLine(); + + if(page.RecoveryTimeLimit > 0) + sb.AppendFormat("\tDrive will employ a maximum of {0} ms to recover data", page.RecoveryTimeLimit). + AppendLine(); + + return sb.ToString(); + } + #endregion Mode Page 0x01: Read error recovery page for MultiMedia Devices + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/02.cs b/Aaru.Decoders/SCSI/Modes/02.cs new file mode 100644 index 000000000..719f07340 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/02.cs @@ -0,0 +1,190 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 02.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 02h: Disconnect-reconnect page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x02: Disconnect-reconnect page + /// Disconnect-reconnect page Page code 0x02 16 bytes in SCSI-2, SPC-1, SPC-2, SPC-3, SPC-4, SPC-5 + public struct ModePage_02 + { + /// Parameters can be saved + public bool PS; + /// How full should be the buffer prior to attempting a reselection + public byte BufferFullRatio; + /// How empty should be the buffer prior to attempting a reselection + public byte BufferEmptyRatio; + /// Max. time in 100 µs increments that the target is permitted to assert BSY without a REQ/ACK + public ushort BusInactivityLimit; + /// Min. time in 100 µs increments to wait after releasing the bus before attempting reselection + public ushort DisconnectTimeLimit; + /// + /// Max. time in 100 µs increments allowed to use the bus before disconnecting, if granted the privilege and not + /// restricted by + /// + public ushort ConnectTimeLimit; + /// Maximum amount of data before disconnecting in 512 bytes increments + public ushort MaxBurstSize; + /// Data transfer disconnect control + public byte DTDC; + + /// Target shall not transfer data for a command during the same interconnect tenancy + public bool DIMM; + /// Wether to use fair or unfair arbitration when requesting an interconnect tenancy + public byte FairArbitration; + /// Max. ammount of data in 512 bytes increments that may be transferred for a command along with the command + public ushort FirstBurstSize; + /// Target is allowed to re-order the data transfer + public bool EMDP; + } + + public static ModePage_02? DecodeModePage_02(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x02) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 12) + return null; + + var decoded = new ModePage_02(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.BufferFullRatio = pageResponse[2]; + decoded.BufferEmptyRatio = pageResponse[3]; + decoded.BusInactivityLimit = (ushort)((pageResponse[4] << 8) + pageResponse[5]); + decoded.DisconnectTimeLimit = (ushort)((pageResponse[6] << 8) + pageResponse[7]); + decoded.ConnectTimeLimit = (ushort)((pageResponse[8] << 8) + pageResponse[9]); + decoded.MaxBurstSize = (ushort)((pageResponse[10] << 8) + pageResponse[11]); + + if(pageResponse.Length >= 13) + { + decoded.EMDP |= (pageResponse[12] & 0x80) == 0x80; + decoded.DIMM |= (pageResponse[12] & 0x08) == 0x08; + decoded.FairArbitration = (byte)((pageResponse[12] & 0x70) >> 4); + decoded.DTDC = (byte)(pageResponse[12] & 0x07); + } + + if(pageResponse.Length >= 16) + decoded.FirstBurstSize = (ushort)((pageResponse[14] << 8) + pageResponse[15]); + + return decoded; + } + + public static string PrettifyModePage_02(byte[] pageResponse) => + PrettifyModePage_02(DecodeModePage_02(pageResponse)); + + public static string PrettifyModePage_02(ModePage_02? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_02 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Disconnect-Reconnect mode page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.BufferFullRatio > 0) + sb.AppendFormat("\t{0} ratio of buffer that shall be full prior to attempting a reselection", + page.BufferFullRatio).AppendLine(); + + if(page.BufferEmptyRatio > 0) + sb.AppendFormat("\t{0} ratio of buffer that shall be empty prior to attempting a reselection", + page.BufferEmptyRatio).AppendLine(); + + if(page.BusInactivityLimit > 0) + sb.AppendFormat("\t{0} µs maximum permitted to assert BSY without a REQ/ACK handshake", + page.BusInactivityLimit * 100).AppendLine(); + + if(page.DisconnectTimeLimit > 0) + sb.AppendFormat("\t{0} µs maximum permitted wait after releasing the bus before attempting reselection", + page.DisconnectTimeLimit * 100).AppendLine(); + + if(page.ConnectTimeLimit > 0) + sb. + AppendFormat("\t{0} µs allowed to use the bus before disconnecting, if granted the privilege and not restricted", + page.ConnectTimeLimit * 100).AppendLine(); + + if(page.MaxBurstSize > 0) + sb.AppendFormat("\t{0} bytes maximum can be transferred before disconnecting", page.MaxBurstSize * 512). + AppendLine(); + + if(page.FirstBurstSize > 0) + sb. + AppendFormat("\t{0} bytes maximum can be transferred for a command along with the disconnect command", + page.FirstBurstSize * 512).AppendLine(); + + if(page.DIMM) + sb.AppendLine("\tTarget shall not transfer data for a command during the same interconnect tenancy"); + + if(page.EMDP) + sb.AppendLine("\tTarget is allowed to re-order the data transfer"); + + switch(page.DTDC) + { + case 0: + sb.AppendLine("\tData transfer disconnect control is not used"); + + break; + case 1: + sb.AppendLine("\tAll data for a command shall be transferred within a single interconnect tenancy"); + + break; + case 3: + sb.AppendLine("\tAll data and the response for a command shall be transferred within a single interconnect tenancy"); + + break; + default: + sb.AppendFormat("\tReserved data transfer disconnect control value {0}", page.DTDC).AppendLine(); + + break; + } + + return sb.ToString(); + } + #endregion Mode Page 0x02: Disconnect-reconnect page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/03.cs b/Aaru.Decoders/SCSI/Modes/03.cs new file mode 100644 index 000000000..7e1a6a405 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/03.cs @@ -0,0 +1,169 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 03.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 03h: Format device page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x03: Format device page + /// Disconnect-reconnect page Page code 0x03 24 bytes in SCSI-2, SBC-1 + public struct ModePage_03 + { + /// Parameters can be saved + public bool PS; + /// Tracks per zone to use in dividing the capacity for the purpose of allocating alternate sectors + public ushort TracksPerZone; + /// Number of sectors per zone that shall be reserved for defect handling + public ushort AltSectorsPerZone; + /// Number of tracks per zone that shall be reserved for defect handling + public ushort AltTracksPerZone; + /// Number of tracks per LUN that shall be reserved for defect handling + public ushort AltTracksPerLun; + /// Number of physical sectors per track + public ushort SectorsPerTrack; + /// Bytes per physical sector + public ushort BytesPerSector; + /// Interleave value, target dependent + public ushort Interleave; + /// Sectors between last block of one track and first block of the next + public ushort TrackSkew; + /// Sectors between last block of a cylinder and first block of the next one + public ushort CylinderSkew; + /// Soft-sectored + public bool SSEC; + /// Hard-sectored + public bool HSEC; + /// Removable + public bool RMB; + /// + /// If set, address are allocated progressively in a surface before going to the next. Otherwise, it goes by + /// cylinders + /// + public bool SURF; + } + + public static ModePage_03? DecodeModePage_03(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x03) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 24) + return null; + + var decoded = new ModePage_03(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.TracksPerZone = (ushort)((pageResponse[2] << 8) + pageResponse[3]); + decoded.AltSectorsPerZone = (ushort)((pageResponse[4] << 8) + pageResponse[5]); + decoded.AltTracksPerZone = (ushort)((pageResponse[6] << 8) + pageResponse[7]); + decoded.AltTracksPerLun = (ushort)((pageResponse[8] << 8) + pageResponse[9]); + decoded.SectorsPerTrack = (ushort)((pageResponse[10] << 8) + pageResponse[11]); + decoded.BytesPerSector = (ushort)((pageResponse[12] << 8) + pageResponse[13]); + decoded.Interleave = (ushort)((pageResponse[14] << 8) + pageResponse[15]); + decoded.TrackSkew = (ushort)((pageResponse[16] << 8) + pageResponse[17]); + decoded.CylinderSkew = (ushort)((pageResponse[18] << 8) + pageResponse[19]); + decoded.SSEC |= (pageResponse[20] & 0x80) == 0x80; + decoded.HSEC |= (pageResponse[20] & 0x40) == 0x40; + decoded.RMB |= (pageResponse[20] & 0x20) == 0x20; + decoded.SURF |= (pageResponse[20] & 0x10) == 0x10; + + return decoded; + } + + public static string PrettifyModePage_03(byte[] pageResponse) => + PrettifyModePage_03(DecodeModePage_03(pageResponse)); + + public static string PrettifyModePage_03(ModePage_03? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_03 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Format device page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + sb. + AppendFormat("\t{0} tracks per zone to use in dividing the capacity for the purpose of allocating alternate sectors", + page.TracksPerZone).AppendLine(); + + sb.AppendFormat("\t{0} sectors per zone that shall be reserved for defect handling", + page.AltSectorsPerZone).AppendLine(); + + sb.AppendFormat("\t{0} tracks per zone that shall be reserved for defect handling", page.AltTracksPerZone). + AppendLine(); + + sb.AppendFormat("\t{0} tracks per LUN that shall be reserved for defect handling", page.AltTracksPerLun). + AppendLine(); + + sb.AppendFormat("\t{0} physical sectors per track", page.SectorsPerTrack).AppendLine(); + sb.AppendFormat("\t{0} Bytes per physical sector", page.BytesPerSector).AppendLine(); + sb.AppendFormat("\tTarget-dependent interleave value is {0}", page.Interleave).AppendLine(); + + sb.AppendFormat("\t{0} sectors between last block of one track and first block of the next", + page.TrackSkew).AppendLine(); + + sb.AppendFormat("\t{0} sectors between last block of a cylinder and first block of the next one", + page.CylinderSkew).AppendLine(); + + if(page.SSEC) + sb.AppendLine("\tDrive supports soft-sectoring format"); + + if(page.HSEC) + sb.AppendLine("\tDrive supports hard-sectoring format"); + + if(page.RMB) + sb.AppendLine("\tDrive media is removable"); + + sb.AppendLine(page.SURF + ? "\tSector addressing is progressively incremented in one surface before going to the next" + : "\tSector addressing is progressively incremented in one cylinder before going to the next"); + + return sb.ToString(); + } + #endregion Mode Page 0x03: Format device page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/04.cs b/Aaru.Decoders/SCSI/Modes/04.cs new file mode 100644 index 000000000..21dfc9827 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/04.cs @@ -0,0 +1,162 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 04.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 04h: Rigid disk drive geometry page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x04: Rigid disk drive geometry page + /// Disconnect-reconnect page Page code 0x04 24 bytes in SCSI-2, SBC-1 + public struct ModePage_04 + { + /// Parameters can be saved + public bool PS; + /// Cylinders used for data storage + public uint Cylinders; + /// Heads for reading and/or writing + public byte Heads; + /// Cylinder where write precompensation starts + public uint WritePrecompCylinder; + /// Cylinder where write current reduction starts + public uint WriteReduceCylinder; + /// Step rate in 100 ns units + public ushort DriveStepRate; + /// Cylinder where the heads park + public int LandingCylinder; + /// Rotational position locking + public byte RPL; + /// Rotational skew to apply when synchronized + public byte RotationalOffset; + /// Medium speed in rpm + public ushort MediumRotationRate; + } + + public static ModePage_04? DecodeModePage_04(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x04) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 20) + return null; + + var decoded = new ModePage_04(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.Cylinders = (uint)((pageResponse[2] << 16) + (pageResponse[3] << 8) + pageResponse[4]); + decoded.Heads = pageResponse[5]; + decoded.WritePrecompCylinder = (uint)((pageResponse[6] << 16) + (pageResponse[7] << 8) + pageResponse[8]); + + decoded.WriteReduceCylinder = (uint)((pageResponse[9] << 16) + (pageResponse[10] << 8) + pageResponse[11]); + + decoded.DriveStepRate = (ushort)((pageResponse[12] << 8) + pageResponse[13]); + + decoded.LandingCylinder = (pageResponse[14] << 16) + (pageResponse[15] << 8) + pageResponse[16]; + decoded.RPL = (byte)(pageResponse[17] & 0x03); + decoded.RotationalOffset = pageResponse[18]; + + if(pageResponse.Length >= 22) + decoded.MediumRotationRate = (ushort)((pageResponse[20] << 8) + pageResponse[21]); + + return decoded; + } + + public static string PrettifyModePage_04(byte[] pageResponse) => + PrettifyModePage_04(DecodeModePage_04(pageResponse)); + + public static string PrettifyModePage_04(ModePage_04? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_04 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Rigid disk drive geometry page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + sb.AppendFormat("\t{0} heads", page.Heads).AppendLine(); + sb.AppendFormat("\t{0} cylinders", page.Cylinders).AppendLine(); + + if(page.WritePrecompCylinder < page.Cylinders) + sb.AppendFormat("\tWrite pre-compensation starts at cylinder {0}", page.WritePrecompCylinder). + AppendLine(); + + if(page.WriteReduceCylinder < page.Cylinders) + sb.AppendFormat("\tWrite current reduction starts at cylinder {0}", page.WriteReduceCylinder). + AppendLine(); + + if(page.DriveStepRate > 0) + sb.AppendFormat("\tDrive steps in {0} ns", (uint)page.DriveStepRate * 100).AppendLine(); + + sb.AppendFormat("\tHeads park in cylinder {0}", page.LandingCylinder).AppendLine(); + + if(page.MediumRotationRate > 0) + sb.AppendFormat("\tMedium rotates at {0} rpm", page.MediumRotationRate).AppendLine(); + + switch(page.RPL) + { + case 0: + sb.AppendLine("\tSpindle synchronization is disable or unsupported"); + + break; + case 1: + sb.AppendLine("\tTarget operates as a synchronized-spindle slave"); + + break; + case 2: + sb.AppendLine("\tTarget operates as a synchronized-spindle master"); + + break; + case 3: + sb.AppendLine("\tTarget operates as a synchronized-spindle master control"); + + break; + } + + return sb.ToString(); + } + #endregion Mode Page 0x04: Rigid disk drive geometry page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/05.cs b/Aaru.Decoders/SCSI/Modes/05.cs new file mode 100644 index 000000000..b5f9ac930 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/05.cs @@ -0,0 +1,313 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 05.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 05h: Flexible disk page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x05: Flexible disk page + /// Disconnect-reconnect page Page code 0x05 32 bytes in SCSI-2, SBC-1 + public struct ModePage_05 + { + /// Parameters can be saved + public bool PS; + /// Data rate of peripheral device on kbit/s + public ushort TransferRate; + /// Heads for reading and/or writing + public byte Heads; + /// Sectors per revolution per head + public byte SectorsPerTrack; + /// Bytes of data per sector + public ushort BytesPerSector; + /// Cylinders used for data storage + public ushort Cylinders; + /// Cylinder where write precompensation starts + public ushort WritePrecompCylinder; + /// Cylinder where write current reduction starts + public ushort WriteReduceCylinder; + /// Step rate in 100 μs units + public ushort DriveStepRate; + /// Width of step pulse in μs + public byte DriveStepPulse; + /// Head settle time in 100 μs units + public ushort HeadSettleDelay; + /// + /// If is true, specified in 1/10s of a second the time waiting for read status before + /// aborting medium access. Otherwise, indicates time to way before medimum access after motor on signal is asserted. + /// + public byte MotorOnDelay; + /// + /// Time in 1/10s of a second to wait before releasing the motor on signal after an idle condition. 0xFF means to + /// never release the signal + /// + public byte MotorOffDelay; + /// Specifies if a signal indicates that the medium is ready to be accessed + public bool TRDY; + /// If true sectors start with one. Otherwise, they start with zero. + public bool SSN; + /// If true specifies that motor on shall remain released. + public bool MO; + /// Number of additional step pulses per cylinder. + public byte SPC; + /// Write compensation value + public byte WriteCompensation; + /// Head loading time in ms. + public byte HeadLoadDelay; + /// Head unloading time in ms. + public byte HeadUnloadDelay; + /// Description of shugart's bus pin 34 usage + public byte Pin34; + /// Description of shugart's bus pin 2 usage + public byte Pin2; + /// Description of shugart's bus pin 4 usage + public byte Pin4; + /// Description of shugart's bus pin 1 usage + public byte Pin1; + /// Medium speed in rpm + public ushort MediumRotationRate; + } + + public static ModePage_05? DecodeModePage_05(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x05) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 32) + return null; + + var decoded = new ModePage_05(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.TransferRate = (ushort)((pageResponse[2] << 8) + pageResponse[3]); + decoded.Heads = pageResponse[4]; + decoded.SectorsPerTrack = pageResponse[5]; + decoded.BytesPerSector = (ushort)((pageResponse[6] << 8) + pageResponse[7]); + decoded.Cylinders = (ushort)((pageResponse[8] << 8) + pageResponse[9]); + decoded.WritePrecompCylinder = (ushort)((pageResponse[10] << 8) + pageResponse[11]); + decoded.WriteReduceCylinder = (ushort)((pageResponse[12] << 8) + pageResponse[13]); + decoded.DriveStepRate = (ushort)((pageResponse[14] << 8) + pageResponse[15]); + decoded.DriveStepPulse = pageResponse[16]; + decoded.HeadSettleDelay = (ushort)((pageResponse[17] << 8) + pageResponse[18]); + decoded.MotorOnDelay = pageResponse[19]; + decoded.MotorOffDelay = pageResponse[20]; + decoded.TRDY |= (pageResponse[21] & 0x80) == 0x80; + decoded.SSN |= (pageResponse[21] & 0x40) == 0x40; + decoded.MO |= (pageResponse[21] & 0x20) == 0x20; + decoded.SPC = (byte)(pageResponse[22] & 0x0F); + decoded.WriteCompensation = pageResponse[23]; + decoded.HeadLoadDelay = pageResponse[24]; + decoded.HeadUnloadDelay = pageResponse[25]; + decoded.Pin34 = (byte)((pageResponse[26] & 0xF0) >> 4); + decoded.Pin2 = (byte)(pageResponse[26] & 0x0F); + decoded.Pin4 = (byte)((pageResponse[27] & 0xF0) >> 4); + decoded.Pin1 = (byte)(pageResponse[27] & 0x0F); + decoded.MediumRotationRate = (ushort)((pageResponse[28] << 8) + pageResponse[29]); + + return decoded; + } + + public static string PrettifyModePage_05(byte[] pageResponse) => + PrettifyModePage_05(DecodeModePage_05(pageResponse)); + + public static string PrettifyModePage_05(ModePage_05? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_05 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Flexible disk page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + sb.AppendFormat("\tTransfer rate: {0} kbit/s", page.TransferRate).AppendLine(); + sb.AppendFormat("\t{0} heads", page.Heads).AppendLine(); + sb.AppendFormat("\t{0} cylinders", page.Cylinders).AppendLine(); + sb.AppendFormat("\t{0} sectors per track", page.SectorsPerTrack).AppendLine(); + sb.AppendFormat("\t{0} bytes per sector", page.BytesPerSector).AppendLine(); + + if(page.WritePrecompCylinder < page.Cylinders) + sb.AppendFormat("\tWrite pre-compensation starts at cylinder {0}", page.WritePrecompCylinder). + AppendLine(); + + if(page.WriteReduceCylinder < page.Cylinders) + sb.AppendFormat("\tWrite current reduction starts at cylinder {0}", page.WriteReduceCylinder). + AppendLine(); + + if(page.DriveStepRate > 0) + sb.AppendFormat("\tDrive steps in {0} μs", (uint)page.DriveStepRate * 100).AppendLine(); + + if(page.DriveStepPulse > 0) + sb.AppendFormat("\tEach step pulse is {0} ms", page.DriveStepPulse).AppendLine(); + + if(page.HeadSettleDelay > 0) + sb.AppendFormat("\tHeads settles in {0} μs", (uint)page.HeadSettleDelay * 100).AppendLine(); + + if(!page.TRDY) + sb. + AppendFormat("\tTarget shall wait {0} seconds before attempting to access the medium after motor on is asserted", + (double)page.MotorOnDelay * 10).AppendLine(); + else + sb. + AppendFormat("\tTarget shall wait {0} seconds after drive is ready before aborting medium access attemps", + (double)page.MotorOnDelay * 10).AppendLine(); + + if(page.MotorOffDelay != 0xFF) + sb. + AppendFormat("\tTarget shall wait {0} seconds before releasing the motor on signal after becoming idle", + (double)page.MotorOffDelay * 10).AppendLine(); + else + sb.AppendLine("\tTarget shall never release the motor on signal"); + + if(page.TRDY) + sb.AppendLine("\tThere is a drive ready signal"); + + if(page.SSN) + sb.AppendLine("\tSectors start at 1"); + + if(page.MO) + sb.AppendLine("\tThe motor on signal shall remain released"); + + sb.AppendFormat("\tDrive needs to do {0} step pulses per cylinder", page.SPC + 1).AppendLine(); + + if(page.WriteCompensation > 0) + sb.AppendFormat("\tWrite pre-compensation is {0}", page.WriteCompensation).AppendLine(); + + if(page.HeadLoadDelay > 0) + sb.AppendFormat("\tHead takes {0} ms to load", page.HeadLoadDelay).AppendLine(); + + if(page.HeadUnloadDelay > 0) + sb.AppendFormat("\tHead takes {0} ms to unload", page.HeadUnloadDelay).AppendLine(); + + if(page.MediumRotationRate > 0) + sb.AppendFormat("\tMedium rotates at {0} rpm", page.MediumRotationRate).AppendLine(); + + switch(page.Pin34 & 0x07) + { + case 0: + sb.AppendLine("\tPin 34 is unconnected"); + + break; + case 1: + sb.Append("\tPin 34 indicates drive is ready when active "); + sb.Append((page.Pin34 & 0x08) == 0x08 ? "high" : "low"); + + break; + case 2: + sb.Append("\tPin 34 indicates disk has changed when active "); + sb.Append((page.Pin34 & 0x08) == 0x08 ? "high" : "low"); + + break; + default: + sb.AppendFormat("\tPin 34 indicates unknown function {0} when active ", page.Pin34 & 0x07); + sb.Append((page.Pin34 & 0x08) == 0x08 ? "high" : "low"); + + break; + } + + switch(page.Pin4 & 0x07) + { + case 0: + sb.AppendLine("\tPin 4 is unconnected"); + + break; + case 1: + sb.Append("\tPin 4 indicates drive is in use when active "); + sb.Append((page.Pin4 & 0x08) == 0x08 ? "high" : "low"); + + break; + case 2: + sb.Append("\tPin 4 indicates eject when active "); + sb.Append((page.Pin4 & 0x08) == 0x08 ? "high" : "low"); + + break; + case 3: + sb.Append("\tPin 4 indicates head load when active "); + sb.Append((page.Pin4 & 0x08) == 0x08 ? "high" : "low"); + + break; + default: + sb.AppendFormat("\tPin 4 indicates unknown function {0} when active ", page.Pin4 & 0x07); + sb.Append((page.Pin4 & 0x08) == 0x08 ? "high" : "low"); + + break; + } + + switch(page.Pin2 & 0x07) + { + case 0: + sb.AppendLine("\tPin 2 is unconnected"); + + break; + default: + sb.AppendFormat("\tPin 2 indicates unknown function {0} when active ", page.Pin2 & 0x07); + sb.Append((page.Pin2 & 0x08) == 0x08 ? "high" : "low"); + + break; + } + + switch(page.Pin1 & 0x07) + { + case 0: + sb.AppendLine("\tPin 1 is unconnected"); + + break; + case 1: + sb.Append("\tPin 1 indicates disk change reset when active "); + sb.Append((page.Pin1 & 0x08) == 0x08 ? "high" : "low"); + + break; + default: + sb.AppendFormat("\tPin 1 indicates unknown function {0} when active ", page.Pin1 & 0x07); + sb.Append((page.Pin1 & 0x08) == 0x08 ? "high" : "low"); + + break; + } + + return sb.ToString(); + } + #endregion Mode Page 0x05: Flexible disk page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/06.cs b/Aaru.Decoders/SCSI/Modes/06.cs new file mode 100644 index 000000000..1855a744a --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/06.cs @@ -0,0 +1,97 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 06.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 06h: Optical memory page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x06: Optical memory page + /// Optical memory page Page code 0x06 4 bytes in SCSI-2 + public struct ModePage_06 + { + /// Parameters can be saved + public bool PS; + /// Report updated block read + public bool RUBR; + } + + public static ModePage_06? DecodeModePage_06(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x06) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 4) + return null; + + var decoded = new ModePage_06(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.RUBR |= (pageResponse[2] & 0x01) == 0x01; + + return decoded; + } + + public static string PrettifyModePage_06(byte[] pageResponse) => + PrettifyModePage_06(DecodeModePage_06(pageResponse)); + + public static string PrettifyModePage_06(ModePage_06? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_06 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI optical memory:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.RUBR) + sb.AppendLine("\tOn reading an updated block drive will return RECOVERED ERROR"); + + return sb.ToString(); + } + #endregion Mode Page 0x06: Optical memory page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/07.cs b/Aaru.Decoders/SCSI/Modes/07.cs new file mode 100644 index 000000000..b5932dc9b --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/07.cs @@ -0,0 +1,132 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 07.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 07h: Verify error recovery page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static partial class Modes + { + #region Mode Page 0x07: Verify error recovery page + /// Disconnect-reconnect page Page code 0x07 12 bytes in SCSI-2, SBC-1, SBC-2 + public struct ModePage_07 + { + /// Parameters can be saved + public bool PS; + /// Enable early recovery + public bool EER; + /// Post error reporting + public bool PER; + /// Disable transfer on error + public bool DTE; + /// Disable correction + public bool DCR; + /// How many times to retry a verify operation + public byte VerifyRetryCount; + /// How many bits of largest data burst error is maximum to apply error correction on it + public byte CorrectionSpan; + /// Maximum time in ms to use in data error recovery procedures + public ushort RecoveryTimeLimit; + } + + public static ModePage_07? DecodeModePage_07(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x07) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 12) + return null; + + var decoded = new ModePage_07(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.EER |= (pageResponse[2] & 0x08) == 0x08; + decoded.PER |= (pageResponse[2] & 0x04) == 0x04; + decoded.DTE |= (pageResponse[2] & 0x02) == 0x02; + decoded.DCR |= (pageResponse[2] & 0x01) == 0x01; + + decoded.VerifyRetryCount = pageResponse[3]; + decoded.CorrectionSpan = pageResponse[4]; + decoded.RecoveryTimeLimit = (ushort)((pageResponse[10] << 8) + pageResponse[11]); + + return decoded; + } + + public static string PrettifyModePage_07(byte[] pageResponse) => + PrettifyModePage_07(DecodeModePage_07(pageResponse)); + + public static string PrettifyModePage_07(ModePage_07? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_07 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Verify error recovery page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.EER) + sb.AppendLine("\tDrive will use the most expedient form of error recovery first"); + + if(page.PER) + sb.AppendLine("\tDrive shall report recovered errors"); + + if(page.DTE) + sb.AppendLine("\tTransfer will be terminated upon error detection"); + + if(page.DCR) + sb.AppendLine("\tError correction is disabled"); + + if(page.VerifyRetryCount > 0) + sb.AppendFormat("\tDrive will repeat verify operations {0} times", page.VerifyRetryCount).AppendLine(); + + if(page.RecoveryTimeLimit > 0) + sb.AppendFormat("\tDrive will employ a maximum of {0} ms to recover data", page.RecoveryTimeLimit). + AppendLine(); + + return sb.ToString(); + } + #endregion Mode Page 0x07: Verify error recovery page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/07_MMC.cs b/Aaru.Decoders/SCSI/Modes/07_MMC.cs new file mode 100644 index 000000000..857e9ab5e --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/07_MMC.cs @@ -0,0 +1,192 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 07_MMC.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 07h: Verify error recovery page for MultiMedia Devices. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x07: Verify error recovery page for MultiMedia Devices + /// Verify error recovery page for MultiMedia Devices Page code 0x07 8 bytes in SCSI-2, MMC-1 + public struct ModePage_07_MMC + { + /// Parameters can be saved + public bool PS; + /// Error recovery parameter + public byte Parameter; + /// How many times to retry a verify operation + public byte VerifyRetryCount; + } + + public static ModePage_07_MMC? DecodeModePage_07_MMC(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x07) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 8) + return null; + + var decoded = new ModePage_07_MMC(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.Parameter = pageResponse[2]; + decoded.VerifyRetryCount = pageResponse[3]; + + return decoded; + } + + public static string PrettifyModePage_07_MMC(byte[] pageResponse) => + PrettifyModePage_07_MMC(DecodeModePage_07_MMC(pageResponse)); + + public static string PrettifyModePage_07_MMC(ModePage_07_MMC? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_07_MMC page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Verify error recovery page for MultiMedia Devices:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.VerifyRetryCount > 0) + sb.AppendFormat("\tDrive will repeat verify operations {0} times", page.VerifyRetryCount).AppendLine(); + + string AllUsed = "\tAll available recovery procedures will be used.\n"; + string CIRCRetriesUsed = "\tOnly retries and CIRC are used.\n"; + string RetriesUsed = "\tOnly retries are used.\n"; + string RecoveredNotReported = "\tRecovered errors will not be reported.\n"; + string RecoveredReported = "\tRecovered errors will be reported.\n"; + string RecoveredAbort = "\tRecovered errors will be reported and aborted with CHECK CONDITION.\n"; + string UnrecECCAbort = "\tUnrecovered ECC errors will return CHECK CONDITION."; + string UnrecCIRCAbort = "\tUnrecovered CIRC errors will return CHECK CONDITION."; + string UnrecECCNotAbort = "\tUnrecovered ECC errors will not abort the transfer."; + string UnrecCIRCNotAbort = "\tUnrecovered CIRC errors will not abort the transfer."; + + string UnrecECCAbortData = "\tUnrecovered ECC errors will return CHECK CONDITION and the uncorrected data."; + + string UnrecCIRCAbortData = + "\tUnrecovered CIRC errors will return CHECK CONDITION and the uncorrected data."; + + switch(page.Parameter) + { + case 0x00: + sb.AppendLine(AllUsed + RecoveredNotReported + UnrecECCAbort); + + break; + case 0x01: + sb.AppendLine(CIRCRetriesUsed + RecoveredNotReported + UnrecCIRCAbort); + + break; + case 0x04: + sb.AppendLine(AllUsed + RecoveredReported + UnrecECCAbort); + + break; + case 0x05: + sb.AppendLine(CIRCRetriesUsed + RecoveredReported + UnrecCIRCAbort); + + break; + case 0x06: + sb.AppendLine(AllUsed + RecoveredAbort + UnrecECCAbort); + + break; + case 0x07: + sb.AppendLine(RetriesUsed + RecoveredAbort + UnrecCIRCAbort); + + break; + case 0x10: + sb.AppendLine(AllUsed + RecoveredNotReported + UnrecECCNotAbort); + + break; + case 0x11: + sb.AppendLine(CIRCRetriesUsed + RecoveredNotReported + UnrecCIRCNotAbort); + + break; + case 0x14: + sb.AppendLine(AllUsed + RecoveredReported + UnrecECCNotAbort); + + break; + case 0x15: + sb.AppendLine(CIRCRetriesUsed + RecoveredReported + UnrecCIRCNotAbort); + + break; + case 0x20: + sb.AppendLine(AllUsed + RecoveredNotReported + UnrecECCAbortData); + + break; + case 0x21: + sb.AppendLine(CIRCRetriesUsed + RecoveredNotReported + UnrecCIRCAbortData); + + break; + case 0x24: + sb.AppendLine(AllUsed + RecoveredReported + UnrecECCAbortData); + + break; + case 0x25: + sb.AppendLine(CIRCRetriesUsed + RecoveredReported + UnrecCIRCAbortData); + + break; + case 0x26: + sb.AppendLine(AllUsed + RecoveredAbort + UnrecECCAbortData); + + break; + case 0x27: + sb.AppendLine(RetriesUsed + RecoveredAbort + UnrecCIRCAbortData); + + break; + case 0x30: goto case 0x10; + case 0x31: goto case 0x11; + case 0x34: goto case 0x14; + case 0x35: goto case 0x15; + default: + sb.AppendFormat("Unknown recovery parameter 0x{0:X2}", page.Parameter).AppendLine(); + + break; + } + + return sb.ToString(); + } + #endregion Mode Page 0x07: Verify error recovery page for MultiMedia Devices + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/08.cs b/Aaru.Decoders/SCSI/Modes/08.cs new file mode 100644 index 000000000..6848b646e --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/08.cs @@ -0,0 +1,279 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 08.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 08h: Caching page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x08: Caching page + /// Disconnect-reconnect page Page code 0x08 12 bytes in SCSI-2 20 bytes in SBC-1, SBC-2, SBC-3 + public struct ModePage_08 + { + /// Parameters can be saved + public bool PS; + /// true if write cache is enabled + public bool WCE; + /// Multiplication factor + public bool MF; + /// true if read cache is enabled + public bool RCD; + /// Advices on reading-cache retention priority + public byte DemandReadRetentionPrio; + /// Advices on writing-cache retention priority + public byte WriteRetentionPriority; + /// If requested read blocks are more than this, no pre-fetch is done + public ushort DisablePreFetch; + /// Minimum pre-fetch + public ushort MinimumPreFetch; + /// Maximum pre-fetch + public ushort MaximumPreFetch; + /// Upper limit on maximum pre-fetch value + public ushort MaximumPreFetchCeiling; + + /// Manual cache controlling + public bool IC; + /// Abort pre-fetch + public bool ABPF; + /// Caching analysis permitted + public bool CAP; + /// Pre-fetch over discontinuities + public bool Disc; + /// is to be used to control caching segmentation + public bool Size; + /// Force sequential write + public bool FSW; + /// Logical block cache segment size + public bool LBCSS; + /// Disable read-ahead + public bool DRA; + /// How many segments should the cache be divided upon + public byte CacheSegments; + /// How many bytes should the cache be divided upon + public ushort CacheSegmentSize; + /// How many bytes should be used as a buffer when all other cached data cannot be evicted + public uint NonCacheSegmentSize; + + public bool NV_DIS; + } + + public static ModePage_08? DecodeModePage_08(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x08) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 12) + return null; + + var decoded = new ModePage_08(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.WCE |= (pageResponse[2] & 0x04) == 0x04; + decoded.MF |= (pageResponse[2] & 0x02) == 0x02; + decoded.RCD |= (pageResponse[2] & 0x01) == 0x01; + + decoded.DemandReadRetentionPrio = (byte)((pageResponse[3] & 0xF0) >> 4); + decoded.WriteRetentionPriority = (byte)(pageResponse[3] & 0x0F); + decoded.DisablePreFetch = (ushort)((pageResponse[4] << 8) + pageResponse[5]); + decoded.MinimumPreFetch = (ushort)((pageResponse[6] << 8) + pageResponse[7]); + decoded.MaximumPreFetch = (ushort)((pageResponse[8] << 8) + pageResponse[9]); + decoded.MaximumPreFetchCeiling = (ushort)((pageResponse[10] << 8) + pageResponse[11]); + + if(pageResponse.Length < 20) + return decoded; + + decoded.IC |= (pageResponse[2] & 0x80) == 0x80; + decoded.ABPF |= (pageResponse[2] & 0x40) == 0x40; + decoded.CAP |= (pageResponse[2] & 0x20) == 0x20; + decoded.Disc |= (pageResponse[2] & 0x10) == 0x10; + decoded.Size |= (pageResponse[2] & 0x08) == 0x08; + + decoded.FSW |= (pageResponse[12] & 0x80) == 0x80; + decoded.LBCSS |= (pageResponse[12] & 0x40) == 0x40; + decoded.DRA |= (pageResponse[12] & 0x20) == 0x20; + + decoded.CacheSegments = pageResponse[13]; + decoded.CacheSegmentSize = (ushort)((pageResponse[14] << 8) + pageResponse[15]); + decoded.NonCacheSegmentSize = (uint)((pageResponse[17] << 16) + (pageResponse[18] << 8) + pageResponse[19]); + + decoded.NV_DIS |= (pageResponse[12] & 0x01) == 0x01; + + return decoded; + } + + public static string PrettifyModePage_08(byte[] pageResponse) => + PrettifyModePage_08(DecodeModePage_08(pageResponse)); + + public static string PrettifyModePage_08(ModePage_08? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_08 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Caching mode page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.RCD) + sb.AppendLine("\tRead-cache is enabled"); + + if(page.WCE) + sb.AppendLine("\tWrite-cache is enabled"); + + switch(page.DemandReadRetentionPrio) + { + case 0: + sb.AppendLine("\tDrive does not distinguish between cached read data"); + + break; + case 1: + sb.AppendLine("\tData put by READ commands should be evicted from cache sooner than data put in read cache by other means"); + + break; + case 0xF: + sb.AppendLine("\tData put by READ commands should not be evicted if there is data cached by other means that can be evicted"); + + break; + default: + sb.AppendFormat("\tUnknown demand read retention priority value {0}", page.DemandReadRetentionPrio). + AppendLine(); + + break; + } + + switch(page.WriteRetentionPriority) + { + case 0: + sb.AppendLine("\tDrive does not distinguish between cached write data"); + + break; + case 1: + sb.AppendLine("\tData put by WRITE commands should be evicted from cache sooner than data put in write cache by other means"); + + break; + case 0xF: + sb.AppendLine("\tData put by WRITE commands should not be evicted if there is data cached by other means that can be evicted"); + + break; + default: + sb.AppendFormat("\tUnknown demand write retention priority value {0}", + page.DemandReadRetentionPrio).AppendLine(); + + break; + } + + if(page.DRA) + sb.AppendLine("\tRead-ahead is disabled"); + else + { + if(page.MF) + sb.AppendLine("\tPre-fetch values indicate a block multiplier"); + + if(page.DisablePreFetch == 0) + sb.AppendLine("\tNo pre-fetch will be done"); + else + { + sb.AppendFormat("\tPre-fetch will be done for READ commands of {0} blocks or less", + page.DisablePreFetch).AppendLine(); + + if(page.MinimumPreFetch > 0) + sb.AppendFormat("At least {0} blocks will be always pre-fetched", page.MinimumPreFetch). + AppendLine(); + + if(page.MaximumPreFetch > 0) + sb.AppendFormat("\tA maximum of {0} blocks will be pre-fetched", page.MaximumPreFetch). + AppendLine(); + + if(page.MaximumPreFetchCeiling > 0) + sb. + AppendFormat("\tA maximum of {0} blocks will be pre-fetched even if it is commanded to pre-fetch more", + page.MaximumPreFetchCeiling).AppendLine(); + + if(page.IC) + sb.AppendLine("\tDevice should use number of cache segments or cache segment size for caching"); + + if(page.ABPF) + sb.AppendLine("\tPre-fetch should be aborted upong receiving a new command"); + + if(page.CAP) + sb.AppendLine("\tCaching analysis is permitted"); + + if(page.Disc) + sb.AppendLine("\tPre-fetch can continue across discontinuities (such as cylinders or tracks)"); + } + } + + if(page.FSW) + sb.AppendLine("\tDrive should not reorder the sequence of write commands to be faster"); + + if(page.Size) + { + if(page.CacheSegmentSize > 0) + if(page.LBCSS) + sb.AppendFormat("\tDrive cache segments should be {0} blocks long", page.CacheSegmentSize). + AppendLine(); + else + sb.AppendFormat("\tDrive cache segments should be {0} bytes long", page.CacheSegmentSize). + AppendLine(); + } + else + { + if(page.CacheSegments > 0) + sb.AppendFormat("\tDrive should have {0} cache segments", page.CacheSegments).AppendLine(); + } + + if(page.NonCacheSegmentSize > 0) + sb. + AppendFormat("\tDrive shall allocate {0} bytes to buffer even when all cached data cannot be evicted", + page.NonCacheSegmentSize).AppendLine(); + + if(page.NV_DIS) + sb.AppendLine("\tNon-Volatile cache is disabled"); + + return sb.ToString(); + } + #endregion Mode Page 0x08: Caching page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/0A.cs b/Aaru.Decoders/SCSI/Modes/0A.cs new file mode 100644 index 000000000..68e9f473c --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/0A.cs @@ -0,0 +1,447 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 0A.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 0Ah: Control mode page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x0A: Control mode page + /// Control mode page Page code 0x0A 8 bytes in SCSI-2 12 bytes in SPC-1, SPC-2, SPC-3, SPC-4, SPC-5 + public struct ModePage_0A + { + /// Parameters can be saved + public bool PS; + /// If set, target shall report log exception conditions + public bool RLEC; + /// Queue algorithm modifier + public byte QueueAlgorithm; + /// + /// If set all remaining suspended I/O processes shall be aborted after the contingent allegiance condition or + /// extended contingent allegiance condition + /// + public byte QErr; + /// Tagged queuing is disabled + public bool DQue; + /// Extended Contingent Allegiance is enabled + public bool EECA; + /// Target may issue an asynchronous event notification upon completing its initialization + public bool RAENP; + /// Target may issue an asynchronous event notification instead of a unit attention condition + public bool UAAENP; + /// Target may issue an asynchronous event notification instead of a deferred error + public bool EAENP; + /// Minimum time in ms after initialization before attempting asynchronous event notifications + public ushort ReadyAENHoldOffPeriod; + + /// Global logging target save disabled + public bool GLTSD; + /// CHECK CONDITION should be reported rather than a long busy condition + public bool RAC; + /// Software write protect is active + public bool SWP; + /// Maximum time in 100 ms units allowed to remain busy. 0xFFFF == unlimited. + public ushort BusyTimeoutPeriod; + + /// Task set type + public byte TST; + /// Tasks aborted by other initiator's actions should be terminated with TASK ABORTED + public bool TAS; + /// Action to be taken when a medium is inserted + public byte AutoloadMode; + /// Time in seconds to complete an extended self-test + public byte ExtendedSelfTestCompletionTime; + + /// All tasks received in nexus with ACA ACTIVE is set and an ACA condition is established shall terminate + public bool TMF_ONLY; + /// + /// Device shall return descriptor format sense data when returning sense data in the same transactions as a CHECK + /// CONDITION + /// + public bool D_SENSE; + /// Unit attention interlocks control + public byte UA_INTLCK_CTRL; + /// LOGICAL BLOCK APPLICATION TAG should not be modified + public bool ATO; + + /// Protector information checking is disabled + public bool DPICZ; + /// No unit attention on release + public bool NUAR; + /// Application Tag mode page is enabled + public bool ATMPE; + /// Abort any write command without protection information + public bool RWWP; + /// Supportes block lengths and protection information + public bool SBLP; + } + + public static ModePage_0A? DecodeModePage_0A(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x0A) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 8) + return null; + + var decoded = new ModePage_0A(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.RLEC |= (pageResponse[2] & 0x01) == 0x01; + + decoded.QueueAlgorithm = (byte)((pageResponse[3] & 0xF0) >> 4); + decoded.QErr = (byte)((pageResponse[3] & 0x06) >> 1); + + decoded.DQue |= (pageResponse[3] & 0x01) == 0x01; + decoded.EECA |= (pageResponse[4] & 0x80) == 0x80; + decoded.RAENP |= (pageResponse[4] & 0x04) == 0x04; + decoded.UAAENP |= (pageResponse[4] & 0x02) == 0x02; + decoded.EAENP |= (pageResponse[4] & 0x01) == 0x01; + + decoded.ReadyAENHoldOffPeriod = (ushort)((pageResponse[6] << 8) + pageResponse[7]); + + if(pageResponse.Length < 10) + return decoded; + + // SPC-1 + decoded.GLTSD |= (pageResponse[2] & 0x02) == 0x02; + decoded.RAC |= (pageResponse[4] & 0x40) == 0x40; + decoded.SWP |= (pageResponse[4] & 0x08) == 0x08; + + decoded.BusyTimeoutPeriod = (ushort)((pageResponse[8] << 8) + pageResponse[9]); + + // SPC-2 + decoded.TST = (byte)((pageResponse[2] & 0xE0) >> 5); + decoded.TAS |= (pageResponse[4] & 0x80) == 0x80; + decoded.AutoloadMode = (byte)(pageResponse[5] & 0x07); + decoded.BusyTimeoutPeriod = (ushort)((pageResponse[10] << 8) + pageResponse[11]); + + // SPC-3 + decoded.TMF_ONLY |= (pageResponse[2] & 0x10) == 0x10; + decoded.D_SENSE |= (pageResponse[2] & 0x04) == 0x04; + decoded.UA_INTLCK_CTRL = (byte)((pageResponse[4] & 0x30) >> 4); + decoded.TAS |= (pageResponse[5] & 0x40) == 0x40; + decoded.ATO |= (pageResponse[5] & 0x80) == 0x80; + + // SPC-5 + decoded.DPICZ |= (pageResponse[2] & 0x08) == 0x08; + decoded.NUAR |= (pageResponse[3] & 0x08) == 0x08; + decoded.ATMPE |= (pageResponse[5] & 0x20) == 0x20; + decoded.RWWP |= (pageResponse[5] & 0x10) == 0x10; + decoded.SBLP |= (pageResponse[5] & 0x08) == 0x08; + + return decoded; + } + + public static string PrettifyModePage_0A(byte[] pageResponse) => + PrettifyModePage_0A(DecodeModePage_0A(pageResponse)); + + public static string PrettifyModePage_0A(ModePage_0A? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_0A page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Control mode page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.RLEC) + sb.AppendLine("\tIf set, target shall report log exception conditions"); + + if(page.DQue) + sb.AppendLine("\tTagged queuing is disabled"); + + if(page.EECA) + sb.AppendLine("\tExtended Contingent Allegiance is enabled"); + + if(page.RAENP) + sb.AppendLine("\tTarget may issue an asynchronous event notification upon completing its initialization"); + + if(page.UAAENP) + sb.AppendLine("\tTarget may issue an asynchronous event notification instead of a unit attention condition"); + + if(page.EAENP) + sb.AppendLine("\tTarget may issue an asynchronous event notification instead of a deferred error"); + + if(page.GLTSD) + sb.AppendLine("\tGlobal logging target save disabled"); + + if(page.RAC) + sb.AppendLine("\tCHECK CONDITION should be reported rather than a long busy condition"); + + if(page.SWP) + sb.AppendLine("\tSoftware write protect is active"); + + if(page.TAS) + sb.AppendLine("\tTasks aborted by other initiator's actions should be terminated with TASK ABORTED"); + + if(page.TMF_ONLY) + sb.AppendLine("\tAll tasks received in nexus with ACA ACTIVE is set and an ACA condition is established shall terminate"); + + if(page.D_SENSE) + sb.AppendLine("\tDevice shall return descriptor format sense data when returning sense data in the same transactions as a CHECK CONDITION"); + + if(page.ATO) + sb.AppendLine("\tLOGICAL BLOCK APPLICATION TAG should not be modified"); + + if(page.DPICZ) + sb.AppendLine("\tProtector information checking is disabled"); + + if(page.NUAR) + sb.AppendLine("\tNo unit attention on release"); + + if(page.ATMPE) + sb.AppendLine("\tApplication Tag mode page is enabled"); + + if(page.RWWP) + sb.AppendLine("\tAbort any write command without protection information"); + + if(page.SBLP) + sb.AppendLine("\tSupportes block lengths and protection information"); + + switch(page.TST) + { + case 0: + sb.AppendLine("\tThe logical unit maintains one task set for all nexuses"); + + break; + case 1: + sb.AppendLine("\tThe logical unit maintains separate task sets for each nexus"); + + break; + default: + sb.AppendFormat("\tUnknown Task set type {0}", page.TST).AppendLine(); + + break; + } + + switch(page.QueueAlgorithm) + { + case 0: + sb.AppendLine("\tCommands should be sent strictly ordered"); + + break; + case 1: + sb.AppendLine("\tCommands can be reordered in any manner"); + + break; + default: + sb.AppendFormat("\tUnknown Queue Algorithm Modifier {0}", page.QueueAlgorithm).AppendLine(); + + break; + } + + switch(page.QErr) + { + case 0: + sb.AppendLine("\tIf ACA is established, the task set commands shall resume after it is cleared, otherwise they shall terminate with CHECK CONDITION"); + + break; + case 1: + sb.AppendLine("\tAll the affected commands in the task set shall be aborted when CHECK CONDITION is returned"); + + break; + case 3: + sb.AppendLine("\tAffected commands in the task set belonging with the CHECK CONDITION nexus shall be aborted"); + + break; + default: + sb.AppendLine("\tReserved QErr value 2 is set"); + + break; + } + + switch(page.UA_INTLCK_CTRL) + { + case 0: + sb.AppendLine("\tLUN shall clear unit attention condition reported in the same nexus"); + + break; + case 2: + sb.AppendLine("\tLUN shall not clear unit attention condition reported in the same nexus"); + + break; + case 3: + sb.AppendLine("\tLUN shall not clear unit attention condition reported in the same nexus and shall establish a unit attention condition for the initiator"); + + break; + default: + sb.AppendLine("\tReserved UA_INTLCK_CTRL value 1 is set"); + + break; + } + + switch(page.AutoloadMode) + { + case 0: + sb.AppendLine("\tOn medium insertion, it shall be loaded for full access"); + + break; + case 1: + sb.AppendLine("\tOn medium insertion, it shall be loaded for auxiliary memory access only"); + + break; + case 2: + sb.AppendLine("\tOn medium insertion, it shall not be loaded"); + + break; + default: + sb.AppendFormat("\tReserved autoload mode {0} set", page.AutoloadMode).AppendLine(); + + break; + } + + if(page.ReadyAENHoldOffPeriod > 0) + sb.AppendFormat("\t{0} ms before attempting asynchronous event notifications after initialization", + page.ReadyAENHoldOffPeriod).AppendLine(); + + if(page.BusyTimeoutPeriod > 0) + if(page.BusyTimeoutPeriod == 0xFFFF) + sb.AppendLine("\tThere is no limit on the maximum time that is allowed to remain busy"); + else + sb.AppendFormat("\tA maximum of {0} ms are allowed to remain busy", page.BusyTimeoutPeriod * 100). + AppendLine(); + + if(page.ExtendedSelfTestCompletionTime > 0) + sb.AppendFormat("\t{0} seconds to complete extended self-test", page.ExtendedSelfTestCompletionTime); + + return sb.ToString(); + } + #endregion Mode Page 0x0A: Control mode page + + #region Mode Page 0x0A subpage 0x01: Control Extension mode page + /// Control Extension mode page Page code 0x0A Subpage code 0x01 32 bytes in SPC-3, SPC-4, SPC-5 + public struct ModePage_0A_S01 + { + /// Parameters can be saved + public bool PS; + /// Timestamp outside this standard + public bool TCMOS; + /// SCSI precedence + public bool SCSIP; + /// Implicit Asymmetric Logical Unit Access Enabled + public bool IALUAE; + /// Initial task priority + public byte InitialPriority; + + /// Device life control disabled + public bool DLC; + /// Maximum size of SENSE data in bytes + public byte MaximumSenseLength; + } + + public static ModePage_0A_S01? DecodeModePage_0A_S01(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) != 0x40) + return null; + + if((pageResponse[0] & 0x3F) != 0x0A) + return null; + + if(pageResponse[1] != 0x01) + return null; + + if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) + return null; + + if(pageResponse.Length < 32) + return null; + + var decoded = new ModePage_0A_S01(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + + decoded.IALUAE |= (pageResponse[4] & 0x01) == 0x01; + decoded.SCSIP |= (pageResponse[4] & 0x02) == 0x02; + decoded.TCMOS |= (pageResponse[4] & 0x04) == 0x04; + + decoded.InitialPriority = (byte)(pageResponse[5] & 0x0F); + + return decoded; + } + + public static string PrettifyModePage_0A_S01(byte[] pageResponse) => + PrettifyModePage_0A_S01(DecodeModePage_0A_S01(pageResponse)); + + public static string PrettifyModePage_0A_S01(ModePage_0A_S01? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_0A_S01 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Control extension page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.TCMOS) + { + sb.Append("\tTimestamp can be initialized by methods outside of the SCSI standards"); + + if(page.SCSIP) + sb.Append(", but SCSI's SET TIMESTAMP shall take precedence over them"); + + sb.AppendLine(); + } + + if(page.IALUAE) + sb.AppendLine("\tImplicit Asymmetric Logical Unit Access is enabled"); + + sb.AppendFormat("\tInitial priority is {0}", page.InitialPriority).AppendLine(); + + if(page.DLC) + sb.AppendLine("\tDevice will not degrade performance to extend its life"); + + if(page.MaximumSenseLength > 0) + sb.AppendFormat("\tMaximum sense data would be {0} bytes", page.MaximumSenseLength).AppendLine(); + + return sb.ToString(); + } + #endregion Mode Page 0x0A subpage 0x01: Control Extension mode page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/0B.cs b/Aaru.Decoders/SCSI/Modes/0B.cs new file mode 100644 index 000000000..d8225a731 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/0B.cs @@ -0,0 +1,115 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 0B.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 0Bh: Medium types supported page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x0B: Medium types supported page + /// Disconnect-reconnect page Page code 0x0B 8 bytes in SCSI-2 + public struct ModePage_0B + { + /// Parameters can be saved + public bool PS; + public MediumTypes MediumType1; + public MediumTypes MediumType2; + public MediumTypes MediumType3; + public MediumTypes MediumType4; + } + + public static ModePage_0B? DecodeModePage_0B(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x0B) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 8) + return null; + + var decoded = new ModePage_0B(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.MediumType1 = (MediumTypes)pageResponse[4]; + decoded.MediumType2 = (MediumTypes)pageResponse[5]; + decoded.MediumType3 = (MediumTypes)pageResponse[6]; + decoded.MediumType4 = (MediumTypes)pageResponse[7]; + + return decoded; + } + + public static string PrettifyModePage_0B(byte[] pageResponse) => + PrettifyModePage_0B(DecodeModePage_0B(pageResponse)); + + public static string PrettifyModePage_0B(ModePage_0B? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_0B page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Medium types supported page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.MediumType1 != MediumTypes.Default) + sb.AppendFormat("Supported medium type one: {0}", GetMediumTypeDescription(page.MediumType1)). + AppendLine(); + + if(page.MediumType2 != MediumTypes.Default) + sb.AppendFormat("Supported medium type two: {0}", GetMediumTypeDescription(page.MediumType2)). + AppendLine(); + + if(page.MediumType3 != MediumTypes.Default) + sb.AppendFormat("Supported medium type three: {0}", GetMediumTypeDescription(page.MediumType3)). + AppendLine(); + + if(page.MediumType4 != MediumTypes.Default) + sb.AppendFormat("Supported medium type four: {0}", GetMediumTypeDescription(page.MediumType4)). + AppendLine(); + + return sb.ToString(); + } + #endregion Mode Page 0x0B: Medium types supported page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/0C.cs b/Aaru.Decoders/SCSI/Modes/0C.cs new file mode 100644 index 000000000..f7c9f357d --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/0C.cs @@ -0,0 +1,41 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 0C.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 0Ch: Notch page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.Decoders.SCSI +{ + public static partial class Modes + { + #region Mode Page 0x0C: Notch page + // TODO: Implement this page + #endregion Mode Page 0x0C: Notch page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/0D.cs b/Aaru.Decoders/SCSI/Modes/0D.cs new file mode 100644 index 000000000..d15abb17e --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/0D.cs @@ -0,0 +1,174 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 0D.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 0Dh: CD-ROM parameteres page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x0D: CD-ROM parameteres page + /// CD-ROM parameteres page Page code 0x0D 8 bytes in SCSI-2, MMC-1, MMC-2, MMC-3 + public struct ModePage_0D + { + /// Parameters can be saved + public bool PS; + /// Time the drive shall remain in hold track state after seek or read + public byte InactivityTimerMultiplier; + /// Seconds per Minute + public ushort SecondsPerMinute; + /// Frames per Second + public ushort FramesPerSecond; + } + + public static ModePage_0D? DecodeModePage_0D(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x0D) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 8) + return null; + + var decoded = new ModePage_0D(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.InactivityTimerMultiplier = (byte)(pageResponse[3] & 0xF); + decoded.SecondsPerMinute = (ushort)((pageResponse[4] << 8) + pageResponse[5]); + decoded.FramesPerSecond = (ushort)((pageResponse[6] << 8) + pageResponse[7]); + + return decoded; + } + + public static string PrettifyModePage_0D(byte[] pageResponse) => + PrettifyModePage_0D(DecodeModePage_0D(pageResponse)); + + public static string PrettifyModePage_0D(ModePage_0D? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_0D page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI CD-ROM parameters page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + switch(page.InactivityTimerMultiplier) + { + case 0: + sb.AppendLine("\tDrive will remain in track hold state a vendor-specified time after a seek or read"); + + break; + case 1: + sb.AppendLine("\tDrive will remain in track hold state 125 ms after a seek or read"); + + break; + case 2: + sb.AppendLine("\tDrive will remain in track hold state 250 ms after a seek or read"); + + break; + case 3: + sb.AppendLine("\tDrive will remain in track hold state 500 ms after a seek or read"); + + break; + case 4: + sb.AppendLine("\tDrive will remain in track hold state 1 second after a seek or read"); + + break; + case 5: + sb.AppendLine("\tDrive will remain in track hold state 2 seconds after a seek or read"); + + break; + case 6: + sb.AppendLine("\tDrive will remain in track hold state 4 seconds after a seek or read"); + + break; + case 7: + sb.AppendLine("\tDrive will remain in track hold state 8 seconds after a seek or read"); + + break; + case 8: + sb.AppendLine("\tDrive will remain in track hold state 16 seconds after a seek or read"); + + break; + case 9: + sb.AppendLine("\tDrive will remain in track hold state 32 seconds after a seek or read"); + + break; + case 10: + sb.AppendLine("\tDrive will remain in track hold state 1 minute after a seek or read"); + + break; + case 11: + sb.AppendLine("\tDrive will remain in track hold state 2 minutes after a seek or read"); + + break; + case 12: + sb.AppendLine("\tDrive will remain in track hold state 4 minutes after a seek or read"); + + break; + case 13: + sb.AppendLine("\tDrive will remain in track hold state 8 minutes after a seek or read"); + + break; + case 14: + sb.AppendLine("\tDrive will remain in track hold state 16 minutes after a seek or read"); + + break; + case 15: + sb.AppendLine("\tDrive will remain in track hold state 32 minutes after a seek or read"); + + break; + } + + if(page.SecondsPerMinute > 0) + sb.AppendFormat("\tEach minute has {0} seconds", page.SecondsPerMinute).AppendLine(); + + if(page.FramesPerSecond > 0) + sb.AppendFormat("\tEach second has {0} frames", page.FramesPerSecond).AppendLine(); + + return sb.ToString(); + } + #endregion Mode Page 0x0D: CD-ROM parameteres page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/0E.cs b/Aaru.Decoders/SCSI/Modes/0E.cs new file mode 100644 index 000000000..f61c698f1 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/0E.cs @@ -0,0 +1,280 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 0E.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 0Eh: CD-ROM audio control parameters page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x0E: CD-ROM audio control parameters page + /// CD-ROM audio control parameters Page code 0x0E 16 bytes in SCSI-2, MMC-1, MMC-2, MMC-3 + public struct ModePage_0E + { + /// Parameters can be saved + public bool PS; + /// Return status as soon as playback operation starts + public bool Immed; + /// Stop on track crossing + public bool SOTC; + /// Indicates is valid + public bool APRVal; + /// Multiplier for + public byte LBAFormat; + /// LBAs per second of audio + public ushort BlocksPerSecondOfAudio; + /// Channels output on this port + public byte OutputPort0ChannelSelection; + /// Volume level for this port + public byte OutputPort0Volume; + /// Channels output on this port + public byte OutputPort1ChannelSelection; + /// Volume level for this port + public byte OutputPort1Volume; + /// Channels output on this port + public byte OutputPort2ChannelSelection; + /// Volume level for this port + public byte OutputPort2Volume; + /// Channels output on this port + public byte OutputPort3ChannelSelection; + /// Volume level for this port + public byte OutputPort3Volume; + } + + public static ModePage_0E? DecodeModePage_0E(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x0E) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 16) + return null; + + var decoded = new ModePage_0E(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.Immed |= (pageResponse[2] & 0x04) == 0x04; + decoded.SOTC |= (pageResponse[2] & 0x02) == 0x02; + decoded.APRVal |= (pageResponse[5] & 0x80) == 0x80; + decoded.LBAFormat = (byte)(pageResponse[5] & 0x0F); + decoded.BlocksPerSecondOfAudio = (ushort)((pageResponse[6] << 8) + pageResponse[7]); + decoded.OutputPort0ChannelSelection = (byte)(pageResponse[8] & 0x0F); + decoded.OutputPort0Volume = pageResponse[9]; + decoded.OutputPort1ChannelSelection = (byte)(pageResponse[10] & 0x0F); + decoded.OutputPort1Volume = pageResponse[11]; + decoded.OutputPort2ChannelSelection = (byte)(pageResponse[12] & 0x0F); + decoded.OutputPort2Volume = pageResponse[13]; + decoded.OutputPort3ChannelSelection = (byte)(pageResponse[14] & 0x0F); + decoded.OutputPort3Volume = pageResponse[15]; + + return decoded; + } + + public static string PrettifyModePage_0E(byte[] pageResponse) => + PrettifyModePage_0E(DecodeModePage_0E(pageResponse)); + + public static string PrettifyModePage_0E(ModePage_0E? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_0E page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI CD-ROM audio control parameters page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + sb.AppendLine(page.Immed ? "\tDrive will return from playback command immediately" + : "\tDrive will return from playback command when playback ends"); + + if(page.SOTC) + sb.AppendLine("\tDrive will stop playback on track end"); + + if(page.APRVal) + { + double blocks; + + if(page.LBAFormat == 8) + blocks = page.BlocksPerSecondOfAudio * (1 / 256); + else + blocks = page.BlocksPerSecondOfAudio; + + sb.AppendFormat("\tThere are {0} blocks per each second of audio", blocks).AppendLine(); + } + + if(page.OutputPort0ChannelSelection > 0) + { + sb.Append("\tOutput port 0 has channels "); + + if((page.OutputPort0ChannelSelection & 0x01) == 0x01) + sb.Append("0 "); + + if((page.OutputPort0ChannelSelection & 0x02) == 0x02) + sb.Append("1 "); + + if((page.OutputPort0ChannelSelection & 0x04) == 0x04) + sb.Append("2 "); + + if((page.OutputPort0ChannelSelection & 0x08) == 0x08) + sb.Append("3 "); + + switch(page.OutputPort0Volume) + { + case 0: + sb.AppendLine("muted"); + + break; + case 0xFF: + sb.AppendLine("at maximum volume"); + + break; + default: + sb.AppendFormat("at volume {0}", page.OutputPort0Volume).AppendLine(); + + break; + } + } + + if(page.OutputPort1ChannelSelection > 0) + { + sb.Append("\tOutput port 1 has channels "); + + if((page.OutputPort1ChannelSelection & 0x01) == 0x01) + sb.Append("0 "); + + if((page.OutputPort1ChannelSelection & 0x02) == 0x02) + sb.Append("1 "); + + if((page.OutputPort1ChannelSelection & 0x04) == 0x04) + sb.Append("2 "); + + if((page.OutputPort1ChannelSelection & 0x08) == 0x08) + sb.Append("3 "); + + switch(page.OutputPort1Volume) + { + case 0: + sb.AppendLine("muted"); + + break; + case 0xFF: + sb.AppendLine("at maximum volume"); + + break; + default: + sb.AppendFormat("at volume {0}", page.OutputPort1Volume).AppendLine(); + + break; + } + } + + if(page.OutputPort2ChannelSelection > 0) + { + sb.Append("\tOutput port 2 has channels "); + + if((page.OutputPort2ChannelSelection & 0x01) == 0x01) + sb.Append("0 "); + + if((page.OutputPort2ChannelSelection & 0x02) == 0x02) + sb.Append("1 "); + + if((page.OutputPort2ChannelSelection & 0x04) == 0x04) + sb.Append("2 "); + + if((page.OutputPort2ChannelSelection & 0x08) == 0x08) + sb.Append("3 "); + + switch(page.OutputPort2Volume) + { + case 0: + sb.AppendLine("muted"); + + break; + case 0xFF: + sb.AppendLine("at maximum volume"); + + break; + default: + sb.AppendFormat("at volume {0}", page.OutputPort2Volume).AppendLine(); + + break; + } + } + + if(page.OutputPort3ChannelSelection <= 0) + return sb.ToString(); + + sb.Append("\tOutput port 3 has channels "); + + if((page.OutputPort3ChannelSelection & 0x01) == 0x01) + sb.Append("0 "); + + if((page.OutputPort3ChannelSelection & 0x02) == 0x02) + sb.Append("1 "); + + if((page.OutputPort3ChannelSelection & 0x04) == 0x04) + sb.Append("2 "); + + if((page.OutputPort3ChannelSelection & 0x08) == 0x08) + sb.Append("3 "); + + switch(page.OutputPort3Volume) + { + case 0: + sb.AppendLine("muted"); + + break; + case 0xFF: + sb.AppendLine("at maximum volume"); + + break; + default: + sb.AppendFormat("at volume {0}", page.OutputPort3Volume).AppendLine(); + + break; + } + + return sb.ToString(); + } + #endregion Mode Page 0x0E: CD-ROM audio control parameters page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/0F.cs b/Aaru.Decoders/SCSI/Modes/0F.cs new file mode 100644 index 000000000..376a4cb5b --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/0F.cs @@ -0,0 +1,204 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 0F.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 0Fh: Data compression page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x0F: Data compression page + /// Data compression page Page code 0x0F 16 bytes in SSC-1, SSC-2, SSC-3 + public struct ModePage_0F + { + /// Parameters can be saved + public bool PS; + /// Data compression enabled + public bool DCE; + /// Data compression capable + public bool DCC; + /// Data decompression enabled + public bool DDE; + /// Report exception on decompression + public byte RED; + /// Compression algorithm + public uint CompressionAlgo; + /// Decompression algorithm + public uint DecompressionAlgo; + } + + public static ModePage_0F? DecodeModePage_0F(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x0F) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 16) + return null; + + var decoded = new ModePage_0F(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + + decoded.DCE |= (pageResponse[2] & 0x80) == 0x80; + decoded.DCC |= (pageResponse[2] & 0x40) == 0x40; + decoded.DDE |= (pageResponse[3] & 0x80) == 0x80; + decoded.RED = (byte)((pageResponse[3] & 0x60) >> 5); + + decoded.CompressionAlgo = (uint)((pageResponse[4] << 24) + (pageResponse[5] << 16) + + (pageResponse[6] << 8) + pageResponse[7]); + + decoded.DecompressionAlgo = (uint)((pageResponse[8] << 24) + (pageResponse[9] << 16) + + (pageResponse[10] << 8) + pageResponse[11]); + + return decoded; + } + + public static string PrettifyModePage_0F(byte[] pageResponse) => + PrettifyModePage_0F(DecodeModePage_0F(pageResponse)); + + public static string PrettifyModePage_0F(ModePage_0F? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_0F page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Data compression page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.DCC) + { + sb.AppendLine("\tDrive supports data compression"); + + if(page.DCE) + { + sb.Append("\tData compression is enabled with "); + + switch(page.CompressionAlgo) + { + case 3: + sb.AppendLine("IBM ALDC with 512 byte buffer"); + + break; + case 4: + sb.AppendLine("IBM ALDC with 1024 byte buffer"); + + break; + case 5: + sb.AppendLine("IBM ALDC with 2048 byte buffer"); + + break; + case 0x10: + sb.AppendLine("IBM IDRC"); + + break; + case 0x20: + sb.AppendLine("DCLZ"); + + break; + case 0xFF: + sb.AppendLine("an unregistered compression algorithm"); + + break; + default: + sb.AppendFormat("an unknown algorithm coded {0}", page.CompressionAlgo).AppendLine(); + + break; + } + } + + if(page.DDE) + { + sb.AppendLine("\tData decompression is enabled"); + + if(page.DecompressionAlgo == 0) + sb.AppendLine("\tLast data read was uncompressed"); + else + { + sb.Append("\tLast data read was compressed with "); + + switch(page.CompressionAlgo) + { + case 3: + sb.AppendLine("IBM ALDC with 512 byte buffer"); + + break; + case 4: + sb.AppendLine("IBM ALDC with 1024 byte buffer"); + + break; + case 5: + sb.AppendLine("IBM ALDC with 2048 byte buffer"); + + break; + case 0x10: + sb.AppendLine("IBM IDRC"); + + break; + case 0x20: + sb.AppendLine("DCLZ"); + + break; + case 0xFF: + sb.AppendLine("an unregistered compression algorithm"); + + break; + default: + sb.AppendFormat("an unknown algorithm coded {0}", page.CompressionAlgo).AppendLine(); + + break; + } + } + } + + sb.AppendFormat("\tReport exception on compression is set to {0}", page.RED).AppendLine(); + } + else + sb.AppendLine("\tDrive does not support data compression"); + + return sb.ToString(); + } + #endregion Mode Page 0x0F: Data compression page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/10.cs b/Aaru.Decoders/SCSI/Modes/10.cs new file mode 100644 index 000000000..d45ffeb99 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/10.cs @@ -0,0 +1,135 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 10.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 10h: XOR control mode page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x10: XOR control mode page + /// XOR control mode page Page code 0x10 24 bytes in SBC-1, SBC-2 + public struct ModePage_10 + { + /// Parameters can be saved + public bool PS; + /// Disables XOR operations + public bool XORDIS; + /// Maximum transfer length in blocks for a XOR command + public uint MaxXorWrite; + /// Maximum regenerate length in blocks + public uint MaxRegenSize; + /// Maximum transfer length in blocks for READ during a rebuild + public uint MaxRebuildRead; + /// Minimum time in ms between READs during a rebuild + public ushort RebuildDelay; + } + + public static ModePage_10? DecodeModePage_10(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x10) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 24) + return null; + + var decoded = new ModePage_10(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + + decoded.XORDIS |= (pageResponse[2] & 0x02) == 0x02; + + decoded.MaxXorWrite = (uint)((pageResponse[4] << 24) + (pageResponse[5] << 16) + (pageResponse[6] << 8) + + pageResponse[7]); + + decoded.MaxRegenSize = (uint)((pageResponse[12] << 24) + (pageResponse[13] << 16) + + (pageResponse[14] << 8) + pageResponse[15]); + + decoded.MaxRebuildRead = (uint)((pageResponse[16] << 24) + (pageResponse[17] << 16) + + (pageResponse[18] << 8) + pageResponse[19]); + + decoded.RebuildDelay = (ushort)((pageResponse[22] << 8) + pageResponse[23]); + + return decoded; + } + + public static string PrettifyModePage_10(byte[] pageResponse) => + PrettifyModePage_10(DecodeModePage_10(pageResponse)); + + public static string PrettifyModePage_10(ModePage_10? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_10 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI XOR control mode page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.XORDIS) + sb.AppendLine("\tXOR operations are disabled"); + else + { + if(page.MaxXorWrite > 0) + sb.AppendFormat("\tDrive accepts a maximum of {0} blocks in a single XOR WRITE command", + page.MaxXorWrite).AppendLine(); + + if(page.MaxRegenSize > 0) + sb.AppendFormat("\tDrive accepts a maximum of {0} blocks in a REGENERATE command", + page.MaxRegenSize).AppendLine(); + + if(page.MaxRebuildRead > 0) + sb.AppendFormat("\tDrive accepts a maximum of {0} blocks in a READ command during rebuild", + page.MaxRebuildRead).AppendLine(); + + if(page.RebuildDelay > 0) + sb.AppendFormat("\tDrive needs a minimum of {0} ms between READ commands during rebuild", + page.RebuildDelay).AppendLine(); + } + + return sb.ToString(); + } + #endregion Mode Page 0x10: XOR control mode page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/10_SSC.cs b/Aaru.Decoders/SCSI/Modes/10_SSC.cs new file mode 100644 index 000000000..7331552bc --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/10_SSC.cs @@ -0,0 +1,331 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 10_SSC.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 10h: Device configuration page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x10: Device configuration page + /// Device configuration page Page code 0x10 16 bytes in SCSI-2, SSC-1, SSC-2, SSC-3 + public struct ModePage_10_SSC + { + /// Parameters can be saved + public bool PS; + /// Used in mode select to change partition to one specified in + public bool CAP; + /// Used in mode select to change format to one specified in + public bool CAF; + /// Active format, vendor-specific + public byte ActiveFormat; + /// Current logical partition + public byte ActivePartition; + /// How full the buffer shall be before writing to medium + public byte WriteBufferFullRatio; + /// How empty the buffer shall be before reading more data from the medium + public byte ReadBufferEmptyRatio; + /// Delay in 100 ms before buffered data is forcefully written to the medium even before buffer is full + public ushort WriteDelayTime; + /// Drive supports recovering data from buffer + public bool DBR; + /// Medium has block IDs + public bool BIS; + /// Drive recognizes and reports setmarks + public bool RSmk; + /// Drive selects best speed + public bool AVC; + /// If drive should stop pre-reading on filemarks + public byte SOCF; + /// If set, recovered buffer data is LIFO, otherwise, FIFO + public bool RBO; + /// Report early warnings + public bool REW; + /// Inter-block gap + public byte GapSize; + /// End-of-Data format + public byte EODDefined; + /// EOD generation enabled + public bool EEG; + /// Synchronize data to medium on early warning + public bool SEW; + /// Bytes to reduce buffer size on early warning + public uint BufferSizeEarlyWarning; + /// Selected data compression algorithm + public byte SelectedCompression; + + /// Soft write protect + public bool SWP; + /// Associated write protect + public bool ASOCWP; + /// Persistent write protect + public bool PERSWP; + /// Permanent write protect + public bool PRMWP; + + public bool BAML; + public bool BAM; + public byte RewindOnReset; + + /// How drive shall respond to detection of compromised WORM medium integrity + public byte WTRE; + /// Respond to commands only if a reservation exists + public bool OIR; + } + + public static ModePage_10_SSC? DecodeModePage_10_SSC(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x10) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 16) + return null; + + var decoded = new ModePage_10_SSC(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.CAP |= (pageResponse[2] & 0x40) == 0x40; + decoded.CAF |= (pageResponse[2] & 0x20) == 0x20; + decoded.ActiveFormat = (byte)(pageResponse[2] & 0x1F); + decoded.ActivePartition = pageResponse[3]; + decoded.WriteBufferFullRatio = pageResponse[4]; + decoded.ReadBufferEmptyRatio = pageResponse[5]; + decoded.WriteDelayTime = (ushort)((pageResponse[6] << 8) + pageResponse[7]); + decoded.DBR |= (pageResponse[8] & 0x80) == 0x80; + decoded.BIS |= (pageResponse[8] & 0x40) == 0x40; + decoded.RSmk |= (pageResponse[8] & 0x20) == 0x20; + decoded.AVC |= (pageResponse[8] & 0x10) == 0x10; + decoded.RBO |= (pageResponse[8] & 0x02) == 0x02; + decoded.REW |= (pageResponse[8] & 0x01) == 0x01; + decoded.EEG |= (pageResponse[10] & 0x10) == 0x10; + decoded.SEW |= (pageResponse[10] & 0x08) == 0x08; + decoded.SOCF = (byte)((pageResponse[8] & 0x0C) >> 2); + + decoded.BufferSizeEarlyWarning = + (uint)((pageResponse[11] << 16) + (pageResponse[12] << 8) + pageResponse[13]); + + decoded.SelectedCompression = pageResponse[14]; + + decoded.SWP |= (pageResponse[10] & 0x04) == 0x04; + decoded.ASOCWP |= (pageResponse[15] & 0x04) == 0x04; + decoded.PERSWP |= (pageResponse[15] & 0x02) == 0x02; + decoded.PRMWP |= (pageResponse[15] & 0x01) == 0x01; + + decoded.BAML |= (pageResponse[10] & 0x02) == 0x02; + decoded.BAM |= (pageResponse[10] & 0x01) == 0x01; + + decoded.RewindOnReset = (byte)((pageResponse[15] & 0x18) >> 3); + + decoded.OIR |= (pageResponse[15] & 0x20) == 0x20; + decoded.WTRE = (byte)((pageResponse[15] & 0xC0) >> 6); + + return decoded; + } + + public static string PrettifyModePage_10_SSC(byte[] pageResponse) => + PrettifyModePage_10_SSC(DecodeModePage_10_SSC(pageResponse)); + + public static string PrettifyModePage_10_SSC(ModePage_10_SSC? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_10_SSC page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Device configuration page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + sb.AppendFormat("\tActive format: {0}", page.ActiveFormat).AppendLine(); + sb.AppendFormat("\tActive partition: {0}", page.ActivePartition).AppendLine(); + + sb.AppendFormat("\tWrite buffer shall have a full ratio of {0} before being flushed to medium", + page.WriteBufferFullRatio).AppendLine(); + + sb.AppendFormat("\tRead buffer shall have an empty ratio of {0} before more data is read from medium", + page.ReadBufferEmptyRatio).AppendLine(); + + sb. + AppendFormat("\tDrive will delay {0} ms before buffered data is forcefully written to the medium even before buffer is full", + page.WriteDelayTime * 100).AppendLine(); + + if(page.DBR) + { + sb.AppendLine("\tDrive supports recovering data from buffer"); + + sb.AppendLine(page.RBO ? "\tRecovered buffer data comes in LIFO order" + : "\tRecovered buffer data comes in FIFO order"); + } + + if(page.BIS) + sb.AppendLine("\tMedium supports block IDs"); + + if(page.RSmk) + sb.AppendLine("\tDrive reports setmarks"); + + switch(page.SOCF) + { + case 0: + sb.AppendLine("\tDrive will pre-read until buffer is full"); + + break; + case 1: + sb.AppendLine("\tDrive will pre-read until one filemark is detected"); + + break; + case 2: + sb.AppendLine("\tDrive will pre-read until two filemark is detected"); + + break; + case 3: + sb.AppendLine("\tDrive will pre-read until three filemark is detected"); + + break; + } + + if(page.REW) + { + sb.AppendLine("\tDrive reports early warnings"); + + if(page.SEW) + sb.AppendLine("\tDrive will synchronize buffer to medium on early warnings"); + } + + switch(page.GapSize) + { + case 0: break; + case 1: + sb.AppendLine("\tInter-block gap is long enough to support update in place"); + + break; + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + sb.AppendFormat("\tInter-block gap is {0} times the device's defined gap size", page.GapSize). + AppendLine(); + + break; + default: + sb.AppendFormat("\tInter-block gap is unknown value {0}", page.GapSize).AppendLine(); + + break; + } + + if(page.EEG) + sb.AppendLine("\tDrive generates end-of-data"); + + switch(page.SelectedCompression) + { + case 0: + sb.AppendLine("\tDrive does not use compression"); + + break; + case 1: + sb.AppendLine("\tDrive uses default compression"); + + break; + default: + sb.AppendFormat("\tDrive uses unknown compression {0}", page.SelectedCompression).AppendLine(); + + break; + } + + if(page.SWP) + sb.AppendLine("\tSoftware write protect is enabled"); + + if(page.ASOCWP) + sb.AppendLine("\tAssociated write protect is enabled"); + + if(page.PERSWP) + sb.AppendLine("\tPersistent write protect is enabled"); + + if(page.PRMWP) + sb.AppendLine("\tPermanent write protect is enabled"); + + if(page.BAML) + sb.AppendLine(page.BAM ? "\tDrive operates using explicit address mode" + : "\tDrive operates using implicit address mode"); + + switch(page.RewindOnReset) + { + case 1: + sb.AppendLine("\tDrive shall position to beginning of default data partition on reset"); + + break; + case 2: + sb.AppendLine("\tDrive shall maintain its position on reset"); + + break; + } + + switch(page.WTRE) + { + case 1: + sb.AppendLine("\tDrive will do nothing on WORM tampered medium"); + + break; + case 2: + sb.AppendLine("\tDrive will return CHECK CONDITION on WORM tampered medium"); + + break; + } + + if(page.OIR) + sb.AppendLine("\tDrive will only respond to commands if it has received a reservation"); + + return sb.ToString(); + } + #endregion Mode Page 0x10: Device configuration page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/11.cs b/Aaru.Decoders/SCSI/Modes/11.cs new file mode 100644 index 000000000..aba14cb94 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/11.cs @@ -0,0 +1,250 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 11.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 11h: Medium partition page (1). +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x11: Medium partition page (1) + public enum PartitionSizeUnitOfMeasures : byte + { + /// Partition size is measures in bytes + Bytes = 0, + /// Partition size is measures in Kilobytes + Kilobytes = 1, + /// Partition size is measures in Megabytes + Megabytes = 2, + /// Partition size is 10eUNITS bytes + Exponential = 3 + } + + public enum MediumFormatRecognitionValues : byte + { + /// Logical unit is incapable of format or partition recognition + Incapable = 0, + /// Logical unit is capable of format recognition only + FormatCapable = 1, + /// Logical unit is capable of partition recognition only + PartitionCapable = 2, + /// Logical unit is capable of both format and partition recognition + Capable = 3 + } + + /// Medium partition page(1) Page code 0x11 + public struct ModePage_11 + { + /// Parameters can be saved + public bool PS; + /// Maximum number of additional partitions supported + public byte MaxAdditionalPartitions; + /// Number of additional partitions to be defined for a volume + public byte AdditionalPartitionsDefined; + /// Device defines partitions based on its fixed definition + public bool FDP; + /// Device should divide medium according to the additional partitions defined field using sizes defined by device + public bool SDP; + /// Initiator defines number and size of partitions + public bool IDP; + /// Defines the unit on which the partition sizes are defined + public PartitionSizeUnitOfMeasures PSUM; + public bool POFM; + public bool CLEAR; + public bool ADDP; + /// Defines the capabilities for the unit to recognize media partitions and format + public MediumFormatRecognitionValues MediumFormatRecognition; + public byte PartitionUnits; + /// Array of partition sizes in units defined above + public ushort[] PartitionSizes; + } + + public static ModePage_11? DecodeModePage_11(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x11) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 8) + return null; + + var decoded = new ModePage_11(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + + decoded.MaxAdditionalPartitions = pageResponse[2]; + decoded.AdditionalPartitionsDefined = pageResponse[3]; + decoded.FDP |= (pageResponse[4] & 0x80) == 0x80; + decoded.SDP |= (pageResponse[4] & 0x40) == 0x40; + decoded.IDP |= (pageResponse[4] & 0x20) == 0x20; + decoded.PSUM = (PartitionSizeUnitOfMeasures)((pageResponse[4] & 0x18) >> 3); + decoded.POFM |= (pageResponse[4] & 0x04) == 0x04; + decoded.CLEAR |= (pageResponse[4] & 0x02) == 0x02; + decoded.ADDP |= (pageResponse[4] & 0x01) == 0x01; + decoded.PartitionUnits = (byte)(pageResponse[6] & 0x0F); + decoded.MediumFormatRecognition = (MediumFormatRecognitionValues)pageResponse[5]; + decoded.PartitionSizes = new ushort[(pageResponse.Length - 8) / 2]; + + for(int i = 8; i < pageResponse.Length; i += 2) + { + decoded.PartitionSizes[(i - 8) / 2] = (ushort)(pageResponse[i] << 8); + decoded.PartitionSizes[(i - 8) / 2] += pageResponse[i + 1]; + } + + return decoded; + } + + public static string PrettifyModePage_11(byte[] pageResponse) => + PrettifyModePage_11(DecodeModePage_11(pageResponse)); + + public static string PrettifyModePage_11(ModePage_11? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_11 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI medium partition page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + sb.AppendFormat("\t{0} maximum additional partitions", page.MaxAdditionalPartitions).AppendLine(); + sb.AppendFormat("\t{0} additional partitions defined", page.AdditionalPartitionsDefined).AppendLine(); + + if(page.FDP) + sb.AppendLine("\tPartitions are fixed under device definitions"); + + if(page.SDP) + sb.AppendLine("\tNumber of partitions can be defined but their size is defined by the device"); + + if(page.IDP) + sb.AppendLine("\tNumber and size of partitions can be manually defined"); + + if(page.POFM) + sb.AppendLine("\tPartition parameters will not be applied until a FORMAT MEDIUM command is received"); + + if(!page.CLEAR && + !page.ADDP) + sb.AppendLine("\tDevice may erase any or all partitions on MODE SELECT for partitioning"); + else if(page.CLEAR && + !page.ADDP) + sb.AppendLine("\tDevice shall erase all partitions on MODE SELECT for partitioning"); + else if(!page.CLEAR) + sb.AppendLine("\tDevice shall not erase any partition on MODE SELECT for partitioning"); + else + sb.AppendLine("\tDevice shall erase all partitions differing on size on MODE SELECT for partitioning"); + + string measure; + + switch(page.PSUM) + { + case PartitionSizeUnitOfMeasures.Bytes: + sb.AppendLine("\tPartitions are defined in bytes"); + measure = "bytes"; + + break; + case PartitionSizeUnitOfMeasures.Kilobytes: + sb.AppendLine("\tPartitions are defined in kilobytes"); + measure = "kilobytes"; + + break; + case PartitionSizeUnitOfMeasures.Megabytes: + sb.AppendLine("\tPartitions are defined in megabytes"); + measure = "megabytes"; + + break; + case PartitionSizeUnitOfMeasures.Exponential: + sb.AppendFormat("\tPartitions are defined in units of {0} bytes", + Math.Pow(10, page.PartitionUnits)).AppendLine(); + + measure = $"units of {Math.Pow(10, page.PartitionUnits)} bytes"; + + break; + default: + sb.AppendFormat("\tUnknown partition size unit code {0}", (byte)page.PSUM).AppendLine(); + measure = "units"; + + break; + } + + switch(page.MediumFormatRecognition) + { + case MediumFormatRecognitionValues.Capable: + sb.AppendLine("\tDevice is capable of recognizing both medium partitions and format"); + + break; + case MediumFormatRecognitionValues.FormatCapable: + sb.AppendLine("\tDevice is capable of recognizing medium format"); + + break; + case MediumFormatRecognitionValues.PartitionCapable: + sb.AppendLine("\tDevice is capable of recognizing medium partitions"); + + break; + case MediumFormatRecognitionValues.Incapable: + sb.AppendLine("\tDevice is not capable of recognizing neither medium partitions nor format"); + + break; + default: + sb.AppendFormat("\tUnknown medium recognition code {0}", (byte)page.MediumFormatRecognition). + AppendLine(); + + break; + } + + sb.AppendFormat("\tMedium has defined {0} partitions", page.PartitionSizes.Length).AppendLine(); + + for(int i = 0; i < page.PartitionSizes.Length; i++) + if(page.PartitionSizes[i] == 0) + if(page.PartitionSizes.Length == 1) + sb.AppendLine("\tDevice recognizes one single partition spanning whole medium"); + else + sb.AppendFormat("\tPartition {0} runs for rest of medium", i).AppendLine(); + else + sb.AppendFormat("\tPartition {0} is {1} {2} long", i, page.PartitionSizes[i], measure).AppendLine(); + + return sb.ToString(); + } + #endregion Mode Page 0x11: Medium partition page (1) + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/12_13_14.cs b/Aaru.Decoders/SCSI/Modes/12_13_14.cs new file mode 100644 index 000000000..030599db9 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/12_13_14.cs @@ -0,0 +1,111 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 12_13_14.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGEs 12h, 13h, 14h: Medium partition page (2-4). +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Pages 0x12, 0x13, 0x14: Medium partition page (2-4) + /// Medium partition page (2-4) Page codes 0x12, 0x13 and 0x14 + public struct ModePage_12_13_14 + { + /// Parameters can be saved + public bool PS; + /// Array of partition sizes in units defined in mode page 11 + public ushort[] PartitionSizes; + } + + public static ModePage_12_13_14? DecodeModePage_12_13_14(byte[] pageResponse) + { + if(pageResponse == null) + return null; + + if((pageResponse[0] & 0x40) == 0x40) + return null; + + if((pageResponse[0] & 0x3F) != 0x12 && + (pageResponse[0] & 0x3F) != 0x13 && + (pageResponse[0] & 0x3F) != 0x14) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 2) + return null; + + var decoded = new ModePage_12_13_14(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + + decoded.PartitionSizes = new ushort[(pageResponse.Length - 2) / 2]; + + for(int i = 2; i < pageResponse.Length; i += 2) + { + decoded.PartitionSizes[(i - 2) / 2] = (ushort)(pageResponse[i] << 8); + decoded.PartitionSizes[(i - 2) / 2] += pageResponse[i + 1]; + } + + return decoded; + } + + public static string PrettifyModePage_12_13_14(byte[] pageResponse) => + PrettifyModePage_12_13_14(DecodeModePage_12_13_14(pageResponse)); + + public static string PrettifyModePage_12_13_14(ModePage_12_13_14? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_12_13_14 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI medium partition page (extra):"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + sb.AppendFormat("\tMedium has defined {0} partitions", page.PartitionSizes.Length).AppendLine(); + + for(int i = 0; i < page.PartitionSizes.Length; i++) + sb.AppendFormat("\tPartition {0} is {1} units long", i, page.PartitionSizes[i]).AppendLine(); + + return sb.ToString(); + } + #endregion Mode Pages 0x12, 0x13, 0x14: Medium partition page (2-4) + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/1A.cs b/Aaru.Decoders/SCSI/Modes/1A.cs new file mode 100644 index 000000000..454cc697b --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/1A.cs @@ -0,0 +1,272 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 1A.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 1Ah: Power condition page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x1A: Power condition page + /// Power condition page Page code 0x1A 12 bytes in SPC-1, SPC-2, SPC-3, SPC-4 40 bytes in SPC-5 + public struct ModePage_1A + { + /// Parameters can be saved + public bool PS; + /// Idle timer activated + public bool Idle; + /// Standby timer activated + public bool Standby; + /// Idle timer + public uint IdleTimer; + /// Standby timer + public uint StandbyTimer; + + /// Interactions between background functions and power management + public byte PM_BG_Precedence; + /// Standby timer Y activated + public bool Standby_Y; + /// Idle timer B activated + public bool Idle_B; + /// Idle timer C activated + public bool Idle_C; + /// Idle timer B + public uint IdleTimer_B; + /// Idle timer C + public uint IdleTimer_C; + /// Standby timer Y + public uint StandbyTimer_Y; + public byte CCF_Idle; + public byte CCF_Standby; + public byte CCF_Stopped; + } + + public static ModePage_1A? DecodeModePage_1A(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x1A) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 12) + return null; + + var decoded = new ModePage_1A(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + + decoded.Standby |= (pageResponse[3] & 0x01) == 0x01; + decoded.Idle |= (pageResponse[3] & 0x02) == 0x02; + + decoded.IdleTimer = (uint)((pageResponse[4] << 24) + (pageResponse[5] << 16) + (pageResponse[6] << 8) + + pageResponse[7]); + + decoded.StandbyTimer = (uint)((pageResponse[8] << 24) + (pageResponse[9] << 16) + (pageResponse[10] << 8) + + pageResponse[11]); + + if(pageResponse.Length < 40) + return decoded; + + decoded.PM_BG_Precedence = (byte)((pageResponse[2] & 0xC0) >> 6); + decoded.Standby_Y |= (pageResponse[2] & 0x01) == 0x01; + decoded.Idle_B |= (pageResponse[3] & 0x04) == 0x04; + decoded.Idle_C |= (pageResponse[3] & 0x08) == 0x08; + + decoded.IdleTimer_B = (uint)((pageResponse[12] << 24) + (pageResponse[13] << 16) + (pageResponse[14] << 8) + + pageResponse[15]); + + decoded.IdleTimer_C = (uint)((pageResponse[16] << 24) + (pageResponse[17] << 16) + (pageResponse[18] << 8) + + pageResponse[19]); + + decoded.StandbyTimer_Y = (uint)((pageResponse[20] << 24) + (pageResponse[21] << 16) + + (pageResponse[22] << 8) + pageResponse[23]); + + decoded.CCF_Idle = (byte)((pageResponse[39] & 0xC0) >> 6); + decoded.CCF_Standby = (byte)((pageResponse[39] & 0x30) >> 4); + decoded.CCF_Stopped = (byte)((pageResponse[39] & 0x0C) >> 2); + + return decoded; + } + + public static string PrettifyModePage_1A(byte[] pageResponse) => + PrettifyModePage_1A(DecodeModePage_1A(pageResponse)); + + public static string PrettifyModePage_1A(ModePage_1A? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_1A page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Power condition page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if((page.Standby && page.StandbyTimer > 0) || + (page.Standby_Y && page.StandbyTimer_Y > 0)) + { + if(page.Standby && + page.StandbyTimer > 0) + sb.AppendFormat("\tStandby timer Z is set to {0} ms", page.StandbyTimer * 100).AppendLine(); + + if(page.Standby_Y && + page.StandbyTimer_Y > 0) + sb.AppendFormat("\tStandby timer Y is set to {0} ms", page.StandbyTimer_Y * 100).AppendLine(); + } + else + sb.AppendLine("\tDrive will not enter standy mode"); + + if((page.Idle && page.IdleTimer > 0) || + (page.Idle_B && page.IdleTimer_B > 0) || + (page.Idle_C && page.IdleTimer_C > 0)) + { + if(page.Idle && + page.IdleTimer > 0) + sb.AppendFormat("\tIdle timer A is set to {0} ms", page.IdleTimer * 100).AppendLine(); + + if(page.Idle_B && + page.IdleTimer_B > 0) + sb.AppendFormat("\tIdle timer B is set to {0} ms", page.IdleTimer_B * 100).AppendLine(); + + if(page.Idle_C && + page.IdleTimer_C > 0) + sb.AppendFormat("\tIdle timer C is set to {0} ms", page.IdleTimer_C * 100).AppendLine(); + } + else + sb.AppendLine("\tDrive will not enter idle mode"); + + switch(page.PM_BG_Precedence) + { + case 0: break; + case 1: + sb.AppendLine("\tPerforming background functions take precedence over maintaining low power conditions"); + + break; + case 2: + sb.AppendLine("\tMaintaining low power conditions take precedence over performing background functions"); + + break; + } + + return sb.ToString(); + } + #endregion Mode Page 0x1A: Power condition page + + #region Mode Page 0x1A subpage 0x01: Power Consumption mode page + /// Power Consumption mode page Page code 0x1A Subpage code 0x01 16 bytes in SPC-5 + public struct ModePage_1A_S01 + { + /// Parameters can be saved + public bool PS; + /// Active power level + public byte ActiveLevel; + /// Power Consumption VPD identifier in use + public byte PowerConsumptionIdentifier; + } + + public static ModePage_1A_S01? DecodeModePage_1A_S01(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) != 0x40) + return null; + + if((pageResponse[0] & 0x3F) != 0x1A) + return null; + + if(pageResponse[1] != 0x01) + return null; + + if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) + return null; + + if(pageResponse.Length < 16) + return null; + + var decoded = new ModePage_1A_S01(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.ActiveLevel = (byte)(pageResponse[6] & 0x03); + decoded.PowerConsumptionIdentifier = pageResponse[7]; + + return decoded; + } + + public static string PrettifyModePage_1A_S01(byte[] pageResponse) => + PrettifyModePage_1A_S01(DecodeModePage_1A_S01(pageResponse)); + + public static string PrettifyModePage_1A_S01(ModePage_1A_S01? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_1A_S01 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Power Consumption page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + switch(page.ActiveLevel) + { + case 0: + sb.AppendFormat("\tDevice power consumption is dictated by identifier {0} of Power Consumption VPD", + page.PowerConsumptionIdentifier).AppendLine(); + + break; + case 1: + sb.AppendLine("\tDevice is in highest relative power consumption level"); + + break; + case 2: + sb.AppendLine("\tDevice is in intermediate relative power consumption level"); + + break; + case 3: + sb.AppendLine("\tDevice is in lowest relative power consumption level"); + + break; + } + + return sb.ToString(); + } + #endregion Mode Page 0x1A subpage 0x01: Power Consumption mode page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/1B.cs b/Aaru.Decoders/SCSI/Modes/1B.cs new file mode 100644 index 000000000..ee80731ec --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/1B.cs @@ -0,0 +1,122 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 1B.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 1Bh: Removable Block Access Capabilities page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x1B: Removable Block Access Capabilities page + /// Removable Block Access Capabilities page Page code 0x1B 12 bytes in INF-8070 + public struct ModePage_1B + { + /// Parameters can be saved + public bool PS; + /// Supports reporting progress of format + public bool SRFP; + /// Non-CD Optical Device + public bool NCD; + /// Phase change dual device supporting a CD and a Non-CD Optical devices + public bool SML; + /// Total number of LUNs + public byte TLUN; + /// System Floppy Type device + public bool SFLP; + } + + public static ModePage_1B? DecodeModePage_1B(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x1B) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 12) + return null; + + var decoded = new ModePage_1B(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.SFLP |= (pageResponse[2] & 0x80) == 0x80; + decoded.SRFP |= (pageResponse[2] & 0x40) == 0x40; + decoded.NCD |= (pageResponse[3] & 0x80) == 0x80; + decoded.SML |= (pageResponse[3] & 0x40) == 0x40; + + decoded.TLUN = (byte)(pageResponse[3] & 0x07); + + return decoded; + } + + public static string PrettifyModePage_1B(byte[] pageResponse) => + PrettifyModePage_1B(DecodeModePage_1B(pageResponse)); + + public static string PrettifyModePage_1B(ModePage_1B? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_1B page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Removable Block Access Capabilities page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.SFLP) + sb.AppendLine("\tDrive can be used as a system floppy device"); + + if(page.SRFP) + sb.AppendLine("\tDrive supports reporting progress of format"); + + if(page.NCD) + sb.AppendLine("\tDrive is a Non-CD Optical Device"); + + if(page.SML) + sb.AppendLine("\tDevice is a dual device supporting CD and Non-CD Optical"); + + if(page.TLUN > 0) + sb.AppendFormat("\tDrive supports {0} LUNs", page.TLUN).AppendLine(); + + return sb.ToString(); + } + #endregion Mode Page 0x1B: Removable Block Access Capabilities page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/1C.cs b/Aaru.Decoders/SCSI/Modes/1C.cs new file mode 100644 index 000000000..ebef8e21a --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/1C.cs @@ -0,0 +1,310 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 1C.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 1Ch: Informational exceptions control page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x1C: Informational exceptions control page + /// Informational exceptions control page Page code 0x1C 12 bytes in SPC-1, SPC-2, SPC-3, SPC-4 + public struct ModePage_1C + { + /// Parameters can be saved + public bool PS; + /// Informational exception operations should not affect performance + public bool Perf; + /// Disable informational exception operations + public bool DExcpt; + /// Create a test device failure at next interval time + public bool Test; + /// Log informational exception conditions + public bool LogErr; + /// Method of reporting informational exceptions + public byte MRIE; + /// 100 ms period to report an informational exception condition + public uint IntervalTimer; + /// How many times to report informational exceptions + public uint ReportCount; + + /// Enable background functions + public bool EBF; + /// Warning reporting enabled + public bool EWasc; + + /// Enable reporting of background self-test errors + public bool EBACKERR; + } + + public static ModePage_1C? DecodeModePage_1C(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x1C) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 8) + return null; + + var decoded = new ModePage_1C(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + + decoded.Perf |= (pageResponse[2] & 0x80) == 0x80; + decoded.DExcpt |= (pageResponse[2] & 0x08) == 0x08; + decoded.Test |= (pageResponse[2] & 0x04) == 0x04; + decoded.LogErr |= (pageResponse[2] & 0x01) == 0x01; + + decoded.MRIE = (byte)(pageResponse[3] & 0x0F); + + decoded.IntervalTimer = (uint)((pageResponse[4] << 24) + (pageResponse[5] << 16) + (pageResponse[6] << 8) + + pageResponse[7]); + + decoded.EBF |= (pageResponse[2] & 0x20) == 0x20; + decoded.EWasc |= (pageResponse[2] & 0x10) == 0x10; + + decoded.EBACKERR |= (pageResponse[2] & 0x02) == 0x02; + + if(pageResponse.Length >= 12) + decoded.ReportCount = (uint)((pageResponse[8] << 24) + (pageResponse[9] << 16) + + (pageResponse[10] << 8) + pageResponse[11]); + + return decoded; + } + + public static string PrettifyModePage_1C(byte[] pageResponse) => + PrettifyModePage_1C(DecodeModePage_1C(pageResponse)); + + public static string PrettifyModePage_1C(ModePage_1C? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_1C page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Informational exceptions control page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.DExcpt) + sb.AppendLine("\tInformational exceptions are disabled"); + else + { + sb.AppendLine("\tInformational exceptions are enabled"); + + switch(page.MRIE) + { + case 0: + sb.AppendLine("\tNo reporting of informational exception condition"); + + break; + case 1: + sb.AppendLine("\tAsynchronous event reporting of informational exceptions"); + + break; + case 2: + sb.AppendLine("\tGenerate unit attention on informational exceptions"); + + break; + case 3: + sb.AppendLine("\tConditionally generate recovered error on informational exceptions"); + + break; + case 4: + sb.AppendLine("\tUnconditionally generate recovered error on informational exceptions"); + + break; + case 5: + sb.AppendLine("\tGenerate no sense on informational exceptions"); + + break; + case 6: + sb.AppendLine("\tOnly report informational exception condition on request"); + + break; + default: + sb.AppendFormat("\tUnknown method of reporting {0}", page.MRIE).AppendLine(); + + break; + } + + if(page.Perf) + sb.AppendLine("\tInformational exceptions reporting should not affect drive performance"); + + if(page.Test) + sb.AppendLine("\tA test informational exception will raise on next timer"); + + if(page.LogErr) + sb.AppendLine("\tDrive shall log informational exception conditions"); + + if(page.IntervalTimer > 0) + if(page.IntervalTimer == 0xFFFFFFFF) + sb.AppendLine("\tTimer interval is vendor-specific"); + else + sb.AppendFormat("\tTimer interval is {0} ms", page.IntervalTimer * 100).AppendLine(); + + if(page.ReportCount > 0) + sb.AppendFormat("\tInformational exception conditions will be reported a maximum of {0} times", + page.ReportCount); + } + + if(page.EWasc) + sb.AppendLine("\tWarning reporting is enabled"); + + if(page.EBF) + sb.AppendLine("\tBackground functions are enabled"); + + if(page.EBACKERR) + sb.AppendLine("\tDrive will report background self-test errors"); + + return sb.ToString(); + } + #endregion Mode Page 0x1C: Informational exceptions control page + + #region Mode Page 0x1C subpage 0x01: Background Control mode page + /// Background Control mode page Page code 0x1A Subpage code 0x01 16 bytes in SPC-5 + public struct ModePage_1C_S01 + { + /// Parameters can be saved + public bool PS; + /// Suspend on log full + public bool S_L_Full; + /// Log only when intervention required + public bool LOWIR; + /// Enable background medium scan + public bool En_Bms; + /// Enable background pre-scan + public bool En_Ps; + /// Time in hours between background medium scans + public ushort BackgroundScanInterval; + /// Maximum time in hours for a background pre-scan to complete + public ushort BackgroundPrescanTimeLimit; + /// Minimum time in ms being idle before resuming a background scan + public ushort MinIdleBeforeBgScan; + /// Maximum time in ms to start processing commands while performing a background scan + public ushort MaxTimeSuspendBgScan; + } + + public static ModePage_1C_S01? DecodeModePage_1C_S01(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) != 0x40) + return null; + + if((pageResponse[0] & 0x3F) != 0x1C) + return null; + + if(pageResponse[1] != 0x01) + return null; + + if((pageResponse[2] << 8) + pageResponse[3] + 4 != pageResponse.Length) + return null; + + if(pageResponse.Length < 16) + return null; + + var decoded = new ModePage_1C_S01(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + + decoded.S_L_Full |= (pageResponse[4] & 0x04) == 0x04; + decoded.LOWIR |= (pageResponse[4] & 0x02) == 0x02; + decoded.En_Bms |= (pageResponse[4] & 0x01) == 0x01; + decoded.En_Ps |= (pageResponse[5] & 0x01) == 0x01; + + decoded.BackgroundScanInterval = (ushort)((pageResponse[6] << 8) + pageResponse[7]); + decoded.BackgroundPrescanTimeLimit = (ushort)((pageResponse[8] << 8) + pageResponse[9]); + decoded.MinIdleBeforeBgScan = (ushort)((pageResponse[10] << 8) + pageResponse[11]); + decoded.MaxTimeSuspendBgScan = (ushort)((pageResponse[12] << 8) + pageResponse[13]); + + return decoded; + } + + public static string PrettifyModePage_1C_S01(byte[] pageResponse) => + PrettifyModePage_1C_S01(DecodeModePage_1C_S01(pageResponse)); + + public static string PrettifyModePage_1C_S01(ModePage_1C_S01? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_1C_S01 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Background Control page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.S_L_Full) + sb.AppendLine("\tBackground scans will be halted if log is full"); + + if(page.LOWIR) + sb.AppendLine("\tBackground scans will only be logged if they require intervention"); + + if(page.En_Bms) + sb.AppendLine("\tBackground medium scans are enabled"); + + if(page.En_Ps) + sb.AppendLine("\tBackground pre-scans are enabled"); + + if(page.BackgroundScanInterval > 0) + sb.AppendFormat("\t{0} hours shall be between the start of a background scan operation and the next", + page.BackgroundScanInterval).AppendLine(); + + if(page.BackgroundPrescanTimeLimit > 0) + sb.AppendFormat("\tBackgroun pre-scan operations can take a maximum of {0} hours", + page.BackgroundPrescanTimeLimit).AppendLine(); + + if(page.MinIdleBeforeBgScan > 0) + sb.AppendFormat("\tAt least {0} ms must be idle before resuming a suspended background scan operation", + page.MinIdleBeforeBgScan).AppendLine(); + + if(page.MaxTimeSuspendBgScan > 0) + sb. + AppendFormat("\tAt most {0} ms must be before suspending a background scan operation and processing received commands", + page.MaxTimeSuspendBgScan).AppendLine(); + + return sb.ToString(); + } + #endregion Mode Page 0x1C subpage 0x01: Background Control mode page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/1C_SFF.cs b/Aaru.Decoders/SCSI/Modes/1C_SFF.cs new file mode 100644 index 000000000..a112afcc0 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/1C_SFF.cs @@ -0,0 +1,175 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 1C_SFF.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 1Ch: Timer & Protect page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x1C: Timer & Protect page + /// Timer & Protect page Page code 0x1C 8 bytes in INF-8070 + public struct ModePage_1C_SFF + { + /// Parameters can be saved + public bool PS; + /// Time the device shall remain in the current state after seek, read or write operation + public byte InactivityTimeMultiplier; + /// Disabled until power cycle + public bool DISP; + /// Software Write Protect until Power-down + public bool SWPP; + } + + public static ModePage_1C_SFF? DecodeModePage_1C_SFF(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x1C) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 8) + return null; + + var decoded = new ModePage_1C_SFF(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.DISP |= (pageResponse[2] & 0x02) == 0x02; + decoded.SWPP |= (pageResponse[3] & 0x01) == 0x01; + + decoded.InactivityTimeMultiplier = (byte)(pageResponse[3] & 0x0F); + + return decoded; + } + + public static string PrettifyModePage_1C_SFF(byte[] pageResponse) => + PrettifyModePage_1C_SFF(DecodeModePage_1C_SFF(pageResponse)); + + public static string PrettifyModePage_1C_SFF(ModePage_1C_SFF? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_1C_SFF page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Timer & Protect page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.DISP) + sb.AppendLine("\tDrive is disabled until power is cycled"); + + if(page.SWPP) + sb.AppendLine("\tDrive is software write-protected until powered down"); + + switch(page.InactivityTimeMultiplier) + { + case 0: + sb.AppendLine("\tDrive will remain in same status a vendor-specified time after a seek, read or write operation"); + + break; + case 1: + sb.AppendLine("\tDrive will remain in same status 125 ms after a seek, read or write operation"); + + break; + case 2: + sb.AppendLine("\tDrive will remain in same status 250 ms after a seek, read or write operation"); + + break; + case 3: + sb.AppendLine("\tDrive will remain in same status 500 ms after a seek, read or write operation"); + + break; + case 4: + sb.AppendLine("\tDrive will remain in same status 1 second after a seek, read or write operation"); + + break; + case 5: + sb.AppendLine("\tDrive will remain in same status 2 seconds after a seek, read or write operation"); + + break; + case 6: + sb.AppendLine("\tDrive will remain in same status 4 seconds after a seek, read or write operation"); + + break; + case 7: + sb.AppendLine("\tDrive will remain in same status 8 seconds after a seek, read or write operation"); + + break; + case 8: + sb.AppendLine("\tDrive will remain in same status 16 seconds after a seek, read or write operation"); + + break; + case 9: + sb.AppendLine("\tDrive will remain in same status 32 seconds after a seek, read or write operation"); + + break; + case 10: + sb.AppendLine("\tDrive will remain in same status 1 minute after a seek, read or write operation"); + + break; + case 11: + sb.AppendLine("\tDrive will remain in same status 2 minutes after a seek, read or write operation"); + + break; + case 12: + sb.AppendLine("\tDrive will remain in same status 4 minutes after a seek, read or write operation"); + + break; + case 13: + sb.AppendLine("\tDrive will remain in same status 8 minutes after a seek, read or write operation"); + + break; + case 14: + sb.AppendLine("\tDrive will remain in same status 16 minutes after a seek, read or write operation"); + + break; + case 15: + sb.AppendLine("\tDrive will remain in same status 32 minutes after a seek, read or write operation"); + + break; + } + + return sb.ToString(); + } + #endregion Mode Page 0x1C: Timer & Protect page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/1D.cs b/Aaru.Decoders/SCSI/Modes/1D.cs new file mode 100644 index 000000000..d9638799c --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/1D.cs @@ -0,0 +1,137 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 1D.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 1Dh: Medium Configuration Mode Page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Mode Page 0x1D: Medium Configuration Mode Page + public struct ModePage_1D + { + /// Parameters can be saved + public bool PS; + public bool WORMM; + public byte WormModeLabelRestrictions; + public byte WormModeFilemarkRestrictions; + } + + public static ModePage_1D? DecodeModePage_1D(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x1D) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 32) + return null; + + var decoded = new ModePage_1D(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.WORMM |= (pageResponse[2] & 0x01) == 0x01; + decoded.WormModeLabelRestrictions = pageResponse[4]; + decoded.WormModeFilemarkRestrictions = pageResponse[5]; + + return decoded; + } + + public static string PrettifyModePage_1D(byte[] pageResponse) => + PrettifyModePage_1D(DecodeModePage_1D(pageResponse)); + + public static string PrettifyModePage_1D(ModePage_1D? modePage) + { + if(!modePage.HasValue) + return null; + + ModePage_1D page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Medium Configuration Mode Page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.WORMM) + sb.AppendLine("\tDrive is operating in WORM mode"); + + switch(page.WormModeLabelRestrictions) + { + case 0: + sb.AppendLine("\tDrive does not allow any logical blocks to be overwritten"); + + break; + case 1: + sb.AppendLine("\tDrive allows a tape header to be overwritten"); + + break; + case 2: + sb.AppendLine("\tDrive allows all format labels to be overwritten"); + + break; + default: + sb.AppendFormat("\tUnknown WORM mode label restrictions code {0}", page.WormModeLabelRestrictions). + AppendLine(); + + break; + } + + switch(page.WormModeFilemarkRestrictions) + { + case 2: + sb.AppendLine("\tDrive allows any number of filemarks immediately preceding EOD to be overwritten except filemark closes to BOP"); + + break; + case 3: + sb.AppendLine("\tDrive allows any number of filemarks immediately preceding EOD to be overwritten"); + + break; + default: + sb.AppendFormat("\tUnknown WORM mode filemark restrictions code {0}", + page.WormModeLabelRestrictions).AppendLine(); + + break; + } + + return sb.ToString(); + } + #endregion Mode Page 0x1D: Medium Configuration Mode Page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/21_Certance.cs b/Aaru.Decoders/SCSI/Modes/21_Certance.cs new file mode 100644 index 000000000..2984898b0 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/21_Certance.cs @@ -0,0 +1,205 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 21_Certance.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes Certance MODE PAGE 21h: Drive Capabilities Control Mode page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Certance Mode Page 0x21: Drive Capabilities Control Mode page + public struct Certance_ModePage_21 + { + /// Parameters can be saved + public bool PS; + public byte OperatingSystemsSupport; + public byte FirmwareTestControl2; + public byte ExtendedPOSTMode; + public byte InquiryStringControl; + public byte FirmwareTestControl; + public byte DataCompressionControl; + public bool HostUnloadOverride; + public byte AutoUnloadMode; + } + + public static Certance_ModePage_21? DecodeCertanceModePage_21(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x21) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length != 9) + return null; + + var decoded = new Certance_ModePage_21(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.OperatingSystemsSupport = pageResponse[2]; + decoded.FirmwareTestControl2 = pageResponse[3]; + decoded.ExtendedPOSTMode = pageResponse[4]; + decoded.InquiryStringControl = pageResponse[5]; + decoded.FirmwareTestControl = pageResponse[6]; + decoded.DataCompressionControl = pageResponse[7]; + decoded.HostUnloadOverride |= (pageResponse[8] & 0x80) == 0x80; + decoded.AutoUnloadMode = (byte)(pageResponse[8] & 0x7F); + + return decoded; + } + + public static string PrettifyCertanceModePage_21(byte[] pageResponse) => + PrettifyCertanceModePage_21(DecodeCertanceModePage_21(pageResponse)); + + public static string PrettifyCertanceModePage_21(Certance_ModePage_21? modePage) + { + if(!modePage.HasValue) + return null; + + Certance_ModePage_21 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("Certance Drive Capabilities Control Mode Page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + switch(page.OperatingSystemsSupport) + { + case 0: + sb.AppendLine("\tOperating systems support is standard LTO"); + + break; + default: + sb.AppendFormat("\tOperating systems support is unknown code {0}", page.OperatingSystemsSupport). + AppendLine(); + + break; + } + + if(page.FirmwareTestControl == page.FirmwareTestControl2) + switch(page.FirmwareTestControl) + { + case 0: + sb.AppendLine("\tFactory test code is disabled"); + + break; + case 1: + sb.AppendLine("\tFactory test code 1 is disabled"); + + break; + case 2: + sb.AppendLine("\tFactory test code 2 is disabled"); + + break; + default: + sb.AppendFormat("\tUnknown factory test code {0}", page.FirmwareTestControl).AppendLine(); + + break; + } + + switch(page.ExtendedPOSTMode) + { + case 0: + sb.AppendLine("\tPower-On Self-Test is enabled"); + + break; + case 1: + sb.AppendLine("\tPower-On Self-Test is disable"); + + break; + default: + sb.AppendFormat("\tUnknown Power-On Self-Test code {0}", page.ExtendedPOSTMode).AppendLine(); + + break; + } + + switch(page.DataCompressionControl) + { + case 0: + sb.AppendLine("\tCompression is controlled using mode pages 0Fh and 10h"); + + break; + case 1: + sb.AppendLine("\tCompression is enabled and not controllable"); + + break; + case 2: + sb.AppendLine("\tCompression is disabled and not controllable"); + + break; + default: + sb.AppendFormat("\tUnknown compression control code {0}", page.DataCompressionControl).AppendLine(); + + break; + } + + if(page.HostUnloadOverride) + sb.AppendLine("\tSCSI UNLOAD command will not eject the cartridge"); + + sb.Append("\tHow should tapes be unloaded in a power cycle, tape incompatibility, firmware download or cleaning end: "); + + switch(page.AutoUnloadMode) + { + case 0: + sb.AppendLine("\tTape will stay threaded at beginning"); + + break; + case 1: + sb.AppendLine("\tTape will be unthreaded"); + + break; + case 2: + sb.AppendLine("\tTape will be unthreaded and unloaded"); + + break; + case 3: + sb.AppendLine("\tData tapes will be threaded at beginning, rest will be unloaded"); + + break; + default: + sb.AppendFormat("\tUnknown auto unload code {0}", page.AutoUnloadMode).AppendLine(); + + break; + } + + return sb.ToString(); + } + #endregion Certance Mode Page 0x21: Drive Capabilities Control Mode page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/22_Certance.cs b/Aaru.Decoders/SCSI/Modes/22_Certance.cs new file mode 100644 index 000000000..df25a76ef --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/22_Certance.cs @@ -0,0 +1,190 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 22_Certance.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes Certance MODE PAGE 22h: Interface Control Mode Page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static partial class Modes + { + #region Certance Mode Page 0x22: Interface Control Mode Page + public struct Certance_ModePage_22 + { + /// Parameters can be saved + public bool PS; + public byte BaudRate; + public byte CmdFwd; + public bool StopBits; + public byte Alerts; + public byte PortATransportType; + public byte PortAPresentSelectionID; + public byte NextSelectionID; + public byte JumperedSelectionID; + public byte TargetInitiatedBusControl; + public bool PortAEnabled; + public bool PortAEnabledOnPower; + } + + public static Certance_ModePage_22? DecodeCertanceModePage_22(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x22) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length != 16) + return null; + + var decoded = new Certance_ModePage_22(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.BaudRate = pageResponse[2]; + decoded.CmdFwd = (byte)((pageResponse[3] & 0x18) >> 3); + decoded.StopBits |= (pageResponse[3] & 0x04) == 0x04; + decoded.CmdFwd = (byte)(pageResponse[3] & 0x03); + decoded.PortATransportType = pageResponse[4]; + decoded.PortAPresentSelectionID = pageResponse[7]; + decoded.NextSelectionID = pageResponse[12]; + decoded.JumperedSelectionID = pageResponse[13]; + decoded.TargetInitiatedBusControl = pageResponse[14]; + decoded.PortAEnabled |= (pageResponse[15] & 0x10) == 0x10; + decoded.PortAEnabledOnPower |= (pageResponse[15] & 0x04) == 0x04; + + return decoded; + } + + public static string PrettifyCertanceModePage_22(byte[] pageResponse) => + PrettifyCertanceModePage_22(DecodeCertanceModePage_22(pageResponse)); + + public static string PrettifyCertanceModePage_22(Certance_ModePage_22? modePage) + { + if(!modePage.HasValue) + return null; + + Certance_ModePage_22 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("Certance Interface Control Mode Page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + switch(page.BaudRate) + { + case 0: + case 1: + case 2: + sb.AppendLine("\tLibrary interface will operate at 9600 baud on next reset"); + + break; + case 3: + sb.AppendLine("\tLibrary interface will operate at 19200 baud on next reset"); + + break; + case 4: + sb.AppendLine("\tLibrary interface will operate at 38400 baud on next reset"); + + break; + case 5: + sb.AppendLine("\tLibrary interface will operate at 57600 baud on next reset"); + + break; + case 6: + sb.AppendLine("\tLibrary interface will operate at 115200 baud on next reset"); + + break; + default: + sb.AppendFormat("\tUnknown library interface baud rate code {0}", page.BaudRate).AppendLine(); + + break; + } + + sb.AppendLine(page.StopBits ? "Library interface transmits 2 stop bits per byte" + : "Library interface transmits 1 stop bits per byte"); + + switch(page.CmdFwd) + { + case 0: + sb.AppendLine("\tCommand forwarding is disabled"); + + break; + case 1: + sb.AppendLine("\tCommand forwarding is enabled"); + + break; + default: + sb.AppendFormat("\tUnknown command forwarding code {0}", page.CmdFwd).AppendLine(); + + break; + } + + switch(page.PortATransportType) + { + case 0: + sb.AppendLine("\tPort A link is down"); + + break; + case 3: + sb.AppendLine("\tPort A uses Parallel SCSI Ultra-160 interface"); + + break; + default: + sb.AppendFormat("\tUnknown port A transport type code {0}", page.PortATransportType).AppendLine(); + + break; + } + + if(page.PortATransportType > 0) + sb.AppendFormat("\tDrive responds to SCSI ID {0}", page.PortAPresentSelectionID).AppendLine(); + + sb.AppendFormat("\tDrive will respond to SCSI ID {0} on Port A enabling", page.NextSelectionID). + AppendLine(); + + sb.AppendFormat("\tDrive jumpers choose SCSI ID {0}", page.JumperedSelectionID).AppendLine(); + + sb.AppendLine(page.PortAEnabled ? "\tSCSI port is enabled" : "\tSCSI port is disabled"); + + sb.AppendLine(page.PortAEnabledOnPower ? "\tSCSI port will be enabled on next power up" + : "\tSCSI port will be disabled on next power up"); + + return sb.ToString(); + } + #endregion Certance Mode Page 0x22: Interface Control Mode Page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/24_IBM.cs b/Aaru.Decoders/SCSI/Modes/24_IBM.cs new file mode 100644 index 000000000..7a92a6538 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/24_IBM.cs @@ -0,0 +1,109 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 24_IBM.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes IBM MODE PAGE 24h: Drive Capabilities Control Mode page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region IBM Mode Page 0x24: Drive Capabilities Control Mode page + public struct IBM_ModePage_24 + { + /// Parameters can be saved + public bool PS; + public byte ModeControl; + public byte VelocitySetting; + public bool EncryptionEnabled; + public bool EncryptionCapable; + } + + public static IBM_ModePage_24? DecodeIBMModePage_24(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x24) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length != 8) + return null; + + var decoded = new IBM_ModePage_24(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.ModeControl = pageResponse[2]; + decoded.VelocitySetting = pageResponse[3]; + decoded.EncryptionEnabled |= (pageResponse[7] & 0x08) == 0x08; + decoded.EncryptionCapable |= (pageResponse[7] & 0x01) == 0x01; + + return decoded; + } + + public static string PrettifyIBMModePage_24(byte[] pageResponse) => + PrettifyIBMModePage_24(DecodeIBMModePage_24(pageResponse)); + + public static string PrettifyIBMModePage_24(IBM_ModePage_24? modePage) + { + if(!modePage.HasValue) + return null; + + IBM_ModePage_24 page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("IBM Vendor-Specific Control Mode Page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + sb.AppendFormat("\tVendor-specific mode control: {0}", page.ModeControl); + sb.AppendFormat("\tVendor-specific velocity setting: {0}", page.VelocitySetting); + + if(!page.EncryptionCapable) + return sb.ToString(); + + sb.AppendLine("\tDrive supports encryption"); + + if(page.EncryptionEnabled) + sb.AppendLine("\tDrive has encryption enabled"); + + return sb.ToString(); + } + #endregion IBM Mode Page 0x24: Drive Capabilities Control Mode page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/2A.cs b/Aaru.Decoders/SCSI/Modes/2A.cs new file mode 100644 index 000000000..51a3a0fbe --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/2A.cs @@ -0,0 +1,243 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 2A.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI MODE PAGE 2Ah: CD-ROM capabilities page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text; +using Aaru.CommonTypes.Structs.Devices.SCSI.Modes; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static partial class Modes + { + #region Mode Page 0x2A: CD-ROM capabilities page + public static string PrettifyModePage_2A(byte[] pageResponse) => + PrettifyModePage_2A(ModePage_2A.Decode(pageResponse)); + + public static string PrettifyModePage_2A(ModePage_2A modePage) + { + if(modePage is null) + return null; + + ModePage_2A page = modePage; + var sb = new StringBuilder(); + + sb.AppendLine("SCSI CD-ROM capabilities page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.AudioPlay) + sb.AppendLine("\tDrive can play audio"); + + if(page.Mode2Form1) + sb.AppendLine("\tDrive can read sectors in Mode 2 Form 1 format"); + + if(page.Mode2Form2) + sb.AppendLine("\tDrive can read sectors in Mode 2 Form 2 format"); + + if(page.MultiSession) + sb.AppendLine("\tDrive supports multi-session discs and/or Photo-CD"); + + if(page.CDDACommand) + sb.AppendLine("\tDrive can read digital audio"); + + if(page.AccurateCDDA) + sb.AppendLine("\tDrive can continue from streaming loss"); + + if(page.Subchannel) + sb.AppendLine("\tDrive can read uncorrected and interleaved R-W subchannels"); + + if(page.DeinterlaveSubchannel) + sb.AppendLine("\tDrive can read, deinterleave and correct R-W subchannels"); + + if(page.C2Pointer) + sb.AppendLine("\tDrive supports C2 pointers"); + + if(page.UPC) + sb.AppendLine("\tDrive can read Media Catalogue Number"); + + if(page.ISRC) + sb.AppendLine("\tDrive can read ISRC"); + + switch(page.LoadingMechanism) + { + case 0: + sb.AppendLine("\tDrive uses media caddy"); + + break; + case 1: + sb.AppendLine("\tDrive uses a tray"); + + break; + case 2: + sb.AppendLine("\tDrive is pop-up"); + + break; + case 4: + sb.AppendLine("\tDrive is a changer with individually changeable discs"); + + break; + case 5: + sb.AppendLine("\tDrive is a changer using cartridges"); + + break; + default: + sb.AppendFormat("\tDrive uses unknown loading mechanism type {0}", page.LoadingMechanism). + AppendLine(); + + break; + } + + if(page.Lock) + sb.AppendLine("\tDrive can lock media"); + + if(page.PreventJumper) + { + sb.AppendLine("\tDrive power ups locked"); + + sb.AppendLine(page.LockState ? "\tDrive is locked, media cannot be ejected or inserted" + : "\tDrive is not locked, media can be ejected and inserted"); + } + else + sb.AppendLine(page.LockState + ? "\tDrive is locked, media cannot be ejected, but if empty, can be inserted" + : "\tDrive is not locked, media can be ejected and inserted"); + + if(page.Eject) + sb.AppendLine("\tDrive can eject media"); + + if(page.SeparateChannelMute) + sb.AppendLine("\tEach channel can be muted independently"); + + if(page.SeparateChannelVolume) + sb.AppendLine("\tEach channel's volume can be controlled independently"); + + if(page.SupportedVolumeLevels > 0) + sb.AppendFormat("\tDrive supports {0} volume levels", page.SupportedVolumeLevels).AppendLine(); + + if(page.BufferSize > 0) + sb.AppendFormat("\tDrive has {0} Kbyte of buffer", page.BufferSize).AppendLine(); + + if(page.MaximumSpeed > 0) + sb.AppendFormat("\tDrive's maximum reading speed is {0} Kbyte/sec.", page.MaximumSpeed).AppendLine(); + + if(page.CurrentSpeed > 0) + sb.AppendFormat("\tDrive's current reading speed is {0} Kbyte/sec.", page.CurrentSpeed).AppendLine(); + + if(page.ReadCDR) + { + sb.AppendLine(page.WriteCDR ? "\tDrive can read and write CD-R" : "\tDrive can read CD-R"); + + if(page.Method2) + sb.AppendLine("\tDrive supports reading CD-R packet media"); + } + + if(page.ReadCDRW) + sb.AppendLine(page.WriteCDRW ? "\tDrive can read and write CD-RW" : "\tDrive can read CD-RW"); + + if(page.ReadDVDROM) + sb.AppendLine("\tDrive can read DVD-ROM"); + + if(page.ReadDVDR) + sb.AppendLine(page.WriteDVDR ? "\tDrive can read and write DVD-R" : "\tDrive can read DVD-R"); + + if(page.ReadDVDRAM) + sb.AppendLine(page.WriteDVDRAM ? "\tDrive can read and write DVD-RAM" : "\tDrive can read DVD-RAM"); + + if(page.Composite) + sb.AppendLine("\tDrive can deliver a composite audio and video data stream"); + + if(page.DigitalPort1) + sb.AppendLine("\tDrive supports IEC-958 digital output on port 1"); + + if(page.DigitalPort2) + sb.AppendLine("\tDrive supports IEC-958 digital output on port 2"); + + if(page.SDP) + sb.AppendLine("\tDrive contains a changer that can report the exact contents of the slots"); + + if(page.CurrentWriteSpeedSelected > 0) + { + if(page.RotationControlSelected == 0) + sb.AppendFormat("\tDrive's current writing speed is {0} Kbyte/sec. in CLV mode", + page.CurrentWriteSpeedSelected).AppendLine(); + else if(page.RotationControlSelected == 1) + sb.AppendFormat("\tDrive's current writing speed is {0} Kbyte/sec. in pure CAV mode", + page.CurrentWriteSpeedSelected).AppendLine(); + } + else + { + if(page.MaxWriteSpeed > 0) + sb.AppendFormat("\tDrive's maximum writing speed is {0} Kbyte/sec.", page.MaxWriteSpeed). + AppendLine(); + + if(page.CurrentWriteSpeed > 0) + sb.AppendFormat("\tDrive's current writing speed is {0} Kbyte/sec.", page.CurrentWriteSpeed). + AppendLine(); + } + + if(page.WriteSpeedPerformanceDescriptors != null) + foreach(ModePage_2A_WriteDescriptor descriptor in + page.WriteSpeedPerformanceDescriptors.Where(descriptor => descriptor.WriteSpeed > 0)) + if(descriptor.RotationControl == 0) + sb.AppendFormat("\tDrive supports writing at {0} Kbyte/sec. in CLV mode", + descriptor.WriteSpeed).AppendLine(); + else if(descriptor.RotationControl == 1) + sb.AppendFormat("\tDrive supports writing at is {0} Kbyte/sec. in pure CAV mode", + descriptor.WriteSpeed).AppendLine(); + + if(page.TestWrite) + sb.AppendLine("\tDrive supports test writing"); + + if(page.ReadBarcode) + sb.AppendLine("\tDrive can read barcode"); + + if(page.SCC) + sb.AppendLine("\tDrive can read both sides of a disc"); + + if(page.LeadInPW) + sb.AppendLine("\tDrive an read raw R-W subchannel from the Lead-In"); + + if(page.CMRSupported == 1) + sb.AppendLine("\tDrive supports DVD CSS and/or DVD CPPM"); + + if(page.BUF) + sb.AppendLine("\tDrive supports buffer under-run free recording"); + + return sb.ToString(); + } + #endregion Mode Page 0x2A: CD-ROM capabilities page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/2F_IBM.cs b/Aaru.Decoders/SCSI/Modes/2F_IBM.cs new file mode 100644 index 000000000..d280b8048 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/2F_IBM.cs @@ -0,0 +1,195 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 2F_IBM.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes IBM MODE PAGE 2Fh: Behaviour Configuration Mode page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "UnassignedField.Global")] + public static partial class Modes + { + #region IBM Mode Page 0x2F: Behaviour Configuration Mode page + public struct IBM_ModePage_2F + { + /// Parameters can be saved + public bool PS; + public byte FenceBehaviour; + public byte CleanBehaviour; + public byte WORMEmulation; + public byte SenseDataBehaviour; + public bool CCDM; + public bool DDEOR; + public bool CLNCHK; + public byte FirmwareUpdateBehaviour; + public byte UOE_D; + public byte UOE_F; + public byte UOE_C; + } + + public static IBM_ModePage_2F? DecodeIBMModePage_2F(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x2F) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length < 8) + return null; + + return new IBM_ModePage_2F + { + PS = (pageResponse[0] & 0x80) == 0x80, + FenceBehaviour = pageResponse[2], + CleanBehaviour = pageResponse[3], + WORMEmulation = pageResponse[4], + SenseDataBehaviour = pageResponse[5], + CCDM = (pageResponse[6] & 0x04) == 0x04, + DDEOR = (pageResponse[6] & 0x02) == 0x02, + CLNCHK = (pageResponse[6] & 0x01) == 0x01, + FirmwareUpdateBehaviour = pageResponse[7], + UOE_C = (byte)((pageResponse[8] & 0x30) >> 4), + UOE_F = (byte)((pageResponse[8] & 0x0C) >> 2) + }; + } + + public static string PrettifyIBMModePage_2F(byte[] pageResponse) => + PrettifyIBMModePage_2F(DecodeIBMModePage_2F(pageResponse)); + + public static string PrettifyIBMModePage_2F(IBM_ModePage_2F? modePage) + { + if(!modePage.HasValue) + return null; + + IBM_ModePage_2F page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("IBM Behaviour Configuration Mode Page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + switch(page.FenceBehaviour) + { + case 0: + sb.AppendLine("\tFence behaviour is normal"); + + break; + case 1: + sb.AppendLine("\tPanic fence behaviour is enabled"); + + break; + default: + sb.AppendFormat("\tUnknown fence behaviour code {0}", page.FenceBehaviour).AppendLine(); + + break; + } + + switch(page.CleanBehaviour) + { + case 0: + sb.AppendLine("\tCleaning behaviour is normal"); + + break; + case 1: + sb.AppendLine("\tDrive will periodically request cleaning"); + + break; + default: + sb.AppendFormat("\tUnknown cleaning behaviour code {0}", page.CleanBehaviour).AppendLine(); + + break; + } + + switch(page.WORMEmulation) + { + case 0: + sb.AppendLine("\tWORM emulation is disabled"); + + break; + case 1: + sb.AppendLine("\tWORM emulation is enabled"); + + break; + default: + sb.AppendFormat("\tUnknown WORM emulation code {0}", page.WORMEmulation).AppendLine(); + + break; + } + + switch(page.SenseDataBehaviour) + { + case 0: + sb.AppendLine("\tUses 35-bytes sense data"); + + break; + case 1: + sb.AppendLine("\tUses 96-bytes sense data"); + + break; + default: + sb.AppendFormat("\tUnknown sense data behaviour code {0}", page.WORMEmulation).AppendLine(); + + break; + } + + if(page.CLNCHK) + sb.AppendLine("\tDrive will set Check Condition when cleaning is needed"); + + if(page.DDEOR) + sb.AppendLine("\tNo deferred error will be reported to a rewind command"); + + if(page.CCDM) + sb.AppendLine("\tDrive will set Check Condition when the criteria for Dead Media is met"); + + if(page.FirmwareUpdateBehaviour > 0) + sb.AppendLine("\tDrive will not accept downlevel firmware via an FMR tape"); + + if(page.UOE_C == 1) + sb.AppendLine("\tDrive will eject cleaning cartridges on error"); + + if(page.UOE_F == 1) + sb.AppendLine("\tDrive will eject firmware cartridges on error"); + + if(page.UOE_D == 1) + sb.AppendLine("\tDrive will eject data cartridges on error"); + + return sb.ToString(); + } + #endregion IBM Mode Page 0x2F: Behaviour Configuration Mode page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/30_Apple.cs b/Aaru.Decoders/SCSI/Modes/30_Apple.cs new file mode 100644 index 000000000..e0199a2dc --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/30_Apple.cs @@ -0,0 +1,71 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 30_Apple.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes Apple MODE PAGE 30h: Apple OEM String. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Linq; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region Apple Mode Page 0x30: Apple OEM String + static readonly byte[] AppleOEMString = + { + 0x41, 0x50, 0x50, 0x4C, 0x45, 0x20, 0x43, 0x4F, 0x4D, 0x50, 0x55, 0x54, 0x45, 0x52, 0x2C, 0x20, 0x49, 0x4E, + 0x43, 0x2E + }; + + public static bool IsAppleModePage_30(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return false; + + if((pageResponse?[0] & 0x3F) != 0x30) + return false; + + if(pageResponse[1] + 2 != pageResponse.Length) + return false; + + if(pageResponse.Length != 30) + return false; + + byte[] str = new byte[20]; + Array.Copy(pageResponse, 10, str, 0, 20); + + return AppleOEMString.SequenceEqual(str); + } + #endregion Apple Mode Page 0x30: Apple OEM String + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/3B_HP.cs b/Aaru.Decoders/SCSI/Modes/3B_HP.cs new file mode 100644 index 000000000..c2129de57 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/3B_HP.cs @@ -0,0 +1,111 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 3B_HP.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes HP MODE PAGE 3Bh: Serial Number Override Mode page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Helpers; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region HP Mode Page 0x3B: Serial Number Override Mode page + public struct HP_ModePage_3B + { + /// Parameters can be saved + public bool PS; + public byte MSN; + public byte[] SerialNumber; + } + + public static HP_ModePage_3B? DecodeHPModePage_3B(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x3B) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length != 16) + return null; + + var decoded = new HP_ModePage_3B(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.MSN = (byte)(pageResponse[2] & 0x03); + decoded.SerialNumber = new byte[10]; + Array.Copy(pageResponse, 6, decoded.SerialNumber, 0, 10); + + return decoded; + } + + public static string PrettifyHPModePage_3B(byte[] pageResponse) => + PrettifyHPModePage_3B(DecodeHPModePage_3B(pageResponse)); + + public static string PrettifyHPModePage_3B(HP_ModePage_3B? modePage) + { + if(!modePage.HasValue) + return null; + + HP_ModePage_3B page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("HP Serial Number Override Mode Page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + switch(page.MSN) + { + case 1: + sb.AppendLine("\tSerial number is the manufacturer's default value"); + + break; + case 3: + sb.AppendLine("\tSerial number is not the manufacturer's default value"); + + break; + } + + sb.AppendFormat("\tSerial number: {0}", StringHandlers.CToString(page.SerialNumber)).AppendLine(); + + return sb.ToString(); + } + #endregion HP Mode Page 0x3B: Serial Number Override Mode page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/3C_HP.cs b/Aaru.Decoders/SCSI/Modes/3C_HP.cs new file mode 100644 index 000000000..ff00083d4 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/3C_HP.cs @@ -0,0 +1,152 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 3C_HP.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes HP MODE PAGE 3Ch: Device Time Mode page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Helpers; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region HP Mode Page 0x3C: Device Time Mode page + public struct HP_ModePage_3C + { + /// Parameters can be saved + public bool PS; + public bool LT; + public bool WT; + public bool PT; + public ushort CurrentPowerOn; + public uint PowerOnTime; + public bool UTC; + public bool NTP; + public uint WorldTime; + public byte LibraryHours; + public byte LibraryMinutes; + public byte LibrarySeconds; + public uint CumulativePowerOn; + } + + public static HP_ModePage_3C? DecodeHPModePage_3C(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x3C) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length != 36) + return null; + + var decoded = new HP_ModePage_3C(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.LT |= (pageResponse[2] & 0x04) == 0x04; + decoded.WT |= (pageResponse[2] & 0x02) == 0x02; + decoded.PT |= (pageResponse[2] & 0x01) == 0x01; + decoded.CurrentPowerOn = (ushort)((pageResponse[6] << 8) + pageResponse[7]); + + decoded.PowerOnTime = (uint)((pageResponse[8] << 24) + (pageResponse[9] << 16) + (pageResponse[10] << 8) + + pageResponse[11]); + + decoded.UTC |= (pageResponse[14] & 0x02) == 0x02; + decoded.NTP |= (pageResponse[14] & 0x01) == 0x01; + + decoded.WorldTime = (uint)((pageResponse[16] << 24) + (pageResponse[17] << 16) + (pageResponse[18] << 8) + + pageResponse[19]); + + decoded.LibraryHours = pageResponse[23]; + decoded.LibraryMinutes = pageResponse[24]; + decoded.LibrarySeconds = pageResponse[25]; + + decoded.CumulativePowerOn = (uint)((pageResponse[32] << 24) + (pageResponse[33] << 16) + + (pageResponse[34] << 8) + pageResponse[35]); + + return decoded; + } + + public static string PrettifyHPModePage_3C(byte[] pageResponse) => + PrettifyHPModePage_3C(DecodeHPModePage_3C(pageResponse)); + + public static string PrettifyHPModePage_3C(HP_ModePage_3C? modePage) + { + if(!modePage.HasValue) + return null; + + HP_ModePage_3C page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("HP Device Time Mode Page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.PT) + { + sb.AppendFormat("\tDrive has been powered up {0} times", page.CurrentPowerOn); + + sb.AppendFormat("\tDrive has been powered up since {0} this time", + TimeSpan.FromSeconds(page.PowerOnTime)).AppendLine(); + + sb.AppendFormat("\tDrive has been powered up a total of {0}", + TimeSpan.FromSeconds(page.CumulativePowerOn)).AppendLine(); + } + + if(page.WT) + { + sb.AppendFormat("\tDrive's date/time is: {0}", DateHandlers.UnixUnsignedToDateTime(page.WorldTime)). + AppendLine(); + + if(page.UTC) + sb.AppendLine("\tDrive's time is UTC"); + + if(page.NTP) + sb.AppendLine("\tDrive's time is synchronized with a NTP source"); + } + + if(page.LT) + sb.AppendFormat("\tLibrary time is {0}", + new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, page.LibraryHours, + page.LibraryMinutes, page.LibrarySeconds)).AppendLine(); + + return sb.ToString(); + } + #endregion HP Mode Page 0x3C: Device Time Mode page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/3D_HP.cs b/Aaru.Decoders/SCSI/Modes/3D_HP.cs new file mode 100644 index 000000000..788b9e2ce --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/3D_HP.cs @@ -0,0 +1,108 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 3D_HP.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes HP MODE PAGE 3Dh: Extended Reset Mode page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region HP Mode Page 0x3D: Extended Reset Mode page + public struct HP_ModePage_3D + { + /// Parameters can be saved + public bool PS; + public byte ResetBehaviour; + } + + public static HP_ModePage_3D? DecodeHPModePage_3D(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x3D) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length != 4) + return null; + + var decoded = new HP_ModePage_3D(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.ResetBehaviour = (byte)(pageResponse[2] & 0x03); + + return decoded; + } + + public static string PrettifyHPModePage_3D(byte[] pageResponse) => + PrettifyHPModePage_3D(DecodeHPModePage_3D(pageResponse)); + + public static string PrettifyHPModePage_3D(HP_ModePage_3D? modePage) + { + if(!modePage.HasValue) + return null; + + HP_ModePage_3D page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("HP Extended Reset Mode Page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + switch(page.ResetBehaviour) + { + case 0: + sb.AppendLine("\tNormal reset behaviour"); + + break; + case 1: + sb.AppendLine("\tDrive will flush and position itself on a LUN or target reset"); + + break; + case 2: + sb.AppendLine("\tDrive will maintain position on a LUN or target reset"); + + break; + } + + return sb.ToString(); + } + #endregion HP Mode Page 0x3D: Extended Reset Mode page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/3D_IBM.cs b/Aaru.Decoders/SCSI/Modes/3D_IBM.cs new file mode 100644 index 000000000..211f9118a --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/3D_IBM.cs @@ -0,0 +1,94 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 3D_IBM.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes IBM MODE PAGE 3D: Behaviour Configuration Mode page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region IBM Mode Page 0x3D: Behaviour Configuration Mode page + public struct IBM_ModePage_3D + { + /// Parameters can be saved + public bool PS; + public ushort NumberOfWraps; + } + + public static IBM_ModePage_3D? DecodeIBMModePage_3D(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x3D) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length != 5) + return null; + + var decoded = new IBM_ModePage_3D(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.NumberOfWraps = (ushort)((pageResponse[3] << 8) + pageResponse[4]); + + return decoded; + } + + public static string PrettifyIBMModePage_3D(byte[] pageResponse) => + PrettifyIBMModePage_3D(DecodeIBMModePage_3D(pageResponse)); + + public static string PrettifyIBMModePage_3D(IBM_ModePage_3D? modePage) + { + if(!modePage.HasValue) + return null; + + IBM_ModePage_3D page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("IBM LEOT Mode Page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + sb.AppendFormat("\t{0} wraps", page.NumberOfWraps).AppendLine(); + + return sb.ToString(); + } + #endregion IBM Mode Page 0x3D: Behaviour Configuration Mode page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/3E_Fujitsu.cs b/Aaru.Decoders/SCSI/Modes/3E_Fujitsu.cs new file mode 100644 index 000000000..3b93198bb --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/3E_Fujitsu.cs @@ -0,0 +1,149 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 3E_Fujitsu.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes Fujitsu MODE PAGE 3Eh: Verify Control page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.CommonTypes.Structs.Devices.SCSI; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static partial class Modes + { + #region Fujitsu Mode Page 0x3E: Verify Control page + public enum Fujitsu_VerifyModes : byte + { + /// Always verify after writing + Always = 0, + /// Never verify after writing + Never = 1, + /// Verify after writing depending on condition + Depends = 2, Reserved = 4 + } + + public struct Fujitsu_ModePage_3E + { + /// Parameters can be saved + public bool PS; + /// If set, AV data support mode is applied + public bool audioVisualMode; + /// If set the test write operation is restricted + public bool streamingMode; + public byte Reserved1; + /// Verify mode for WRITE commands + public Fujitsu_VerifyModes verifyMode; + public byte Reserved2; + /// Device type provided in response to INQUIRY + public PeripheralDeviceTypes devType; + public byte[] Reserved3; + } + + public static Fujitsu_ModePage_3E? DecodeFujitsuModePage_3E(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x3E) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length != 8) + return null; + + var decoded = new Fujitsu_ModePage_3E(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + + decoded.audioVisualMode |= (pageResponse[2] & 0x80) == 0x80; + decoded.streamingMode |= (pageResponse[2] & 0x40) == 0x40; + decoded.Reserved1 = (byte)((pageResponse[2] & 0x3C) >> 2); + decoded.verifyMode = (Fujitsu_VerifyModes)(pageResponse[2] & 0x03); + + decoded.Reserved2 = (byte)((pageResponse[3] & 0xE0) >> 5); + decoded.devType = (PeripheralDeviceTypes)(pageResponse[3] & 0x1F); + + decoded.Reserved3 = new byte[4]; + Array.Copy(pageResponse, 4, decoded.Reserved3, 0, 4); + + return decoded; + } + + public static string PrettifyFujitsuModePage_3E(byte[] pageResponse) => + PrettifyFujitsuModePage_3E(DecodeFujitsuModePage_3E(pageResponse)); + + public static string PrettifyFujitsuModePage_3E(Fujitsu_ModePage_3E? modePage) + { + if(!modePage.HasValue) + return null; + + Fujitsu_ModePage_3E page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("Fujitsu Verify Control Page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + if(page.audioVisualMode) + sb.AppendLine("\tAudio/Visual data support mode is applied"); + + if(page.streamingMode) + sb.AppendLine("\tTest write operation is restricted during read or write operations."); + + switch(page.verifyMode) + { + case Fujitsu_VerifyModes.Always: + sb.AppendLine("\tAlways apply the verify operation"); + + break; + case Fujitsu_VerifyModes.Never: + sb.AppendLine("\tNever apply the verify operation"); + + break; + case Fujitsu_VerifyModes.Depends: + sb.AppendLine("\tApply the verify operation depending on the condition"); + + break; + } + + sb.AppendFormat("\tThe device type that would be provided in the INQUIRY response is {0}", page.devType). + AppendLine(); + + return sb.ToString(); + } + #endregion Fujitsu Mode Page 0x3E: Verify Control page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/3E_HP.cs b/Aaru.Decoders/SCSI/Modes/3E_HP.cs new file mode 100644 index 000000000..3687f5b88 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/3E_HP.cs @@ -0,0 +1,100 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : 3E_HP.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes HP MODE PAGE 3Eh: CD-ROM Emulation/Disaster Recovery Mode page. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + #region HP Mode Page 0x3E: CD-ROM Emulation/Disaster Recovery Mode page + public struct HP_ModePage_3E + { + /// Parameters can be saved + public bool PS; + public bool NonAuto; + public bool CDmode; + } + + public static HP_ModePage_3E? DecodeHPModePage_3E(byte[] pageResponse) + { + if((pageResponse?[0] & 0x40) == 0x40) + return null; + + if((pageResponse?[0] & 0x3F) != 0x3E) + return null; + + if(pageResponse[1] + 2 != pageResponse.Length) + return null; + + if(pageResponse.Length != 4) + return null; + + var decoded = new HP_ModePage_3E(); + + decoded.PS |= (pageResponse[0] & 0x80) == 0x80; + decoded.NonAuto |= (pageResponse[2] & 0x02) == 0x02; + decoded.CDmode |= (pageResponse[2] & 0x01) == 0x01; + + return decoded; + } + + public static string PrettifyHPModePage_3E(byte[] pageResponse) => + PrettifyHPModePage_3E(DecodeHPModePage_3E(pageResponse)); + + public static string PrettifyHPModePage_3E(HP_ModePage_3E? modePage) + { + if(!modePage.HasValue) + return null; + + HP_ModePage_3E page = modePage.Value; + var sb = new StringBuilder(); + + sb.AppendLine("HP CD-ROM Emulation/Disaster Recovery Mode Page:"); + + if(page.PS) + sb.AppendLine("\tParameters can be saved"); + + sb.AppendLine(page.CDmode ? "\tDrive is emulating a CD-ROM drive" + : "\tDrive is not emulating a CD-ROM drive"); + + if(page.NonAuto) + sb.AppendLine("\tDrive will not exit emulation automatically"); + + return sb.ToString(); + } + #endregion HP Mode Page 0x3E: CD-ROM Emulation/Disaster Recovery Mode page + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/Headers.cs b/Aaru.Decoders/SCSI/Modes/Headers.cs new file mode 100644 index 000000000..32e28ea68 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/Headers.cs @@ -0,0 +1,2129 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Headers.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Prettifies SCSI MODE headers. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.CommonTypes.Structs.Devices.SCSI; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + public static string GetMediumTypeDescription(MediumTypes type) + { + switch(type) + { + case MediumTypes.ECMA54: + return + "ECMA-54: 200 mm Flexible Disk Cartridge using Two-Frequency Recording at 13262 ftprad on One Side"; + case MediumTypes.ECMA59: + return + "ECMA-59 & ANSI X3.121-1984: 200 mm Flexible Disk Cartridge using Two-Frequency Recording at 13262 ftprad on Both Sides"; + case MediumTypes.ECMA69: + return "ECMA-69: 200 mm Flexible Disk Cartridge using MFM Recording at 13262 ftprad on Both Sides"; + case MediumTypes.ECMA66: + return + "ECMA-66: 130 mm Flexible Disk Cartridge using Two-Frequency Recording at 7958 ftprad on One Side"; + case MediumTypes.ECMA70: + return + "ECMA-70 & ANSI X3.125-1985: 130 mm Flexible Disk Cartridge using MFM Recording at 7958 ftprad on Both Sides; 1,9 Tracks per mm"; + case MediumTypes.ECMA78: + return + "ECMA-78 & ANSI X3.126-1986: 130 mm Flexible Disk Cartridge using MFM Recording at 7958 ftprad on Both Sides; 3,8 Tracks per mm"; + case MediumTypes.ECMA99: + return + "ECMA-99 & ISO 8630-1985: 130 mm Flexible Disk Cartridge using MFM Recording at 13262 ftprad on Both Sides; 3,8 Tracks per mm"; + case MediumTypes.ECMA100: + return + "ECMA-100 & ANSI X3.137: 90 mm Flexible Disk Cartridge using MFM Recording at 7859 ftprad on Both Sides; 5,3 Tracks per mm"; + + // Most probably they will never appear, but magneto-opticals use these codes + /* + case MediumTypes.Unspecified_SS: + return "Unspecified single sided flexible disk"; + case MediumTypes.Unspecified_DS: + return "Unspecified double sided flexible disk"; + */ + case MediumTypes.X3_73: return "ANSI X3.73-1980: 200 mm, 6631 ftprad, 1,9 Tracks per mm, 1 side"; + case MediumTypes.X3_73_DS: return "ANSI X3.73-1980: 200 mm, 6631 ftprad, 1,9 Tracks per mm, 2 sides"; + case MediumTypes.X3_82: return "ANSI X3.80-1980: 130 mm, 3979 ftprad, 1,9 Tracks per mm, 1 side"; + case MediumTypes.Type3Floppy: + return "3.5-inch, 135 tpi, 12362 bits/radian, double-sided MFM (aka 1.25Mb)"; + case MediumTypes.HDFloppy: return "3.5-inch, 135 tpi, 15916 bits/radian, double-sided MFM (aka 1.44Mb)"; + case MediumTypes.ReadOnly: return "a Read-only optical"; + case MediumTypes.WORM: return "a Write-once Read-many optical"; + case MediumTypes.Erasable: return "a Erasable optical"; + case MediumTypes.RO_WORM: return "a combination of read-only and write-once optical"; + + // These magneto-opticals were never manufactured + /* + case MediumTypes.RO_RW: + return "a combination of read-only and erasable optical"; + break; + case MediumTypes.WORM_RW: + return "a combination of write-once and erasable optical"; + */ + case MediumTypes.DOW: return "a direct-overwrite optical"; + case MediumTypes.HiMD: return "a Sony Hi-MD disc"; + default: return $"Unknown medium type 0x{(byte)type:X2}"; + } + } + + public static string PrettifyModeHeader(ModeHeader? header, PeripheralDeviceTypes deviceType) + { + if(!header.HasValue) + return null; + + var sb = new StringBuilder(); + + sb.AppendLine("SCSI Mode Sense Header:"); + + switch(deviceType) + { + #region Direct access device mode header + case PeripheralDeviceTypes.DirectAccess: + { + if(header.Value.MediumType != MediumTypes.Default) + sb.AppendFormat("\tMedium is {0}", GetMediumTypeDescription(header.Value.MediumType)). + AppendLine(); + + if(header.Value.WriteProtected) + sb.AppendLine("\tMedium is write protected"); + + if(header.Value.DPOFUA) + sb.AppendLine("\tDrive supports DPO and FUA bits"); + + if(header.Value.BlockDescriptors != null) + foreach(BlockDescriptor descriptor in header.Value.BlockDescriptors) + { + string density = ""; + + switch(descriptor.Density) + { + case DensityType.Default: break; + case DensityType.Flux7958: + density = "7958 flux transitions per radian"; + + break; + case DensityType.Flux13262: + density = "13262 flux transitions per radian"; + + break; + case DensityType.Flux15916: + density = "15916 flux transitions per radian"; + + break; + default: + density = $"with unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + + if(density != "") + if(descriptor.Blocks == 0) + sb.AppendFormat("\tAll remaining blocks have {0} and are {1} bytes each", density, + descriptor.BlockLength).AppendLine(); + else + sb.AppendFormat("\t{0} blocks have {1} and are {2} bytes each", descriptor.Blocks, + density, descriptor.BlockLength).AppendLine(); + else if(descriptor.Blocks == 0) + sb.AppendFormat("\tAll remaining blocks are {0} bytes each", descriptor.BlockLength). + AppendLine(); + else + sb.AppendFormat("\t{0} blocks are {1} bytes each", descriptor.Blocks, + descriptor.BlockLength).AppendLine(); + } + + break; + } + #endregion Direct access device mode header + + #region Sequential access device mode header + case PeripheralDeviceTypes.SequentialAccess: + { + switch(header.Value.BufferedMode) + { + case 0: + sb.AppendLine("\tDevice writes directly to media"); + + break; + case 1: + sb.AppendLine("\tDevice uses a write cache"); + + break; + case 2: + sb.AppendLine("\tDevice uses a write cache but doesn't return until cache is flushed"); + + break; + default: + sb.AppendFormat("\tUnknown buffered mode code 0x{0:X2}", header.Value.BufferedMode). + AppendLine(); + + break; + } + + if(header.Value.Speed == 0) + sb.AppendLine("\tDevice uses default speed"); + else + sb.AppendFormat("\tDevice uses speed {0}", header.Value.Speed).AppendLine(); + + if(header.Value.WriteProtected) + sb.AppendLine("\tMedium is write protected"); + + string medium; + + switch(header.Value.MediumType) + { + case MediumTypes.Default: + medium = "undefined"; + + break; + case MediumTypes.Tape12: + medium = "6,3 mm tape with 12 tracks at 394 ftpmm or DC-9250"; + + break; + case MediumTypes.Tape24: + medium = "6,3 mm tape with 24 tracks at 394 ftpmm or MLR1-26GBSL"; + + break; + case MediumTypes.LTOWORM: + medium = "LTO Ultrium WORM or cleaning cartridge"; + + break; + case MediumTypes.LTO: + medium = "LTO Ultrium"; + + break; + case MediumTypes.LTO2: + medium = "LTO Ultrium-2"; + + break; + case MediumTypes.DC2900SL: + medium = "DC-2900SL"; + + break; + case MediumTypes.MLR1: + medium = "MLR1-26GB or DDS-3"; + + break; + case MediumTypes.DC9200: + medium = "DC-9200 or DDS-4"; + + break; + case MediumTypes.DAT72: + medium = "DAT-72"; + + break; + case MediumTypes.LTO3: + medium = "LTO Ultrium-3"; + + break; + case MediumTypes.LTO3WORM: + medium = "LTO Ultrium-3 WORM"; + + break; + case MediumTypes.DDSCleaning: + medium = "DDS cleaning cartridge"; + + break; + case MediumTypes.SLR32: + medium = "SLR-32"; + + break; + case MediumTypes.SLRtape50: + medium = "SLRtape-50"; + + break; + case MediumTypes.LTO4: + medium = "LTO Ultrium-4"; + + break; + case MediumTypes.LTO4WORM: + medium = "LTO Ultrium-4 WORM"; + + break; + case MediumTypes.SLRtape50SL: + medium = "SLRtape-50 SL"; + + break; + case MediumTypes.SLR32SL: + medium = "SLR-32SL"; + + break; + case MediumTypes.SLR5: + medium = "SLR-5"; + + break; + case MediumTypes.SLR5SL: + medium = "SLR-5SL"; + + break; + case MediumTypes.LTO5: + medium = "LTO Ultrium-5"; + + break; + case MediumTypes.LTO5WORM: + medium = "LTO Ultrium-5 WORM"; + + break; + case MediumTypes.SLRtape7: + medium = "SLRtape-7"; + + break; + case MediumTypes.SLRtape7SL: + medium = "SLRtape-7 SL"; + + break; + case MediumTypes.SLRtape24: + medium = "SLRtape-24"; + + break; + case MediumTypes.SLRtape24SL: + medium = "SLRtape-24 SL"; + + break; + case MediumTypes.LTO6: + medium = "LTO Ultrium-6"; + + break; + case MediumTypes.LTO6WORM: + medium = "LTO Ultrium-6 WORM"; + + break; + case MediumTypes.SLRtape140: + medium = "SLRtape-140"; + + break; + case MediumTypes.SLRtape40: + medium = "SLRtape-40"; + + break; + case MediumTypes.SLRtape60: + medium = "SLRtape-60 or SLRtape-75"; + + break; + case MediumTypes.SLRtape100: + medium = "SLRtape-100"; + + break; + case MediumTypes.SLR40_60_100: + medium = "SLR-40, SLR-60 or SLR-100"; + + break; + case MediumTypes.LTO7: + medium = "LTO Ultrium-7"; + + break; + case MediumTypes.LTO7WORM: + medium = "LTO Ultrium-7 WORM"; + + break; + case MediumTypes.LTOCD: + medium = "LTO Ultrium"; + + break; + case MediumTypes.Exatape15m: + medium = "Exatape 15m, IBM MagStar or VXA"; + + break; + case MediumTypes.CT1: + medium = "CompactTape I, Exatape 28m, CompactTape II, VXA-2 or VXA-3"; + + break; + case MediumTypes.Exatape54m: + medium = "Exatape 54m or DLTtape III"; + + break; + case MediumTypes.Exatape80m: + medium = "Exatape 80m or DLTtape IIIxt"; + + break; + case MediumTypes.Exatape106m: + medium = "Exatape 106m, DLTtape IV or Travan 5"; + + break; + case MediumTypes.Exatape106mXL: + medium = "Exatape 160m XL or Super DLTtape I"; + + break; + case MediumTypes.SDLT2: + medium = "Super DLTtape II"; + + break; + case MediumTypes.VStapeI: + medium = "VStape I"; + + break; + case MediumTypes.DLTtapeS4: + medium = "DLTtape S4"; + + break; + case MediumTypes.Travan7: + medium = "Travan 7"; + + break; + case MediumTypes.Exatape22m: + medium = "Exatape 22m"; + + break; + case MediumTypes.Exatape40m: + medium = "Exatape 40m"; + + break; + case MediumTypes.Exatape76m: + medium = "Exatape 76m"; + + break; + case MediumTypes.Exatape112m: + medium = "Exatape 112m"; + + break; + case MediumTypes.Exatape22mAME: + medium = "Exatape 22m AME"; + + break; + case MediumTypes.Exatape170m: + medium = "Exatape 170m"; + + break; + case MediumTypes.Exatape125m: + medium = "Exatape 125m"; + + break; + case MediumTypes.Exatape45m: + medium = "Exatape 45m"; + + break; + case MediumTypes.Exatape225m: + medium = "Exatape 225m"; + + break; + case MediumTypes.Exatape150m: + medium = "Exatape 150m"; + + break; + case MediumTypes.Exatape75m: + medium = "Exatape 75m"; + + break; + default: + medium = $"unknown medium type 0x{(byte)header.Value.MediumType:X2}"; + + break; + } + + sb.AppendFormat("\tMedium is {0}", medium).AppendLine(); + + if(header.Value.BlockDescriptors != null) + foreach(BlockDescriptor descriptor in header.Value.BlockDescriptors) + { + string density = ""; + + switch(header.Value.MediumType) + { + case MediumTypes.Default: + { + switch(descriptor.Density) + { + case DensityType.Default: break; + case DensityType.ECMA62: + density = + "ECMA-62 & ANSI X3.22-1983: 12,7 mm 9-Track Magnetic Tape, 32 ftpmm, NRZI, 32 cpmm"; + + break; + case DensityType.ECMA62_Phase: + density = + "ECMA-62 & ANSI X3.39-1986: 12,7 mm 9-Track Magnetic Tape, 126 ftpmm, Phase Encoding, 63 cpmm"; + + break; + case DensityType.ECMA62_GCR: + density = + "ECMA-62 & ANSI X3.54-1986: 12,7 mm 9-Track Magnetic Tape, 356 ftpmm, NRZI, 245 cpmm GCR"; + + break; + case DensityType.ECMA79: + density = + "ECMA-79 & ANSI X3.116-1986: 6,30 mm Magnetic Tape Cartridge, 252 ftpmm, MFM"; + + break; + case DensityType.IBM3480: + density = + "Draft ECMA & ANSI X3B5/87-099: 12,7 mm 18-Track Magnetic Tape Cartridge, 1944 ftpmm, IFM, GCR (IBM 3480, 3490, 3490E)"; + + break; + case DensityType.ECMA46: + density = + "ECMA-46 & ANSI X3.56-1986: 6,30 mm Magnetic Tape Cartridge, Phase Encoding, 63 bpmm"; + + break; + case DensityType.ECMA98: + density = "ECMA-98: 6,30 mm Magnetic Tape Cartridge, NRZI, 394 ftpmm"; + + break; + case DensityType.X3_136: + density = + "ANXI X3.136-1986: 6,3 mm 4 or 9-Track Magnetic Tape Cartridge, 315 bpmm, GCR (QIC-24)"; + + break; + case DensityType.X3_157: + density = + "ANXI X3.157-1987: 12,7 mm 9-Track Magnetic Tape, 126 bpmm, Phase Encoding"; + + break; + case DensityType.X3_158: + density = + "ANXI X3.158-1987: 3,81 mm 4-Track Magnetic Tape Cassette, 315 bpmm, GCR"; + + break; + case DensityType.X3B5_86: + density = + "ANXI X3B5/86-199: 12,7 mm 22-Track Magnetic Tape Cartridge, 262 bpmm, MFM"; + + break; + case DensityType.HiTC1: + density = "HI-TC1: 12,7 mm 24-Track Magnetic Tape Cartridge, 500 bpmm, GCR"; + + break; + case DensityType.HiTC2: + density = "HI-TC2: 12,7 mm 24-Track Magnetic Tape Cartridge, 999 bpmm, GCR"; + + break; + case DensityType.QIC120: + density = "QIC-120: 6,3 mm 15-Track Magnetic Tape Cartridge, 394 bpmm, GCR"; + + break; + case DensityType.QIC150: + density = "QIC-150: 6,3 mm 18-Track Magnetic Tape Cartridge, 394 bpmm, GCR"; + + break; + case DensityType.QIC320: + density = "QIC-320: 6,3 mm 26-Track Magnetic Tape Cartridge, 630 bpmm, GCR"; + + break; + case DensityType.QIC1350: + density = + "QIC-1350: 6,3 mm 30-Track Magnetic Tape Cartridge, 2034 bpmm, RLL"; + + break; + case DensityType.X3B5_88: + density = + "ANXI X3B5/88-185A: 3,81 mm Magnetic Tape Cassette, 2400 bpmm, DDS"; + + break; + case DensityType.X3_202: + density = "ANXI X3.202-1991: 8 mm Magnetic Tape Cassette, 1703 bpmm, RLL"; + + break; + case DensityType.ECMA_TC17: + density = "ECMA TC17: 8 mm Magnetic Tape Cassette, 1789 bpmm, RLL"; + + break; + case DensityType.X3_193: + density = + "ANXI X3.193-1990: 12,7 mm 48-Track Magnetic Tape Cartridge, 394 bpmm, MFM"; + + break; + case DensityType.X3B5_91: + density = + "ANXI X3B5/97-174: 12,7 mm 48-Track Magnetic Tape Cartridge, 1673 bpmm, MFM"; + + break; + case DensityType.QIC11: + density = "QIC-11"; + + break; + case DensityType.IBM3490E: + density = "IBM 3490E"; + + break; + case DensityType.LTO1: + //case DensityType.SAIT1: + density = "LTO Ultrium or Super AIT-1"; + + break; + case DensityType.LTO2Old: + density = "LTO Ultrium-2"; + + break; + case DensityType.LTO2: + //case DensityType.T9840: + density = "LTO Ultrium-2 or T9840"; + + break; + case DensityType.T9940: + density = "T9940"; + + break; + case DensityType.LTO3: + //case DensityType.T9940: + density = "LTO Ultrium-3 or T9940"; + + break; + case DensityType.T9840C: + density = "T9840C"; + + break; + case DensityType.LTO4: + //case DensityType.T9840D: + density = "LTO Ultrium-4 or T9840D"; + + break; + case DensityType.T10000A: + density = "T10000A"; + + break; + case DensityType.T10000B: + density = "T10000B"; + + break; + case DensityType.T10000C: + density = "T10000C"; + + break; + case DensityType.T10000D: + density = "T10000D"; + + break; + case DensityType.AIT1: + density = "AIT-1"; + + break; + case DensityType.AIT2: + density = "AIT-2"; + + break; + case DensityType.AIT3: + density = "AIT-3"; + + break; + case DensityType.DDS2: + density = "DDS-2"; + + break; + case DensityType.DDS3: + density = "DDS-3"; + + break; + case DensityType.DDS4: + density = "DDS-4"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.LTOWORM: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "LTO Ultrium cleaning cartridge"; + + break; + case DensityType.LTO3: + density = "LTO Ultrium-3 WORM"; + + break; + case DensityType.LTO4: + density = "LTO Ultrium-4 WORM"; + + break; + case DensityType.LTO5: + density = "LTO Ultrium-5 WORM"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.LTO: + { + switch(descriptor.Density) + { + case DensityType.LTO1: + density = "LTO Ultrium"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.LTO2: + { + switch(descriptor.Density) + { + case DensityType.LTO2: + density = "LTO Ultrium-2"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.DDS3: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "MLR1-26GB"; + + break; + case DensityType.DDS3: + density = "DDS-3"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.DDS4: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "DC-9200"; + + break; + case DensityType.DDS4: + density = "DDS-4"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.DAT72: + { + switch(descriptor.Density) + { + case DensityType.DAT72: + density = "DAT-72"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.LTO3: + case MediumTypes.LTO3WORM: + { + switch(descriptor.Density) + { + case DensityType.LTO3: + density = "LTO Ultrium-3"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.DDSCleaning: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "DDS cleaning cartridge"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.LTO4: + case MediumTypes.LTO4WORM: + { + switch(descriptor.Density) + { + case DensityType.LTO4: + density = "LTO Ultrium-4"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.LTO5: + case MediumTypes.LTO5WORM: + { + switch(descriptor.Density) + { + case DensityType.LTO5: + density = "LTO Ultrium-5"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.LTO6: + case MediumTypes.LTO6WORM: + { + switch(descriptor.Density) + { + case DensityType.LTO6: + density = "LTO Ultrium-6"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.LTO7: + case MediumTypes.LTO7WORM: + { + switch(descriptor.Density) + { + case DensityType.LTO7: + density = "LTO Ultrium-7"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.LTOCD: + { + switch(descriptor.Density) + { + case DensityType.LTO2: + density = "LTO Ultrium-2 in CD emulation mode"; + + break; + case DensityType.LTO3: + density = "LTO Ultrium-3 in CD emulation mode"; + + break; + case DensityType.LTO4: + density = "LTO Ultrium-4 in CD emulation mode"; + + break; + case DensityType.LTO5: + density = "LTO Ultrium-5 in CD emulation mode"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.Exatape15m: + { + switch(descriptor.Density) + { + case DensityType.Ex8200: + density = "EXB-8200"; + + break; + case DensityType.Ex8200c: + density = "EXB-8200 compressed"; + + break; + case DensityType.Ex8500: + density = "EXB-8500"; + + break; + case DensityType.Ex8500c: + density = "EXB-8500 compressed"; + + break; + case DensityType.Mammoth: + density = "Mammoth"; + + break; + case DensityType.IBM3590: + density = "IBM 3590"; + + break; + case DensityType.IBM3590E: + density = "IBM 3590E"; + + break; + case DensityType.VXA1: + density = "VXA-1"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.Exatape28m: + { + switch(descriptor.Density) + { + case DensityType.Ex8200: + density = "EXB-8200"; + + break; + case DensityType.Ex8200c: + density = "EXB-8200 compressed"; + + break; + case DensityType.Ex8500: + density = "EXB-8500"; + + break; + case DensityType.Ex8500c: + density = "EXB-8500 compressed"; + + break; + case DensityType.Mammoth: + density = "Mammoth"; + + break; + case DensityType.CT1: + density = "CompactTape I"; + + break; + case DensityType.CT2: + density = "CompactTape II"; + + break; + case DensityType.IBM3590: + density = "IBM 3590 extended"; + + break; + case DensityType.IBM3590E: + density = "IBM 3590E extended"; + + break; + case DensityType.VXA2: + density = "VXA-2"; + + break; + case DensityType.VXA3: + density = "VXA-3"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.Exatape54m: + { + switch(descriptor.Density) + { + case DensityType.Ex8200: + density = "EXB-8200"; + + break; + case DensityType.Ex8200c: + density = "EXB-8200 compressed"; + + break; + case DensityType.Ex8500: + density = "EXB-8500"; + + break; + case DensityType.Ex8500c: + density = "EXB-8500 compressed"; + + break; + case DensityType.Mammoth: + density = "Mammoth"; + + break; + case DensityType.DLT3_42k: + density = "DLTtape III at 42500 bpi"; + + break; + case DensityType.DLT3_56t: + density = "DLTtape III with 56 tracks"; + + break; + case DensityType.DLT3_62k: + case DensityType.DLT3_62kAlt: + density = "DLTtape III at 62500 bpi"; + + break; + case DensityType.DLT3c: + density = "DLTtape III compressed"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.Exatape80m: + { + switch(descriptor.Density) + { + case DensityType.Ex8200: + density = "EXB-8200"; + + break; + case DensityType.Ex8200c: + density = "EXB-8200 compressed"; + + break; + case DensityType.Ex8500: + density = "EXB-8500"; + + break; + case DensityType.Ex8500c: + density = "EXB-8500 compressed"; + + break; + case DensityType.Mammoth: + density = "Mammoth"; + + break; + case DensityType.DLT3_62k: + case DensityType.DLT3_62kAlt: + density = "DLTtape IIIxt"; + + break; + case DensityType.DLT3c: + density = "DLTtape IIIxt compressed"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.Exatape106m: + { + switch(descriptor.Density) + { + case DensityType.Ex8200: + density = "EXB-8200"; + + break; + case DensityType.Ex8200c: + density = "EXB-8200 compressed"; + + break; + case DensityType.Ex8500: + density = "EXB-8500"; + + break; + case DensityType.Ex8500c: + density = "EXB-8500 compressed"; + + break; + case DensityType.Mammoth: + density = "Mammoth"; + + break; + case DensityType.DLT4: + case DensityType.DLT4Alt: + density = "DLTtape IV"; + + break; + case DensityType.DLT4_123k: + case DensityType.DLT4_123kAlt: + density = "DLTtape IV at 123090 bpi"; + + break; + case DensityType.DLT4_98k: + density = "DLTtape IV at 98250 bpi"; + + break; + case DensityType.Travan5: + density = "Travan 5"; + + break; + case DensityType.DLT4c: + density = "DLTtape IV compressed"; + + break; + case DensityType.DLT4_85k: + density = "DLTtape IV at 85937 bpi"; + + break; + case DensityType.DLT4c_85k: + density = "DLTtape IV at 85937 bpi compressed"; + + break; + case DensityType.DLT4c_123k: + density = "DLTtape IV at 123090 bpi compressed"; + + break; + case DensityType.DLT4c_98k: + density = "DLTtape IV at 98250 bpi compressed"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.Exatape106mXL: + { + switch(descriptor.Density) + { + case DensityType.Ex8200: + density = "EXB-8200"; + + break; + case DensityType.Ex8200c: + density = "EXB-8200 compressed"; + + break; + case DensityType.Ex8500: + density = "EXB-8500"; + + break; + case DensityType.Ex8500c: + density = "EXB-8500 compressed"; + + break; + case DensityType.Mammoth: + density = "Mammoth"; + + break; + case DensityType.SDLT1_133k: + case DensityType.SDLT1_133kAlt: + density = "Super DLTtape I at 133000 bpi"; + + break; + case DensityType.SDLT1: + //case DensityType.SDLT1Alt: + density = "Super DLTtape I"; + + break; + case DensityType.SDLT1c: + density = "Super DLTtape I compressed"; + + break; + /*case DensityType.SDLT1_133kAlt: + density = "Super DLTtape I at 133000 bpi compressed"; + break;*/ + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.SDLT2: + { + switch(descriptor.Density) + { + case DensityType.SDLT2: + density = "Super DLTtape II"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.VStapeI: + { + switch(descriptor.Density) + { + case DensityType.VStape1: + case DensityType.VStape1Alt: + density = "VStape I"; + + break; + case DensityType.VStape1c: + density = "VStape I compressed"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.DLTtapeS4: + { + switch(descriptor.Density) + { + case DensityType.DLTS4: + density = "DLTtape S4"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.Exatape22m: + { + switch(descriptor.Density) + { + case DensityType.Ex8200: + density = "EXB-8200"; + + break; + case DensityType.Ex8200c: + density = "EXB-8200 compressed"; + + break; + case DensityType.Ex8500: + density = "EXB-8500"; + + break; + case DensityType.Ex8500c: + density = "EXB-8500 compressed"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.Exatape40m: + { + switch(descriptor.Density) + { + case DensityType.Ex8200: + density = "EXB-8200"; + + break; + case DensityType.Ex8200c: + density = "EXB-8200 compressed"; + + break; + case DensityType.Ex8500: + density = "EXB-8500"; + + break; + case DensityType.Ex8500c: + density = "EXB-8500 compressed"; + + break; + case DensityType.Mammoth: + density = "Mammoth"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.Exatape76m: + { + switch(descriptor.Density) + { + case DensityType.Ex8200: + density = "EXB-8200"; + + break; + case DensityType.Ex8200c: + density = "EXB-8200 compressed"; + + break; + case DensityType.Ex8500: + density = "EXB-8500"; + + break; + case DensityType.Ex8500c: + density = "EXB-8500 compressed"; + + break; + case DensityType.Mammoth: + density = "Mammoth"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.Exatape112m: + { + switch(descriptor.Density) + { + case DensityType.Ex8200: + density = "EXB-8200"; + + break; + case DensityType.Ex8200c: + density = "EXB-8200 compressed"; + + break; + case DensityType.Ex8500: + density = "EXB-8500"; + + break; + case DensityType.Ex8500c: + density = "EXB-8500 compressed"; + + break; + case DensityType.Mammoth: + density = "Mammoth"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.Exatape22mAME: + case MediumTypes.Exatape170m: + case MediumTypes.Exatape125m: + case MediumTypes.Exatape45m: + case MediumTypes.Exatape225m: + case MediumTypes.Exatape150m: + case MediumTypes.Exatape75m: + { + switch(descriptor.Density) + { + case DensityType.Mammoth: + density = "Mammoth"; + + break; + case DensityType.Mammoth2: + density = "Mammoth-2"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.DC2900SL: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "DC-2900SL"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.DC9250: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "DC-9250"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.SLR32: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "SLR-32"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.MLR1SL: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "MRL1-26GBSL"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.SLRtape50: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "SLRtape-50"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.SLRtape50SL: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "SLRtape-50 SL"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.SLR32SL: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "SLR-32 SL"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.SLR5: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "SLR-5"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.SLR5SL: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "SLR-5 SL"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.SLRtape7: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "SLRtape-7"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.SLRtape7SL: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "SLRtape-7 SL"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.SLRtape24: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "SLRtape-24"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.SLRtape24SL: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "SLRtape-24 SL"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.SLRtape140: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "SLRtape-140"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.SLRtape40: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "SLRtape-40"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.SLRtape60: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "SLRtape-60 or SLRtape-75"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.SLRtape100: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "SLRtape-100"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + case MediumTypes.SLR40_60_100: + { + switch(descriptor.Density) + { + case DensityType.Default: + density = "SLR40, SLR60 or SLR100"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + } + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + + if(density != "") + if(descriptor.Blocks == 0) + if(descriptor.BlockLength == 0) + sb. + AppendFormat("\tAll remaining blocks conform to {0} and have a variable length", + density).AppendLine(); + else + sb.AppendFormat("\tAll remaining blocks conform to {0} and are {1} bytes each", + density, descriptor.BlockLength).AppendLine(); + else if(descriptor.BlockLength == 0) + sb.AppendFormat("\t{0} blocks conform to {1} and have a variable length", + descriptor.Blocks, density).AppendLine(); + else + sb.AppendFormat("\t{0} blocks conform to {1} and are {2} bytes each", + descriptor.Blocks, density, descriptor.BlockLength).AppendLine(); + else if(descriptor.Blocks == 0) + if(descriptor.BlockLength == 0) + sb.AppendFormat("\tAll remaining blocks have a variable length").AppendLine(); + else + sb.AppendFormat("\tAll remaining blocks are {0} bytes each", + descriptor.BlockLength).AppendLine(); + else if(descriptor.BlockLength == 0) + sb.AppendFormat("\t{0} blocks have a variable length", descriptor.Blocks).AppendLine(); + else + sb.AppendFormat("\t{0} blocks are {1} bytes each", descriptor.Blocks, + descriptor.BlockLength).AppendLine(); + } + + break; + } + #endregion Sequential access device mode header + + #region Printer device mode header + case PeripheralDeviceTypes.PrinterDevice: + { + switch(header.Value.BufferedMode) + { + case 0: + sb.AppendLine("\tDevice prints directly"); + + break; + case 1: + sb.AppendLine("\tDevice uses a print cache"); + + break; + default: + sb.AppendFormat("\tUnknown buffered mode code 0x{0:X2}", header.Value.BufferedMode). + AppendLine(); + + break; + } + + break; + } + #endregion Printer device mode header + + #region Optical device mode header + case PeripheralDeviceTypes.OpticalDevice: + { + if(header.Value.MediumType != MediumTypes.Default) + { + sb.Append("\tMedium is "); + + switch(header.Value.MediumType) + { + case MediumTypes.ReadOnly: + sb.AppendLine("a Read-only optical"); + + break; + case MediumTypes.WORM: + sb.AppendLine("a Write-once Read-many optical"); + + break; + case MediumTypes.Erasable: + sb.AppendLine("a Erasable optical"); + + break; + case MediumTypes.RO_WORM: + sb.AppendLine("a combination of read-only and write-once optical"); + + break; + case MediumTypes.RO_RW: + sb.AppendLine("a combination of read-only and erasable optical"); + + break; + case MediumTypes.WORM_RW: + sb.AppendLine("a combination of write-once and erasable optical"); + + break; + case MediumTypes.DOW: + sb.AppendLine("a direct-overwrite optical"); + + break; + default: + sb.AppendFormat("an unknown medium type 0x{0:X2}", (byte)header.Value.MediumType). + AppendLine(); + + break; + } + } + + if(header.Value.WriteProtected) + sb.AppendLine("\tMedium is write protected"); + + if(header.Value.EBC) + sb.AppendLine("\tBlank checking during write is enabled"); + + if(header.Value.DPOFUA) + sb.AppendLine("\tDrive supports DPO and FUA bits"); + + if(header.Value.BlockDescriptors != null) + foreach(BlockDescriptor descriptor in header.Value.BlockDescriptors) + { + string density = ""; + + switch(descriptor.Density) + { + case DensityType.Default: break; + case DensityType.ISO10090: + density = + "ISO/IEC 10090: 86 mm Read/Write single-sided optical disc with 12500 tracks"; + + break; + case DensityType.D581: + density = "89 mm Read/Write double-sided optical disc with 12500 tracks"; + + break; + case DensityType.X3_212: + density = + "ANSI X3.212: 130 mm Read/Write double-sided optical disc with 18750 tracks"; + + break; + case DensityType.X3_191: + density = + "ANSI X3.191: 130 mm Write-Once double-sided optical disc with 30000 tracks"; + + break; + case DensityType.X3_214: + density = + "ANSI X3.214: 130 mm Write-Once double-sided optical disc with 20000 tracks"; + + break; + case DensityType.X3_211: + density = + "ANSI X3.211: 130 mm Write-Once double-sided optical disc with 18750 tracks"; + + break; + case DensityType.D407: + density = "200 mm optical disc"; + + break; + case DensityType.ISO13614: + density = "ISO/IEC 13614: 300 mm double-sided optical disc"; + + break; + case DensityType.X3_200: + density = "ANSI X3.200: 356 mm double-sided optical disc with 56350 tracks"; + + break; + default: + density = $"unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + + if(density != "") + if(descriptor.Blocks == 0) + if(descriptor.BlockLength == 0) + sb.AppendFormat("\tAll remaining blocks are {0} and have a variable length", + density).AppendLine(); + else + sb.AppendFormat("\tAll remaining blocks are {0} and are {1} bytes each", + density, descriptor.BlockLength).AppendLine(); + else if(descriptor.BlockLength == 0) + sb.AppendFormat("\t{0} blocks are {1} and have a variable length", + descriptor.Blocks, density).AppendLine(); + else + sb.AppendFormat("\t{0} blocks are {1} and are {2} bytes each", descriptor.Blocks, + density, descriptor.BlockLength).AppendLine(); + else if(descriptor.Blocks == 0) + if(descriptor.BlockLength == 0) + sb.AppendFormat("\tAll remaining blocks have a variable length").AppendLine(); + else + sb.AppendFormat("\tAll remaining blocks are {0} bytes each", + descriptor.BlockLength).AppendLine(); + else if(descriptor.BlockLength == 0) + sb.AppendFormat("\t{0} blocks have a variable length", descriptor.Blocks).AppendLine(); + else + sb.AppendFormat("\t{0} blocks are {1} bytes each", descriptor.Blocks, + descriptor.BlockLength).AppendLine(); + } + + break; + } + #endregion Optical device mode header + + #region Multimedia device mode header + case PeripheralDeviceTypes.MultiMediaDevice: + { + sb.Append("\tMedium is "); + + switch(header.Value.MediumType) + { + case MediumTypes.CDROM: + sb.AppendLine("120 mm CD-ROM"); + + break; + case MediumTypes.CDDA: + sb.AppendLine("120 mm Compact Disc Digital Audio"); + + break; + case MediumTypes.MixedCD: + sb.AppendLine("120 mm Compact Disc with data and audio"); + + break; + case MediumTypes.CDROM_80: + sb.AppendLine("80 mm CD-ROM"); + + break; + case MediumTypes.CDDA_80: + sb.AppendLine("80 mm Compact Disc Digital Audio"); + + break; + case MediumTypes.MixedCD_80: + sb.AppendLine("80 mm Compact Disc with data and audio"); + + break; + case MediumTypes.Unknown_CD: + sb.AppendLine("Unknown medium type"); + + break; + case MediumTypes.HybridCD: + sb.AppendLine("120 mm Hybrid disc (Photo CD)"); + + break; + case MediumTypes.Unknown_CDR: + sb.AppendLine("Unknown size CD-R"); + + break; + case MediumTypes.CDR: + sb.AppendLine("120 mm CD-R with data only"); + + break; + case MediumTypes.CDR_DA: + sb.AppendLine("120 mm CD-R with audio only"); + + break; + case MediumTypes.CDR_Mixed: + sb.AppendLine("120 mm CD-R with data and audio"); + + break; + case MediumTypes.HybridCDR: + sb.AppendLine("120 mm Hybrid CD-R (Photo CD)"); + + break; + case MediumTypes.CDR_80: + sb.AppendLine("80 mm CD-R with data only"); + + break; + case MediumTypes.CDR_DA_80: + sb.AppendLine("80 mm CD-R with audio only"); + + break; + case MediumTypes.CDR_Mixed_80: + sb.AppendLine("80 mm CD-R with data and audio"); + + break; + case MediumTypes.HybridCDR_80: + sb.AppendLine("80 mm Hybrid CD-R (Photo CD)"); + + break; + case MediumTypes.Unknown_CDRW: + sb.AppendLine("Unknown size CD-RW"); + + break; + case MediumTypes.CDRW: + sb.AppendLine("120 mm CD-RW with data only"); + + break; + case MediumTypes.CDRW_DA: + sb.AppendLine("120 mm CD-RW with audio only"); + + break; + case MediumTypes.CDRW_Mixed: + sb.AppendLine("120 mm CD-RW with data and audio"); + + break; + case MediumTypes.HybridCDRW: + sb.AppendLine("120 mm Hybrid CD-RW (Photo CD)"); + + break; + case MediumTypes.CDRW_80: + sb.AppendLine("80 mm CD-RW with data only"); + + break; + case MediumTypes.CDRW_DA_80: + sb.AppendLine("80 mm CD-RW with audio only"); + + break; + case MediumTypes.CDRW_Mixed_80: + sb.AppendLine("80 mm CD-RW with data and audio"); + + break; + case MediumTypes.HybridCDRW_80: + sb.AppendLine("80 mm Hybrid CD-RW (Photo CD)"); + + break; + case MediumTypes.Unknown_HD: + sb.AppendLine("Unknown size HD disc"); + + break; + case MediumTypes.HD: + sb.AppendLine("120 mm HD disc"); + + break; + case MediumTypes.HD_80: + sb.AppendLine("80 mm HD disc"); + + break; + case MediumTypes.NoDisc: + sb.AppendLine("No disc inserted, tray closed or caddy inserted"); + + break; + case MediumTypes.TrayOpen: + sb.AppendLine("Tray open or no caddy inserted"); + + break; + case MediumTypes.MediumError: + sb.AppendLine("Tray closed or caddy inserted but medium error"); + + break; + case MediumTypes.UnknownBlockDevice: + sb.AppendLine("Unknown block device"); + + break; + case MediumTypes.ReadOnlyBlockDevice: + sb.AppendLine("Read-only block device"); + + break; + case MediumTypes.ReadWriteBlockDevice: + sb.AppendLine("Read/Write block device"); + + break; + case MediumTypes.LTOCD: + sb.AppendLine("LTO in CD-ROM emulation mode"); + + break; + default: + sb.AppendFormat("Unknown medium type 0x{0:X2}", (byte)header.Value.MediumType).AppendLine(); + + break; + } + + if(header.Value.WriteProtected) + sb.AppendLine("\tMedium is write protected"); + + if(header.Value.DPOFUA) + sb.AppendLine("\tDrive supports DPO and FUA bits"); + + if(header.Value.BlockDescriptors != null) + foreach(BlockDescriptor descriptor in header.Value.BlockDescriptors) + { + string density = ""; + + switch(descriptor.Density) + { + case DensityType.Default: break; + case DensityType.User: + density = "user data only"; + + break; + case DensityType.UserAuxiliary: + density = "user data plus auxiliary data"; + + break; + case DensityType.UserAuxiliaryTag: + density = "4-byte tag, user data plus auxiliary data"; + + break; + case DensityType.Audio: + density = "audio information only"; + + break; + case DensityType.LTO2: + density = "LTO Ultrium-2"; + + break; + case DensityType.LTO3: + density = "LTO Ultrium-3"; + + break; + case DensityType.LTO4: + density = "LTO Ultrium-4"; + + break; + case DensityType.LTO5: + density = "LTO Ultrium-5"; + + break; + default: + density = $"with unknown density code 0x{(byte)descriptor.Density:X2}"; + + break; + } + + if(density != "") + if(descriptor.Blocks == 0) + sb.AppendFormat("\tAll remaining blocks have {0} and are {1} bytes each", density, + descriptor.BlockLength).AppendLine(); + else + sb.AppendFormat("\t{0} blocks have {1} and are {2} bytes each", descriptor.Blocks, + density, descriptor.BlockLength).AppendLine(); + else if(descriptor.Blocks == 0) + sb.AppendFormat("\tAll remaining blocks are {0} bytes each", descriptor.BlockLength). + AppendLine(); + else + sb.AppendFormat("\t{0} blocks are {1} bytes each", descriptor.Blocks, + descriptor.BlockLength).AppendLine(); + } + + break; + } + #endregion Multimedia device mode header + } + + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/Mode10.cs b/Aaru.Decoders/SCSI/Modes/Mode10.cs new file mode 100644 index 000000000..c24301157 --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/Mode10.cs @@ -0,0 +1,360 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Mode10.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes and encodines SCSI modes in MODE SENSE/SELECT (10) format. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Aaru.CommonTypes.Structs.Devices.SCSI; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + public static ModeHeader? DecodeModeHeader10(byte[] modeResponse, PeripheralDeviceTypes deviceType) + { + if(modeResponse == null || + modeResponse.Length < 8) + return null; + + ushort modeLength = (ushort)((modeResponse[0] << 8) + modeResponse[1]); + ushort blockDescLength = (ushort)((modeResponse[6] << 8) + modeResponse[7]); + + if(modeResponse.Length < modeLength) + return null; + + var header = new ModeHeader + { + MediumType = (MediumTypes)modeResponse[2] + }; + + bool longLBA = (modeResponse[4] & 0x01) == 0x01; + + if(blockDescLength > 0) + if(longLBA) + { + header.BlockDescriptors = new BlockDescriptor[blockDescLength / 16]; + + for(int i = 0; i < header.BlockDescriptors.Length; i++) + { + if(12 + (i * 16) + 8 >= modeResponse.Length) + break; + + header.BlockDescriptors[i] = new BlockDescriptor + { + Density = DensityType.Default + }; + + byte[] temp = new byte[8]; + temp[0] = modeResponse[7 + (i * 16) + 8]; + temp[1] = modeResponse[6 + (i * 16) + 8]; + temp[2] = modeResponse[5 + (i * 16) + 8]; + temp[3] = modeResponse[4 + (i * 16) + 8]; + temp[4] = modeResponse[3 + (i * 16) + 8]; + temp[5] = modeResponse[2 + (i * 16) + 8]; + temp[6] = modeResponse[1 + (i * 16) + 8]; + temp[7] = modeResponse[0 + (i * 16) + 8]; + header.BlockDescriptors[i].Blocks = BitConverter.ToUInt64(temp, 0); + header.BlockDescriptors[i].BlockLength += (uint)(modeResponse[15 + (i * 16) + 8] << 24); + header.BlockDescriptors[i].BlockLength += (uint)(modeResponse[14 + (i * 16) + 8] << 16); + header.BlockDescriptors[i].BlockLength += (uint)(modeResponse[13 + (i * 16) + 8] << 8); + header.BlockDescriptors[i].BlockLength += modeResponse[12 + (i * 16) + 8]; + } + } + else + { + header.BlockDescriptors = new BlockDescriptor[blockDescLength / 8]; + + for(int i = 0; i < header.BlockDescriptors.Length; i++) + { + if(7 + (i * 8) + 8 >= modeResponse.Length) + break; + + header.BlockDescriptors[i] = new BlockDescriptor(); + + if(deviceType != PeripheralDeviceTypes.DirectAccess) + header.BlockDescriptors[i].Density = (DensityType)modeResponse[0 + (i * 8) + 8]; + else + { + header.BlockDescriptors[i].Density = DensityType.Default; + header.BlockDescriptors[i].Blocks += (ulong)(modeResponse[0 + (i * 8) + 8] << 24); + } + + header.BlockDescriptors[i].Blocks += (ulong)(modeResponse[1 + (i * 8) + 8] << 16); + header.BlockDescriptors[i].Blocks += (ulong)(modeResponse[2 + (i * 8) + 8] << 8); + header.BlockDescriptors[i].Blocks += modeResponse[3 + (i * 8) + 8]; + header.BlockDescriptors[i].BlockLength += (uint)(modeResponse[5 + (i * 8) + 8] << 16); + header.BlockDescriptors[i].BlockLength += (uint)(modeResponse[6 + (i * 8) + 8] << 8); + header.BlockDescriptors[i].BlockLength += modeResponse[7 + (i * 8) + 8]; + } + } + + switch(deviceType) + { + case PeripheralDeviceTypes.DirectAccess: + case PeripheralDeviceTypes.MultiMediaDevice: + header.WriteProtected = (modeResponse[3] & 0x80) == 0x80; + header.DPOFUA = (modeResponse[3] & 0x10) == 0x10; + + break; + case PeripheralDeviceTypes.SequentialAccess: + header.WriteProtected = (modeResponse[3] & 0x80) == 0x80; + header.Speed = (byte)(modeResponse[3] & 0x0F); + header.BufferedMode = (byte)((modeResponse[3] & 0x70) >> 4); + + break; + case PeripheralDeviceTypes.PrinterDevice: + header.BufferedMode = (byte)((modeResponse[3] & 0x70) >> 4); + + break; + case PeripheralDeviceTypes.OpticalDevice: + header.WriteProtected = (modeResponse[3] & 0x80) == 0x80; + header.EBC = (modeResponse[3] & 0x01) == 0x01; + header.DPOFUA = (modeResponse[3] & 0x10) == 0x10; + + break; + } + + return header; + } + + public static string PrettifyModeHeader10(byte[] modeResponse, PeripheralDeviceTypes deviceType) => + PrettifyModeHeader(DecodeModeHeader10(modeResponse, deviceType), deviceType); + + public static DecodedMode? DecodeMode10(byte[] modeResponse, PeripheralDeviceTypes deviceType) + { + ModeHeader? hdr = DecodeModeHeader10(modeResponse, deviceType); + + if(!hdr.HasValue) + return null; + + var decoded = new DecodedMode + { + Header = hdr.Value + }; + + bool longlba = (modeResponse[4] & 0x01) == 0x01; + int offset; + int blkDrLength = 0; + + if(decoded.Header.BlockDescriptors != null) + blkDrLength = decoded.Header.BlockDescriptors.Length; + + if(longlba) + offset = 8 + (blkDrLength * 16); + else + offset = 8 + (blkDrLength * 8); + + int length = modeResponse[0] << 8; + length += modeResponse[1]; + length += 2; + + if(length != modeResponse.Length) + return decoded; + + List listpages = new List(); + + while(offset < modeResponse.Length) + { + bool isSubpage = (modeResponse[offset] & 0x40) == 0x40; + var pg = new ModePage(); + byte pageNo = (byte)(modeResponse[offset] & 0x3F); + + if(pageNo == 0) + { + pg.PageResponse = new byte[modeResponse.Length - offset]; + Array.Copy(modeResponse, offset, pg.PageResponse, 0, pg.PageResponse.Length); + pg.Page = 0; + pg.Subpage = 0; + offset += pg.PageResponse.Length; + } + else + { + if(isSubpage) + { + pg.PageResponse = new byte[(modeResponse[offset + 2] << 8) + modeResponse[offset + 3] + 4]; + int copyLen = pg.PageResponse.Length; + + if(pg.PageResponse.Length + offset > modeResponse.Length) + copyLen = modeResponse.Length - offset; + + Array.Copy(modeResponse, offset, pg.PageResponse, 0, copyLen); + pg.Page = (byte)(modeResponse[offset] & 0x3F); + pg.Subpage = modeResponse[offset + 1]; + offset += pg.PageResponse.Length; + } + else + { + pg.PageResponse = new byte[modeResponse[offset + 1] + 2]; + int copyLen = pg.PageResponse.Length; + + if(pg.PageResponse.Length + offset > modeResponse.Length) + copyLen = modeResponse.Length - offset; + + Array.Copy(modeResponse, offset, pg.PageResponse, 0, copyLen); + pg.Page = (byte)(modeResponse[offset] & 0x3F); + pg.Subpage = 0; + offset += pg.PageResponse.Length; + } + } + + listpages.Add(pg); + } + + decoded.Pages = listpages.ToArray(); + + return decoded; + } + + public static byte[] EncodeModeHeader10(ModeHeader header, PeripheralDeviceTypes deviceType, + bool longLBA = false) + { + byte[] hdr; + + if(header.BlockDescriptors != null) + hdr = longLBA ? new byte[8 + (header.BlockDescriptors.Length * 16)] + : new byte[8 + (header.BlockDescriptors.Length * 8)]; + else + hdr = new byte[8]; + + hdr[2] = (byte)header.MediumType; + + switch(deviceType) + { + case PeripheralDeviceTypes.DirectAccess: + case PeripheralDeviceTypes.MultiMediaDevice: + if(header.WriteProtected) + hdr[3] += 0x80; + + if(header.DPOFUA) + hdr[3] += 0x10; + + break; + case PeripheralDeviceTypes.SequentialAccess: + if(header.WriteProtected) + hdr[3] += 0x80; + + hdr[3] += (byte)(header.Speed & 0x0F); + hdr[3] += (byte)((header.BufferedMode << 4) & 0x70); + + break; + case PeripheralDeviceTypes.PrinterDevice: + hdr[3] += (byte)((header.BufferedMode << 4) & 0x70); + + break; + case PeripheralDeviceTypes.OpticalDevice: + if(header.WriteProtected) + hdr[3] += 0x80; + + if(header.EBC) + hdr[3] += 0x01; + + if(header.DPOFUA) + hdr[3] += 0x10; + + break; + } + + if(longLBA) + hdr[4] += 0x01; + + if(header.BlockDescriptors == null) + return hdr; + + if(longLBA) + for(int i = 0; i < header.BlockDescriptors.Length; i++) + { + byte[] temp = BitConverter.GetBytes(header.BlockDescriptors[i].Blocks); + hdr[7 + (i * 16) + 8] = temp[0]; + hdr[6 + (i * 16) + 8] = temp[1]; + hdr[5 + (i * 16) + 8] = temp[2]; + hdr[4 + (i * 16) + 8] = temp[3]; + hdr[3 + (i * 16) + 8] = temp[4]; + hdr[2 + (i * 16) + 8] = temp[5]; + hdr[1 + (i * 16) + 8] = temp[6]; + hdr[0 + (i * 16) + 8] = temp[7]; + hdr[12 + (i * 16) + 8] = (byte)((header.BlockDescriptors[i].BlockLength & 0xFF000000) >> 24); + hdr[13 + (i * 16) + 8] = (byte)((header.BlockDescriptors[i].BlockLength & 0xFF0000) >> 16); + hdr[14 + (i * 16) + 8] = (byte)((header.BlockDescriptors[i].BlockLength & 0xFF00) >> 8); + hdr[15 + (i * 16) + 8] = (byte)(header.BlockDescriptors[i].BlockLength & 0xFF); + } + else + for(int i = 0; i < header.BlockDescriptors.Length; i++) + { + if(deviceType != PeripheralDeviceTypes.DirectAccess) + hdr[0 + (i * 8) + 8] = (byte)header.BlockDescriptors[i].Density; + else + hdr[0 + (i * 8) + 8] = (byte)((header.BlockDescriptors[i].Blocks & 0xFF000000) >> 24); + + hdr[1 + (i * 8) + 8] = (byte)((header.BlockDescriptors[i].Blocks & 0xFF0000) >> 16); + hdr[2 + (i * 8) + 8] = (byte)((header.BlockDescriptors[i].Blocks & 0xFF00) >> 8); + hdr[3 + (i * 8) + 8] = (byte)(header.BlockDescriptors[i].Blocks & 0xFF); + hdr[5 + (i * 8) + 8] = (byte)((header.BlockDescriptors[i].BlockLength & 0xFF0000) >> 16); + hdr[6 + (i * 8) + 8] = (byte)((header.BlockDescriptors[i].BlockLength & 0xFF00) >> 8); + hdr[7 + (i * 8) + 8] = (byte)(header.BlockDescriptors[i].BlockLength & 0xFF); + } + + return hdr; + } + + public static byte[] EncodeMode10(DecodedMode mode, PeripheralDeviceTypes deviceType) + { + int modeSize = 0; + + if(mode.Pages != null) + modeSize += mode.Pages.Sum(page => page.PageResponse.Length); + + byte[] hdr = EncodeModeHeader10(mode.Header, deviceType); + modeSize += hdr.Length; + byte[] md = new byte[modeSize]; + + Array.Copy(hdr, 0, md, 0, hdr.Length); + + if(mode.Pages == null) + return md; + + { + int offset = hdr.Length; + + foreach(ModePage page in mode.Pages) + { + Array.Copy(page.PageResponse, 0, md, offset, page.PageResponse.Length); + offset += page.PageResponse.Length; + } + } + + return md; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/Mode6.cs b/Aaru.Decoders/SCSI/Modes/Mode6.cs new file mode 100644 index 000000000..9e9b815ec --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/Mode6.cs @@ -0,0 +1,279 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Modes.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes and encodines SCSI modes in MODE SENSE/SELECT (6) format. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Aaru.CommonTypes.Structs.Devices.SCSI; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + public static ModeHeader? DecodeModeHeader6(byte[] modeResponse, PeripheralDeviceTypes deviceType) + { + if(modeResponse == null || + modeResponse.Length < 4 || + modeResponse.Length < modeResponse[0] + 1) + return null; + + var header = new ModeHeader + { + MediumType = (MediumTypes)modeResponse[1] + }; + + if(modeResponse[3] > 0) + { + header.BlockDescriptors = new BlockDescriptor[modeResponse[3] / 8]; + + for(int i = 0; i < header.BlockDescriptors.Length; i++) + { + header.BlockDescriptors[i].Density = (DensityType)modeResponse[0 + (i * 8) + 4]; + header.BlockDescriptors[i].Blocks += (ulong)(modeResponse[1 + (i * 8) + 4] << 16); + header.BlockDescriptors[i].Blocks += (ulong)(modeResponse[2 + (i * 8) + 4] << 8); + header.BlockDescriptors[i].Blocks += modeResponse[3 + (i * 8) + 4]; + header.BlockDescriptors[i].BlockLength += (uint)(modeResponse[5 + (i * 8) + 4] << 16); + header.BlockDescriptors[i].BlockLength += (uint)(modeResponse[6 + (i * 8) + 4] << 8); + header.BlockDescriptors[i].BlockLength += modeResponse[7 + (i * 8) + 4]; + } + } + + switch(deviceType) + { + case PeripheralDeviceTypes.DirectAccess: + case PeripheralDeviceTypes.MultiMediaDevice: + header.WriteProtected = (modeResponse[2] & 0x80) == 0x80; + header.DPOFUA = (modeResponse[2] & 0x10) == 0x10; + + break; + case PeripheralDeviceTypes.SequentialAccess: + header.WriteProtected = (modeResponse[2] & 0x80) == 0x80; + header.Speed = (byte)(modeResponse[2] & 0x0F); + header.BufferedMode = (byte)((modeResponse[2] & 0x70) >> 4); + + break; + case PeripheralDeviceTypes.PrinterDevice: + header.BufferedMode = (byte)((modeResponse[2] & 0x70) >> 4); + + break; + case PeripheralDeviceTypes.OpticalDevice: + header.WriteProtected = (modeResponse[2] & 0x80) == 0x80; + header.EBC = (modeResponse[2] & 0x01) == 0x01; + header.DPOFUA = (modeResponse[2] & 0x10) == 0x10; + + break; + } + + return header; + } + + public static string PrettifyModeHeader6(byte[] modeResponse, PeripheralDeviceTypes deviceType) => + PrettifyModeHeader(DecodeModeHeader6(modeResponse, deviceType), deviceType); + + public static DecodedMode? DecodeMode6(byte[] modeResponse, PeripheralDeviceTypes deviceType) + { + ModeHeader? hdr = DecodeModeHeader6(modeResponse, deviceType); + + if(!hdr.HasValue) + return null; + + var decoded = new DecodedMode + { + Header = hdr.Value + }; + + int blkDrLength = 0; + + if(decoded.Header.BlockDescriptors != null) + blkDrLength = decoded.Header.BlockDescriptors.Length; + + int offset = 4 + (blkDrLength * 8); + int length = modeResponse[0] + 1; + + if(length != modeResponse.Length) + return decoded; + + List listpages = new List(); + + while(offset < modeResponse.Length) + { + bool isSubpage = (modeResponse[offset] & 0x40) == 0x40; + var pg = new ModePage(); + byte pageNo = (byte)(modeResponse[offset] & 0x3F); + + if(pageNo == 0) + { + pg.PageResponse = new byte[modeResponse.Length - offset]; + Array.Copy(modeResponse, offset, pg.PageResponse, 0, pg.PageResponse.Length); + pg.Page = 0; + pg.Subpage = 0; + offset += pg.PageResponse.Length; + } + else + { + if(isSubpage) + { + if(offset + 3 >= modeResponse.Length) + break; + + pg.PageResponse = new byte[(modeResponse[offset + 2] << 8) + modeResponse[offset + 3] + 4]; + int copyLen = pg.PageResponse.Length; + + if(pg.PageResponse.Length + offset > modeResponse.Length) + copyLen = modeResponse.Length - offset; + + Array.Copy(modeResponse, offset, pg.PageResponse, 0, copyLen); + pg.Page = (byte)(modeResponse[offset] & 0x3F); + pg.Subpage = modeResponse[offset + 1]; + offset += pg.PageResponse.Length; + } + else + { + if(offset + 1 >= modeResponse.Length) + break; + + pg.PageResponse = new byte[modeResponse[offset + 1] + 2]; + int copyLen = pg.PageResponse.Length; + + if(pg.PageResponse.Length + offset > modeResponse.Length) + copyLen = modeResponse.Length - offset; + + Array.Copy(modeResponse, offset, pg.PageResponse, 0, copyLen); + pg.Page = (byte)(modeResponse[offset] & 0x3F); + pg.Subpage = 0; + offset += pg.PageResponse.Length; + } + } + + listpages.Add(pg); + } + + decoded.Pages = listpages.ToArray(); + + return decoded; + } + + public static byte[] EncodeModeHeader6(ModeHeader header, PeripheralDeviceTypes deviceType) + { + byte[] hdr = header.BlockDescriptors != null ? new byte[4 + (header.BlockDescriptors.Length * 8)] + : new byte[4]; + + hdr[1] = (byte)header.MediumType; + + switch(deviceType) + { + case PeripheralDeviceTypes.DirectAccess: + case PeripheralDeviceTypes.MultiMediaDevice: + if(header.WriteProtected) + hdr[2] += 0x80; + + if(header.DPOFUA) + hdr[2] += 0x10; + + break; + case PeripheralDeviceTypes.SequentialAccess: + if(header.WriteProtected) + hdr[2] += 0x80; + + hdr[2] += (byte)(header.Speed & 0x0F); + hdr[2] += (byte)((header.BufferedMode << 4) & 0x70); + + break; + case PeripheralDeviceTypes.PrinterDevice: + hdr[2] += (byte)((header.BufferedMode << 4) & 0x70); + + break; + case PeripheralDeviceTypes.OpticalDevice: + if(header.WriteProtected) + hdr[2] += 0x80; + + if(header.EBC) + hdr[2] += 0x01; + + if(header.DPOFUA) + hdr[2] += 0x10; + + break; + } + + if(header.BlockDescriptors == null) + return hdr; + + hdr[3] = (byte)(header.BlockDescriptors.Length * 8); + + for(int i = 0; i < header.BlockDescriptors.Length; i++) + { + hdr[0 + (i * 8) + 4] = (byte)header.BlockDescriptors[i].Density; + hdr[1 + (i * 8) + 4] = (byte)((header.BlockDescriptors[i].Blocks & 0xFF0000) >> 16); + hdr[2 + (i * 8) + 4] = (byte)((header.BlockDescriptors[i].Blocks & 0xFF00) >> 8); + hdr[3 + (i * 8) + 4] = (byte)(header.BlockDescriptors[i].Blocks & 0xFF); + hdr[5 + (i * 8) + 4] = (byte)((header.BlockDescriptors[i].BlockLength & 0xFF0000) >> 16); + hdr[6 + (i * 8) + 4] = (byte)((header.BlockDescriptors[i].BlockLength & 0xFF00) >> 8); + hdr[7 + (i * 8) + 4] = (byte)(header.BlockDescriptors[i].BlockLength & 0xFF); + } + + return hdr; + } + + public static byte[] EncodeMode6(DecodedMode mode, PeripheralDeviceTypes deviceType) + { + int modeSize = 0; + + if(mode.Pages != null) + modeSize += mode.Pages.Sum(page => page.PageResponse.Length); + + byte[] hdr = EncodeModeHeader6(mode.Header, deviceType); + modeSize += hdr.Length; + byte[] md = new byte[modeSize]; + + Array.Copy(hdr, 0, md, 0, hdr.Length); + + if(mode.Pages == null) + return md; + + { + int offset = hdr.Length; + + foreach(ModePage page in mode.Pages) + { + Array.Copy(page.PageResponse, 0, md, offset, page.PageResponse.Length); + offset += page.PageResponse.Length; + } + } + + return md; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Modes/Structs.cs b/Aaru.Decoders/SCSI/Modes/Structs.cs new file mode 100644 index 000000000..3bccba22a --- /dev/null +++ b/Aaru.Decoders/SCSI/Modes/Structs.cs @@ -0,0 +1,72 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Structs.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Common structures for MODE pages decoding and encoding. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Modes + { + public struct BlockDescriptor + { + public DensityType Density; + public ulong Blocks; + public uint BlockLength; + } + + public struct ModeHeader + { + public MediumTypes MediumType; + public bool WriteProtected; + public BlockDescriptor[] BlockDescriptors; + public byte Speed; + public byte BufferedMode; + public bool EBC; + public bool DPOFUA; + } + + public struct ModePage + { + public byte Page; + public byte Subpage; + public byte[] PageResponse; + } + + public struct DecodedMode + { + public ModeHeader Header; + public ModePage[] Pages; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/SSC/BlockLimits.cs b/Aaru.Decoders/SCSI/SSC/BlockLimits.cs new file mode 100644 index 000000000..568341c38 --- /dev/null +++ b/Aaru.Decoders/SCSI/SSC/BlockLimits.cs @@ -0,0 +1,94 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : BlockLimits.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI SSC block limits structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SCSI.SSC +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class BlockLimits + { + public static BlockLimitsData? Decode(byte[] response) + { + if(response?.Length != 6) + return null; + + return new BlockLimitsData + { + granularity = (byte)(response[0] & 0x1F), + maxBlockLen = (uint)((response[1] << 16) + (response[2] << 8) + response[3]), + minBlockLen = (ushort)((response[4] << 8) + response[5]) + }; + } + + public static string Prettify(BlockLimitsData? decoded) + { + if(decoded == null) + return null; + + var sb = new StringBuilder(); + + if(decoded.Value.maxBlockLen == decoded.Value.minBlockLen) + sb.AppendFormat("Device's block size is fixed at {0} bytes", decoded.Value.minBlockLen).AppendLine(); + else + { + if(decoded.Value.maxBlockLen > 0) + sb.AppendFormat("Device's maximum block size is {0} bytes", decoded.Value.maxBlockLen).AppendLine(); + else + sb.AppendLine("Device does not specify a maximum block size"); + + sb.AppendFormat("Device's minimum block size is {0} bytes", decoded.Value.minBlockLen).AppendLine(); + + if(decoded.Value.granularity > 0) + sb.AppendFormat("Device's needs a block size granularity of 2^{0} ({1}) bytes", + decoded.Value.granularity, Math.Pow(2, decoded.Value.granularity)).AppendLine(); + } + + return sb.ToString(); + } + + public static string Prettify(byte[] response) => Prettify(Decode(response)); + + public struct BlockLimitsData + { + /// All blocks size must be multiple of 2^ + public byte granularity; + /// Maximum block length in bytes + public uint maxBlockLen; + /// Minimum block length in bytes + public ushort minBlockLen; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/SSC/DensitySupport.cs b/Aaru.Decoders/SCSI/SSC/DensitySupport.cs new file mode 100644 index 000000000..e6bee06fc --- /dev/null +++ b/Aaru.Decoders/SCSI/SSC/DensitySupport.cs @@ -0,0 +1,294 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : DensitySupport.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI SSC density support structures. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Helpers; + +namespace Aaru.Decoders.SCSI.SSC +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class DensitySupport + { + public static DensitySupportHeader? DecodeDensity(byte[] response) + { + if(response == null) + return null; + + if(response.Length <= 56) + return null; + + ushort responseLen = (ushort)((response[0] << 8) + response[1] + 2); + + if(response.Length != responseLen) + return null; + + List descriptors = new List(); + int offset = 4; + + while(offset < response.Length) + { + var descriptor = new DensitySupportDescriptor + { + primaryCode = response[offset + 0], + secondaryCode = response[offset + 1], + writable = (response[offset + 2] & 0x80) == 0x80, + duplicate = (response[offset + 2] & 0x40) == 0x40, + defaultDensity = (response[offset + 2] & 0x20) == 0x20, + reserved = (byte)((response[offset + 2] & 0x1E) >> 1), + lenvalid = (response[offset + 2] & 0x01) == 0x01, + len = (ushort)((response[offset + 3] << 8) + response[offset + 4]), + bpmm = (uint)((response[offset + 5] << 16) + (response[offset + 6] << 8) + response[offset + 7]), + width = (ushort)((response[offset + 8] << 8) + response[offset + 9]), + tracks = (ushort)((response[offset + 10] << 8) + response[offset + 11]), + capacity = (uint)((response[offset + 12] << 24) + (response[offset + 13] << 16) + + (response[offset + 14] << 8) + response[offset + 15]) + }; + + byte[] tmp = new byte[8]; + Array.Copy(response, offset + 16, tmp, 0, 8); + descriptor.organization = StringHandlers.CToString(tmp).Trim(); + tmp = new byte[8]; + Array.Copy(response, offset + 24, tmp, 0, 8); + descriptor.name = StringHandlers.CToString(tmp).Trim(); + tmp = new byte[20]; + Array.Copy(response, offset + 32, tmp, 0, 20); + descriptor.description = StringHandlers.CToString(tmp).Trim(); + + if(descriptor.lenvalid) + offset += descriptor.len + 5; + else + offset += 52; + + descriptors.Add(descriptor); + } + + var decoded = new DensitySupportHeader + { + length = responseLen, + reserved = (ushort)((response[2] << 8) + response[3] + 2), + descriptors = descriptors.ToArray() + }; + + return decoded; + } + + public static string PrettifyDensity(DensitySupportHeader? density) + { + if(density == null) + return null; + + DensitySupportHeader decoded = density.Value; + var sb = new StringBuilder(); + + foreach(DensitySupportDescriptor descriptor in decoded.descriptors) + { + sb.AppendFormat("Density \"{0}\" defined by \"{1}\".", descriptor.name, descriptor.organization). + AppendLine(); + + sb.AppendFormat("\tPrimary code: {0:X2}h", descriptor.primaryCode).AppendLine(); + + if(descriptor.primaryCode != descriptor.secondaryCode) + sb.AppendFormat("\tSecondary code: {0:X2}h", descriptor.secondaryCode).AppendLine(); + + if(descriptor.writable) + sb.AppendLine("\tDrive can write this density"); + + if(descriptor.duplicate) + sb.AppendLine("\tThis descriptor is duplicated"); + + if(descriptor.defaultDensity) + sb.AppendLine("\tThis is the default density on the drive"); + + sb.AppendFormat("\tDensity has {0} bits per mm, with {1} tracks in a {2} mm width tape", + descriptor.bpmm, descriptor.tracks, descriptor.width / (double)10).AppendLine(); + + sb.AppendFormat("\tDensity maximum capacity is {0} megabytes", descriptor.capacity).AppendLine(); + sb.AppendFormat("\tDensity description: {0}", descriptor.description).AppendLine(); + sb.AppendLine(); + } + + return sb.ToString(); + } + + public static string PrettifyDensity(byte[] response) => PrettifyDensity(DecodeDensity(response)); + + public static MediaTypeSupportHeader? DecodeMediumType(byte[] response) + { + if(response == null) + return null; + + if(response.Length <= 60) + return null; + + ushort responseLen = (ushort)((response[0] << 8) + response[1] + 2); + + if(response.Length != responseLen) + return null; + + List descriptors = new List(); + int offset = 4; + + while(offset < response.Length) + { + var descriptor = new MediaTypeSupportDescriptor + { + mediumType = response[offset + 0], + reserved1 = response[offset + 1], + len = (ushort)((response[offset + 2] << 8) + response[offset + 3]) + }; + + if(descriptor.len != 52) + return null; + + descriptor.numberOfCodes = response[offset + 4]; + descriptor.densityCodes = new byte[9]; + Array.Copy(response, offset + 5, descriptor.densityCodes, 0, 9); + descriptor.width = (ushort)((response[offset + 14] << 8) + response[offset + 15]); + descriptor.length = (ushort)((response[offset + 16] << 8) + response[offset + 17]); + descriptor.reserved1 = response[offset + 18]; + descriptor.reserved1 = response[offset + 19]; + byte[] tmp = new byte[8]; + Array.Copy(response, offset + 20, tmp, 0, 8); + descriptor.organization = StringHandlers.CToString(tmp).Trim(); + tmp = new byte[8]; + Array.Copy(response, offset + 28, tmp, 0, 8); + descriptor.name = StringHandlers.CToString(tmp).Trim(); + tmp = new byte[20]; + Array.Copy(response, offset + 36, tmp, 0, 20); + descriptor.description = StringHandlers.CToString(tmp).Trim(); + + offset += 56; + + descriptors.Add(descriptor); + } + + var decoded = new MediaTypeSupportHeader + { + length = responseLen, + reserved = (ushort)((response[2] << 8) + response[3] + 2), + descriptors = descriptors.ToArray() + }; + + return decoded; + } + + public static string PrettifyMediumType(MediaTypeSupportHeader? mediumType) + { + if(mediumType == null) + return null; + + MediaTypeSupportHeader decoded = mediumType.Value; + var sb = new StringBuilder(); + + foreach(MediaTypeSupportDescriptor descriptor in decoded.descriptors) + { + sb.AppendFormat("Medium type \"{0}\" defined by \"{1}\".", descriptor.name, descriptor.organization). + AppendLine(); + + sb.AppendFormat("\tMedium type code: {0:X2}h", descriptor.mediumType).AppendLine(); + + if(descriptor.numberOfCodes > 0) + { + sb.AppendFormat("\tMedium supports following density codes:"); + + for(int i = 0; i < descriptor.numberOfCodes; i++) + sb.AppendFormat(" {0:X2}h", descriptor.densityCodes[i]); + + sb.AppendLine(); + } + + sb.AppendFormat("\tMedium has a nominal length of {0} m in a {1} mm width tape", descriptor.length, + descriptor.width / (double)10).AppendLine(); + + sb.AppendFormat("\tMedium description: {0}", descriptor.description).AppendLine(); + sb.AppendLine(); + } + + return sb.ToString(); + } + + public static string PrettifyMediumType(byte[] response) => PrettifyMediumType(DecodeMediumType(response)); + + public struct DensitySupportHeader + { + public ushort length; + public ushort reserved; + public DensitySupportDescriptor[] descriptors; + } + + public struct MediaTypeSupportHeader + { + public ushort length; + public ushort reserved; + public MediaTypeSupportDescriptor[] descriptors; + } + + public struct DensitySupportDescriptor + { + public byte primaryCode; + public byte secondaryCode; + public bool writable; + public bool duplicate; + public bool defaultDensity; + public byte reserved; + public bool lenvalid; + public ushort len; + public uint bpmm; + public ushort width; + public ushort tracks; + public uint capacity; + public string organization; + public string name; + public string description; + } + + public struct MediaTypeSupportDescriptor + { + public byte mediumType; + public byte reserved1; + public ushort len; + public byte numberOfCodes; + public byte[] densityCodes; + public ushort width; + public ushort length; + public byte reserved2; + public byte reserved3; + public string organization; + public string name; + public string description; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Sense.cs b/Aaru.Decoders/SCSI/Sense.cs new file mode 100644 index 000000000..af5d12c02 --- /dev/null +++ b/Aaru.Decoders/SCSI/Sense.cs @@ -0,0 +1,2001 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Sense.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SCSI SENSE. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Decoders.ATA; + +namespace Aaru.Decoders.SCSI +{ + public enum SenseType + { + StandardSense, ExtendedSenseFixedCurrent, ExtendedSenseFixedPast, + ExtendedSenseDescriptorCurrent, ExtendedSenseDescriptorPast, Invalid, + Unknown + } + + public struct DecodedSense + { + public FixedSense? Fixed; + public DescriptorSense? Descriptor; + public readonly byte ASC => Descriptor?.ASC ?? (Fixed?.ASC ?? 0); + public readonly byte ASCQ => Descriptor?.ASCQ ?? (Fixed?.ASCQ ?? 0); + public readonly SenseKeys SenseKey => Descriptor?.SenseKey ?? (Fixed?.SenseKey ?? SenseKeys.NoSense); + public readonly string Description => Sense.GetSenseDescription(ASC, ASCQ); + } + + [SuppressMessage("ReSharper", "MemberCanBeInternal"), SuppressMessage("ReSharper", "NotAccessedField.Global"), + SuppressMessage("ReSharper", "InconsistentNaming")] + public struct StandardSense + { + /// If set, is valid + public bool AddressValid; + /// Error class, 0 to 6 + public byte ErrorClass; + /// Error type + public byte ErrorType; + /// Private usage + public byte Private; + /// LBA where error happened + public uint LBA; + } + + public enum SenseKeys : byte + { + /// No information to be reported, but bits should be checked + NoSense = 0, + /// Target performed some recovery to successfully complete last command + RecoveredError = 1, + /// Target is not ready + NotReady = 2, + /// Non-recoverable medium error occurred + MediumError = 3, + /// Non-recoverable hardware error occurred + HardwareError = 4, + /// Target has received an illegal request + IllegalRequest = 5, + /// Target requires initiator attention + UnitAttention = 6, + /// A protected command has been denied + DataProtect = 7, + /// A blank block has been tried to read or a non-rewritable one to write + BlankCheck = 8, + /// For private/vendor usage + PrivateUse = 9, + /// COPY command aborted + CopyAborted = 0xA, + /// Command aborted + AbortedCommand = 0xB, + /// SEARCH command has been satisfied + Equal = 0xC, + /// End-of-medium reached with data remaining in buffer + VolumeOverflow = 0xD, + /// COMPARE failed + Miscompare = 0xE, + /// Complated + Completed = 0xF + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "UnassignedField.Global"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct FixedSense + { + /// If set, is valid + public bool InformationValid; + /// Contains number of current segment descriptor + public byte SegmentNumber; + /// If set indicates current command has read a filemark or a setmark + public bool Filemark; + /// If set indicates device has arrived end-of-medium + public bool EOM; + /// Means the requested logical block length did not match the logical block length on the medium + public bool ILI; + /// Contains the sense key + public SenseKeys SenseKey; + /// Additional information + public uint Information; + /// Additional sense length + public byte AdditionalLength; + /// Command specific information field + public uint CommandSpecific; + /// Additional sense code + public byte ASC; + /// Additional sense code qualifier + public byte ASCQ; + public byte FieldReplaceable; + /// If set, is valid + public bool SKSV; + public uint SenseKeySpecific; + public byte[] AdditionalSense; + } + + [SuppressMessage("ReSharper", "MemberCanBeInternal"), SuppressMessage("ReSharper", "InconsistentNaming"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct DescriptorSense + { + /// Contains the sense key + public SenseKeys SenseKey; + /// Additional sense code + public byte ASC; + /// Additional sense code qualifier + public byte ASCQ; + public bool Overflow; + /// The descriptors, indexed by type + public Dictionary Descriptors; + } + + [SuppressMessage("ReSharper", "MemberCanBeInternal"), SuppressMessage("ReSharper", "InconsistentNaming"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public struct AnotherProgressIndicationSenseDescriptor + { + public SenseKeys SenseKey; + public byte ASC; + public byte ASCQ; + public ushort Progress; + } + + [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class Sense + { + /// Gets the SCSI SENSE type to help chosing the correct decoding function + /// The type. + /// Sense bytes. + public static SenseType GetType(byte[] sense) + { + if(sense == null) + return SenseType.Invalid; + + if(sense.Length < 4) + return SenseType.Invalid; + + if((sense[0] & 0x70) != 0x70) + return sense.Length != 4 ? SenseType.Invalid : SenseType.StandardSense; + + switch(sense[0] & 0x0F) + { + case 0: return SenseType.ExtendedSenseFixedCurrent; + case 1: return SenseType.ExtendedSenseFixedPast; + case 2: return SenseType.ExtendedSenseDescriptorCurrent; + case 3: return SenseType.ExtendedSenseDescriptorPast; + default: return SenseType.Unknown; + } + } + + public static StandardSense? DecodeStandard(byte[] sense) + { + if(GetType(sense) != SenseType.StandardSense) + return null; + + var decoded = new StandardSense(); + decoded.AddressValid |= (sense[0] & 0x80) == 0x80; + decoded.ErrorClass = (byte)((sense[0] & 0x70) >> 4); + decoded.ErrorType = (byte)(sense[0] & 0x0F); + decoded.Private = (byte)((sense[1] & 0x80) >> 4); + decoded.LBA = (uint)(((sense[1] & 0x0F) << 16) + (sense[2] << 8) + sense[3]); + + return decoded; + } + + public static DecodedSense? Decode(byte[] sense) + { + var decoded = new DecodedSense(); + + switch(sense[0]) + { + case 0x70: + case 0x71: + decoded.Fixed = DecodeFixed(sense); + + break; + case 0x72: + case 0x73: + decoded.Descriptor = DecodeDescriptor(sense); + + break; + } + + return decoded.Fixed is null && decoded.Descriptor is null ? (DecodedSense?)null : decoded; + } + + public static FixedSense? DecodeFixed(byte[] sense) => DecodeFixed(sense, out _); + + public static FixedSense? DecodeFixed(byte[] sense, out string senseDescription) + { + senseDescription = null; + + if(sense is null || + sense.Length == 0) + return null; + + if((sense[0] & 0x7F) != 0x70 && + (sense[0] & 0x7F) != 0x71) + return null; + + if(sense.Length < 8) + return null; + + var decoded = new FixedSense + { + InformationValid = (sense[0] & 0x80) == 0x80, + SegmentNumber = sense[1], + Filemark = (sense[2] & 0x80) == 0x80, + EOM = (sense[2] & 0x40) == 0x40, + ILI = (sense[2] & 0x20) == 0x20, + SenseKey = (SenseKeys)(sense[2] & 0x0F), + Information = (uint)((sense[3] << 24) + (sense[4] << 16) + (sense[5] << 8) + sense[6]), + AdditionalLength = sense[7] + }; + + if(sense.Length >= 12) + decoded.CommandSpecific = (uint)((sense[8] << 24) + (sense[9] << 16) + (sense[10] << 8) + sense[11]); + + if(sense.Length >= 14) + { + decoded.ASC = sense[12]; + decoded.ASCQ = sense[13]; + senseDescription = GetSenseDescription(decoded.ASC, decoded.ASCQ); + } + + if(sense.Length >= 15) + decoded.FieldReplaceable = sense[14]; + + if(sense.Length >= 18) + decoded.SenseKeySpecific = (uint)((sense[15] << 16) + (sense[16] << 8) + sense[17]); + + if(sense.Length <= 18) + return decoded; + + decoded.AdditionalSense = new byte[sense.Length - 18]; + Array.Copy(sense, 18, decoded.AdditionalSense, 0, decoded.AdditionalSense.Length); + + return decoded; + } + + public static DescriptorSense? DecodeDescriptor(byte[] sense) => DecodeDescriptor(sense, out _); + + public static DescriptorSense? DecodeDescriptor(byte[] sense, out string senseDescription) + { + senseDescription = null; + + if(sense == null) + return null; + + if(sense.Length < 8) + return null; + + // Fixed sense + if((sense[0] & 0x7F) == 0x70 || + (sense[0] & 0x7F) == 0x71) + return null; + + var decoded = new DescriptorSense + { + SenseKey = (SenseKeys)(sense[1] & 0x0F), + ASC = sense[2], + ASCQ = sense[3], + Overflow = (sense[4] & 0x80) == 0x80, + Descriptors = new Dictionary() + }; + + senseDescription = GetSenseDescription(decoded.ASC, decoded.ASCQ); + + int offset = 8; + + while(offset < sense.Length) + if(offset + 2 < sense.Length) + { + byte descType = sense[offset]; + int descLen = sense[offset + 1] + 2; + + byte[] desc = new byte[descLen]; + + if(offset + descLen >= sense.Length) + descLen = sense.Length - offset; + + Array.Copy(sense, offset, desc, 0, descLen); + + if(!decoded.Descriptors.ContainsKey(descType)) + decoded.Descriptors.Add(descType, desc); + + offset += descLen; + } + else + break; + + return decoded; + } + + public static string PrettifySense(byte[] sense) + { + SenseType type = GetType(sense); + + switch(type) + { + case SenseType.StandardSense: return PrettifySense(DecodeStandard(sense)); + case SenseType.ExtendedSenseFixedCurrent: + case SenseType.ExtendedSenseFixedPast: return PrettifySense(DecodeFixed(sense)); + case SenseType.ExtendedSenseDescriptorCurrent: + case SenseType.ExtendedSenseDescriptorPast: return PrettifySense(DecodeDescriptor(sense)); + default: return null; + } + } + + public static string PrettifySense(StandardSense? sense) + { + if(!sense.HasValue) + return null; + + return sense.Value.AddressValid + ? $"Error class {sense.Value.ErrorClass} type {sense.Value.ErrorType} happened on block {sense.Value.LBA}\n" + : $"Error class {sense.Value.ErrorClass} type {sense.Value.ErrorType}\n"; + } + + public static string PrettifySense(FixedSense? sense) + { + if(!sense.HasValue) + return null; + + FixedSense decoded = sense.Value; + + var sb = new StringBuilder(); + + sb.AppendFormat("SCSI SENSE: {0}", GetSenseKey(decoded.SenseKey)).AppendLine(); + + if(decoded.SegmentNumber > 0) + sb.AppendFormat("On segment {0}", decoded.SegmentNumber).AppendLine(); + + if(decoded.Filemark) + sb.AppendLine("Filemark or setmark found"); + + if(decoded.EOM) + sb.AppendLine("End-of-medium/partition found"); + + if(decoded.ILI) + sb.AppendLine("Incorrect length indicator"); + + if(decoded.InformationValid) + sb.AppendFormat("On logical block {0}", decoded.Information).AppendLine(); + + if(decoded.AdditionalLength < 6) + return sb.ToString(); + + sb.AppendLine(GetSenseDescription(decoded.ASC, decoded.ASCQ)); + + if(decoded.AdditionalLength < 10) + return sb.ToString(); + + if(!decoded.SKSV) + return sb.ToString(); + + switch(decoded.SenseKey) + { + case SenseKeys.IllegalRequest: + { + sb.AppendLine((decoded.SenseKeySpecific & 0x400000) == 0x400000 ? "Illegal field in CDB" + : "Illegal field in data parameters"); + + if((decoded.SenseKeySpecific & 0x200000) == 0x200000) + sb.AppendFormat("Invalid value in bit {0} in field {1} of CDB", + (decoded.SenseKeySpecific & 0x70000) >> 16, decoded.SenseKeySpecific & 0xFFFF). + AppendLine(); + else + sb.AppendFormat("Invalid value in field {0} of CDB", decoded.SenseKeySpecific & 0xFFFF). + AppendLine(); + } + + break; + case SenseKeys.NotReady: + sb.AppendFormat("Format progress {0:P}", (double)(decoded.SenseKeySpecific & 0xFFFF) / 65536). + AppendLine(); + + break; + case SenseKeys.RecoveredError: + case SenseKeys.HardwareError: + case SenseKeys.MediumError: + sb.AppendFormat("Actual retry count is {0}", decoded.SenseKeySpecific & 0xFFFF).AppendLine(); + + break; + } + + return sb.ToString(); + } + + public static string PrettifySense(DescriptorSense? sense) + { + if(!sense.HasValue) + return null; + + DescriptorSense decoded = sense.Value; + + var sb = new StringBuilder(); + + sb.AppendFormat("SCSI SENSE: {0}", GetSenseKey(decoded.SenseKey)).AppendLine(); + sb.AppendLine(GetSenseDescription(decoded.ASC, decoded.ASCQ)); + + if(decoded.Descriptors == null || + decoded.Descriptors.Count == 0) + return sb.ToString(); + + foreach(KeyValuePair kvp in decoded.Descriptors) + switch(kvp.Key) + { + case 0x00: + sb.AppendLine(PrettifyDescriptor00(kvp.Value)); + + break; + } + + return sb.ToString(); + } + + /// Decodes the information sense data descriptor + /// The information value + /// Descriptor. + public static ulong DecodeDescriptor00(byte[] descriptor) + { + if(descriptor.Length != 12 || + descriptor[0] != 0x00) + return 0; + + byte[] temp = new byte[8]; + + temp[0] = descriptor[11]; + temp[1] = descriptor[10]; + temp[2] = descriptor[9]; + temp[3] = descriptor[8]; + temp[4] = descriptor[7]; + temp[5] = descriptor[6]; + temp[6] = descriptor[5]; + temp[7] = descriptor[4]; + + return BitConverter.ToUInt64(temp, 0); + } + + /// Decodes the command-specific information sense data descriptor + /// The command-specific information sense data descriptor. + /// Descriptor. + public static ulong DecodeDescriptor01(byte[] descriptor) + { + if(descriptor.Length != 12 || + descriptor[0] != 0x01) + return 0; + + byte[] temp = new byte[8]; + + temp[0] = descriptor[11]; + temp[1] = descriptor[10]; + temp[2] = descriptor[9]; + temp[3] = descriptor[8]; + temp[4] = descriptor[7]; + temp[5] = descriptor[6]; + temp[6] = descriptor[5]; + temp[7] = descriptor[4]; + + return BitConverter.ToUInt64(temp, 0); + } + + /// Decodes the sense key specific sense data descriptor + /// The sense key specific sense data descriptor. + /// Descriptor. + public static byte[] DecodeDescriptor02(byte[] descriptor) + { + if(descriptor.Length != 8 || + descriptor[0] != 0x02) + return null; + + byte[] temp = new byte[3]; + Array.Copy(descriptor, 4, temp, 0, 3); + + return temp; + } + + /// Decodes the field replaceable unit sense data descriptor + /// The field replaceable unit sense data descriptor. + /// Descriptor. + public static byte DecodeDescriptor03(byte[] descriptor) + { + if(descriptor.Length != 4 || + descriptor[0] != 0x03) + return 0; + + return descriptor[3]; + } + + /// Decodes the another progress indication sense data descriptor + /// The another progress indication sense data descriptor. + /// Descriptor. + public static AnotherProgressIndicationSenseDescriptor? DecodeDescriptor0A(byte[] descriptor) + { + if(descriptor.Length != 8 || + descriptor[0] != 0x0A) + return null; + + return new AnotherProgressIndicationSenseDescriptor + { + SenseKey = (SenseKeys)descriptor[2], + ASC = descriptor[3], + ASCQ = descriptor[4], + Progress = (ushort)((descriptor[6] << 8) + descriptor[7]) + }; + } + + public static void DecodeDescriptor04(byte[] descriptor, out bool filemark, out bool eom, out bool ili) + { + filemark = (descriptor[3] & 0x80) > 0; + eom = (descriptor[3] & 0x40) > 0; + ili = (descriptor[3] & 0x20) > 0; + } + + public static void DecodeDescriptor05(byte[] descriptor) => throw new NotImplementedException("Check SBC-3"); + + public static void DecodeDescriptor06(byte[] descriptor) => throw new NotImplementedException("Check OSD"); + + public static void DecodeDescriptor07(byte[] descriptor) => throw new NotImplementedException("Check OSD"); + + public static void DecodeDescriptor08(byte[] descriptor) => throw new NotImplementedException("Check OSD"); + + public static AtaErrorRegistersLba48 DecodeDescriptor09(byte[] descriptor) => new AtaErrorRegistersLba48 + { + Error = descriptor[3], + SectorCount = (ushort)((descriptor[4] << 8) + descriptor[5]), + LbaLowCurrent = descriptor[6], + LbaLowPrevious = descriptor[7], + LbaMidCurrent = descriptor[8], + LbaMidPrevious = descriptor[9], + LbaHighCurrent = descriptor[10], + LbaHighPrevious = descriptor[11], + DeviceHead = descriptor[12], + Status = descriptor[13] + }; + + public static void DecodeDescriptor0B(byte[] descriptor) => throw new NotImplementedException("Check SBC-3"); + + public static void DecodeDescriptor0D(byte[] descriptor) => throw new NotImplementedException("Check SBC-3"); + + public static string PrettifyDescriptor00(ulong information) => $"On logical block {information}\n"; + + public static string PrettifyDescriptor00(byte[] descriptor) => + PrettifyDescriptor00(DecodeDescriptor00(descriptor)); + + public static string GetSenseKey(SenseKeys key) + { + switch(key) + { + case SenseKeys.AbortedCommand: return "ABORTED COMMAND"; + case SenseKeys.BlankCheck: return "BLANK CHECK"; + case SenseKeys.CopyAborted: return "COPY ABORTED"; + case SenseKeys.DataProtect: return "DATA PROTECT"; + case SenseKeys.Equal: return "EQUAL"; + case SenseKeys.HardwareError: return "HARDWARE ERROR"; + case SenseKeys.IllegalRequest: return "ILLEGAL REQUEST"; + case SenseKeys.MediumError: return "MEDIUM ERROR"; + case SenseKeys.Miscompare: return "MISCOMPARE"; + case SenseKeys.NoSense: return "NO SENSE"; + case SenseKeys.PrivateUse: return "PRIVATE USE"; + case SenseKeys.RecoveredError: return "RECOVERED ERROR"; + case SenseKeys.Completed: return "COMPLETED"; + case SenseKeys.UnitAttention: return "UNIT ATTENTION"; + case SenseKeys.VolumeOverflow: return "VOLUME OVERFLOW"; + default: return "UNKNOWN"; + } + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + public static string GetSenseDescription(byte ASC, byte ASCQ) + { + switch(ASC) + { + case 0x00: + switch(ASCQ) + { + case 0x00: return "NO ADDITIONAL SENSE INFORMATION"; + case 0x01: return "FILEMARK DETECTED"; + case 0x02: return "END-OF-PARTITION/MEDIUM DETECTED"; + case 0x03: return "SETMARK DETECTED"; + case 0x04: return "BEGINNING-OF-PARTITION/MEDIUM DETECTED"; + case 0x05: return "END-OF-DATA DETECTED"; + case 0x06: return "I/O PROCESS TERMINATED"; + case 0x07: return "PROGRAMMABLE EARLY WARNING DETECTED"; + case 0x11: return "AUDIO PLAY OPERATION IN PROGRESS"; + case 0x12: return "AUDIO PLAY OPERATION PAUSED"; + case 0x13: return "AUDIO PLAY OPERATION SUCCESSFULLY COMPLETED"; + case 0x14: return "AUDIO PLAY OPERATION STOPPED DUE TO ERROR"; + case 0x15: return "NO CURRENT AUDIO STATUS TO RETURN"; + case 0x16: return "OPERATION IN PROGRESS"; + case 0x17: return "CLEANING REQUESTED"; + case 0x18: return "ERASE OPERATION IN PROGRESS"; + case 0x19: return "LOCATE OPERATION IN PROGRESS"; + case 0x1A: return "REWIND OPERATION IN PROGRESS"; + case 0x1B: return "SET CAPACITY OPERATION IN PROGRESS"; + case 0x1C: return "VERIFY OPERATION IN PROGRESS"; + case 0x1D: return "ATA PASS THROUGH INFORMATION AVAILABLE"; + case 0x1E: return "CONFLICTING SA CREATION REQUEST"; + case 0x1F: return "LOGICAL UNIT TRANSITIONING TO ANOTHER POWER CONDITION"; + case 0x20: return "EXTENDED COPY INFORMATION AVAILABLE"; + case 0x21: return "ATOMIC COMMAND ABORTED DUE TO ACA"; + } + + break; + case 0x01: + switch(ASCQ) + { + case 0x00: return "NO INDEX/SECTOR SIGNAL"; + } + + break; + case 0x02: + switch(ASCQ) + { + case 0x00: return "NO SEEK COMPLETE"; + } + + break; + case 0x03: + switch(ASCQ) + { + case 0x00: return "PERIPHERAL DEVICE WRITE FAULT"; + case 0x01: return "NO WRITE CURRENT"; + case 0x02: return "EXCESSIVE WRITE ERRORS"; + } + + break; + case 0x04: + switch(ASCQ) + { + case 0x00: return "LOGICAL UNIT NOT READY, CAUSE NOT REPORTABLE"; + case 0x01: return "LOGICAL UNIT IS IN PROCESS OF BECOMING READY"; + case 0x02: return "LOGICAL UNIT NOT READY, INITIALIZING COMMAND REQUIRED"; + case 0x03: return "LOGICAL UNIT NOT READY, MANUAL INTERVENTION REQUIRED"; + case 0x04: return "LOGICAL UNIT NOT READY, FORMAT IN PROGRESS"; + case 0x05: return "LOGICAL UNIT NOT READY, REBUILD IN PROGRESS"; + case 0x06: return "LOGICAL UNIT NOT READY, RECALCULATION IN PROGRESS"; + case 0x07: return "LOGICAL UNIT NOT READY, OPERATION IN PROGRESS"; + case 0x08: return "LOGICAL UNIT NOT READY, LONG WRITE IN PROGRESS"; + case 0x09: return "LOGICAL UNIT NOT READY, SELF-TEST IN PROGRESS"; + case 0x0A: return "LOGICAL UNIT NOT ACCESSIBLE, ASYMMETRIC ACCESS STATE TRANSITION"; + case 0x0B: return "LOGICAL UNIT NOT ACCESSIBLE, TARGET IN STANDBY STATE"; + case 0x0C: return "LOGICAL UNIT NOT ACCESSIBLE, TARGET PORT IN UNAVAILABLE STATE"; + case 0x0D: return "LOGICAL UNIT NOT READY, STRUCTURE CHECK REQUIRED"; + case 0x0E: return "LOGICAL UNIT NOT READY, SECURITY SESSION IN PROGRESS"; + case 0x10: return "LOGICAL UNIT NOT READY, AUXILIARY MEMORY NOT ACCESSIBLE"; + case 0x11: return "LOGICAL UNIT NOT READY, NOTIFY (ENABLE SPINUP) REQUIRED"; + case 0x12: return "LOGICAL UNIT NOT READY, OFFLINE"; + case 0x13: return "LOGICAL UNIT NOT READY, SA CREATION IN PROGRESS"; + case 0x14: return "LOGICAL UNIT NOT READY, SPACE ALLOCATION IN PROGRESS"; + case 0x15: return "LOGICAL UNIT NOT READY, ROBOTICS DISABLED"; + case 0x16: return "LOGICAL UNIT NOT READY, CONFIGURATION REQUIRED"; + case 0x17: return "LOGICAL UNIT NOT READY, CALIBRATION REQUIRED"; + case 0x18: return "LOGICAL UNIT NOT READY, A DOOR IS OPEN"; + case 0x19: return "LOGICAL UNIT NOT READY, OPERATING IN SEQUENTIAL MODE"; + case 0x1A: return "LOGICAL UNIT NOT READY, START STOP UNIT IN PROGRESS"; + case 0x1B: return "LOGICAL UNIT NOT READY, SANITIZE IN PROGRESS"; + case 0x1C: return "LOGICAL UNIT NOT READY, ADDITIONAL POWER USE NOT YET GRANTED"; + case 0x1D: return "LOGICAL UNIT NOT READY, CONFIGURATION IN PROGRESS"; + case 0x1E: return "LOGICAL UNIT NOT READY, MICROCODE ACTIVATION REQUIRED"; + case 0x1F: return "LOGICAL UNIT NOT READY, MICROCODE DOWNLOAD REQUIRED"; + case 0x20: return "LOGICAL UNIT NOT READY, LOGICAL UNIT RESET REQUIRED"; + case 0x21: return "LOGICAL UNIT NOT READY, HARD RESET REQUIRED"; + case 0x22: return "LOGICAL UNIT NOT READY, POWER CYCLE REQUIRED"; + } + + break; + case 0x05: + switch(ASCQ) + { + case 0x00: return "LOGICAL UNIT DOES NOT RESPOND TO SELECTION"; + } + + break; + case 0x06: + switch(ASCQ) + { + case 0x00: return "NO REFERENCE POSITION FOUND"; + } + + break; + case 0x07: + switch(ASCQ) + { + case 0x00: return "MULTIPLE PERIPHERAL DEVICES SELECTED"; + } + + break; + case 0x08: + switch(ASCQ) + { + case 0x00: return "LOGICAL UNIT COMMUNICATION FAILURE"; + case 0x01: return "LOGICAL UNIT COMMUNICATION TIME-OUT"; + case 0x02: return "LOGICAL UNIT COMMUNICATION PARITY ERROR"; + case 0x03: return "LOGICAL UNIT COMMUNICATION CRC ERROR"; + case 0x04: return "UNREACHABLE COPY TARGET"; + } + + break; + case 0x09: + switch(ASCQ) + { + case 0x00: return "TRACK FLOLLOWING ERROR"; + case 0x01: return "TRACKING SERVO FAILURE"; + case 0x02: return "FOCUS SERVO FAILURE"; + case 0x03: return "SPINDLE SERVO FAILURE"; + case 0x04: return "HEAD SELECT FAULT"; + case 0x05: return "VIBRATION INDUCED TRACKING ERROR"; + } + + break; + case 0x0A: + switch(ASCQ) + { + case 0x00: return "ERROR LOG OVERFLOW"; + } + + break; + case 0x0B: + switch(ASCQ) + { + case 0x00: return "WARNING"; + case 0x01: return "WARNING - SPECIFIED TEMPERATURE EXCEEDED"; + case 0x02: return "WARNING - ENCLOSURE DEGRADED"; + case 0x03: return "WARNING - BACKGROUND SELF-TEST FAILED"; + case 0x04: return "WARNING - BACKGROUND PRE-SCAN DETECTED MEDIUM ERROR"; + case 0x05: return "WARNING - BACKGROUND MEDIUM SCAN DETECTED MEDIUM ERROR"; + case 0x06: return "WARNING - NON-VOLATILE CACHE NOW VOLATILE"; + case 0x07: return "WARNING - DEGRADED POWER TO NON-VOLATILE CACHE"; + case 0x08: return "WARNING - POWER LOSS EXPECTED"; + case 0x09: return "WARNING - DEVICE STATISTICS NOTIFICATION ACTIVE"; + case 0x0A: return "WARNING - HIGH CRITICAL TEMPERATURE LIMIT EXCEEDED"; + case 0x0B: return "WARNING - LOW CRITICAL TEMPERATURE LIMIT EXCEEDED"; + case 0x0C: return "WARNING - HIGH OPERATING TEMPERATURE LIMIT EXCEEDED"; + case 0x0D: return "WARNING - LOW OPERATING TEMPERATURE LIMIT EXCEEDED"; + case 0x0E: return "WARNING - HIGH CRITICAL HUMIDITY LIMIT EXCEEDED"; + case 0x0F: return "WARNING - LOW CRITICAL HUMIDITY LIMIT EXCEEDED"; + case 0x10: return "WARNING - HIGH OPERATING HUMIDITY LIMIT EXCEEDED"; + case 0x11: return "WARNING - LOW OPERATING HUMIDITY LIMIT EXCEEDED"; + } + + break; + case 0x0C: + switch(ASCQ) + { + case 0x00: return "WRITE ERROR"; + case 0x01: return "WRITE ERROR - RECOVERED WITH AUTO REALLOCATION"; + case 0x02: return "WRITE ERROR - AUTO REALLOCATION FAILED"; + case 0x03: return "WRITE ERROR - RECOMMENDED REASSIGNMENT"; + case 0x04: return "COMPRESSION CHECK MISCOMPARE ERROR"; + case 0x05: return "DATA EXPANSION OCCURRED DURING COMPRESSION"; + case 0x06: return "BLOCK NOT COMPRESSIBLE"; + case 0x07: return "WRITE ERROR - RECOVERY NEEDED"; + case 0x08: return "WRITE ERROR - RECOVERY FAILED"; + case 0x09: return "WRITE ERROR - LOSS OF STREAMING"; + case 0x0A: return "WRITE ERROR - PADDING BLOCKS ADDED"; + case 0x0B: return "AUXILIARY MEMORY WRITE ERROR"; + case 0x0C: return "WRITE ERROR - UNEXPECTED UNSOLICITED DATA"; + case 0x0D: return "WRITE ERROR - NOT ENOUGH UNSOLICITED DATA"; + case 0x0E: return "MULTIPLE WRITE ERRORS"; + case 0x0F: return "DEFECTS IN ERROR WINDOW"; + case 0x10: return "INCOMPLETE MULTIPLE ATOMIC WRITE OPERATIONS"; + case 0x11: return "WRITE ERROR - RECOVERY SCAN NEEDED"; + case 0x12: return "WRITE ERROR - INSUFFICIENT ZONE RESOURCES"; + } + + break; + case 0x0D: + switch(ASCQ) + { + case 0x00: return "ERROR DETECTED BY THIRD PARTY TEMPORARY INITIATOR"; + case 0x01: return "THIRD PARTY DEVICE FAILURE"; + case 0x02: return "COPY TARGET DEVICE NOT REACHABLE"; + case 0x03: return "INCORRECT COPY TARGET DEVICE TYPE"; + case 0x04: return "COPY TARGET DEVICE DATA UNDERRUN"; + case 0x05: return "COPY TARGET DEVICE DATA OVERRUN"; + } + + break; + case 0x0E: + switch(ASCQ) + { + case 0x00: return "INVALID INFORMATION UNIT"; + case 0x01: return "INFORMATION UNIT TOO SHORT"; + case 0x02: return "INFORMATION UNIT TOO LONG"; + case 0x03: return "INVALID FIELD IN COMMAND INFORMATION UNIT"; + } + + break; + case 0x10: + switch(ASCQ) + { + case 0x00: return "ID CRC OR ECC ERROR"; + case 0x01: return "LOGICAL BLOCK GUARD CHECK FAILED"; + case 0x02: return "LOGICAL BLOCK APPLICATION TAG CHECK FAILED"; + case 0x03: return "LOGICAL BLOCK REFERENCE TAG CHECK FAILED"; + case 0x04: return "LOGICAL BLOCK PROTECTION ERROR ON RECOVER BUFFERED DATA"; + case 0x05: return "LOGICAL BLOCK PROTECTION METHOD ERROR"; + } + + break; + case 0x11: + switch(ASCQ) + { + case 0x00: return "UNRECOVERED READ ERROR"; + case 0x01: return "READ RETRIES EXHAUSTED"; + case 0x02: return "ERROR TOO LONG TO CORRECT"; + case 0x03: return "MULTIPLE READ ERRORS"; + case 0x04: return "UNRECOVERED READ ERROR - AUTO REALLOCATE FAILED"; + case 0x05: return "L-EC UNCORRECTABLE ERROR"; + case 0x06: return "CIRC UNRECOVERED ERROR"; + case 0x07: return "DATA RESYNCHRONIZATION ERROR"; + case 0x08: return "INCOMPLETE BLOCK READ"; + case 0x09: return "NO GAP FOUND"; + case 0x0A: return "MISCORRECTED ERROR"; + case 0x0B: return "UNRECOVERED READ ERROR - RECOMMENDED REASSIGNMENT"; + case 0x0C: return "UNRECOVERED READ ERROR - RECOMMENDED REWRITE THE DATA"; + case 0x0D: return "DE-COMPRESSION CRC ERROR"; + case 0x0E: return "CANNOT DECOMPRESS USING DECLARED ALGORITHM"; + case 0x0F: return "ERROR READING UPC/EAN NUMBER"; + case 0x10: return "ERROR READING ISRC NUMBER"; + case 0x11: return "READ ERROR - LOSS OF STREAMING"; + case 0x12: return "AUXILIARY MEMORY READ ERROR"; + case 0x13: return "READ ERROR - FAILED RETRANSMISSITION REQUEST"; + case 0x14: return "READ ERROR - LBA MARKED BAD BY APPLICATION CLIENT"; + case 0x15: return "WRITE AFTER SANITIZE REQUIRED"; + } + + break; + case 0x12: + switch(ASCQ) + { + case 0x00: return "ADDRESS MARK NOT FOUND FOR ID FIELD"; + } + + break; + case 0x13: + switch(ASCQ) + { + case 0x00: return "ADDRESS MARK NOT FOUND FOR DATA FIELD"; + } + + break; + case 0x14: + switch(ASCQ) + { + case 0x00: return "RECORDED ENTITY NOT FOUND"; + case 0x01: return "RECORD NOT FOUND"; + case 0x02: return "FILEMARK OR SETMARK NOT FOUND"; + case 0x03: return "END-OF-DATA NOT FOUND"; + case 0x04: return "BLOCK SEQUENCE ERROR"; + case 0x05: return "RECORD NOT FOUND - RECOMMENDAD REASSIGNMENT"; + case 0x06: return "RECORD NOT FOUND - DATA AUTO-REALLOCATED"; + case 0x07: return "LOCATE OPERATION FAILURE"; + } + + break; + case 0x15: + switch(ASCQ) + { + case 0x00: return "RANDOM POSITIONING ERROR"; + case 0x01: return "MECHANICAL POSITIONING ERROR"; + case 0x02: return "POSITIONING ERROR DETECTED BY READ OF MEDIUM"; + } + + break; + case 0x16: + switch(ASCQ) + { + case 0x00: return "DATA SYNCHRONIZATION MARK ERROR"; + case 0x01: return "DATA SYNC ERROR - DATA REWRITTEN"; + case 0x02: return "DATA SYNC ERROR - RECOMMENDED REWRITE"; + case 0x03: return "DATA SYNC ERROR - DATA AUTO-REALLOCATED"; + case 0x04: return "DATA SYNC ERROR - RECOMMENDED REASSIGNMENT"; + } + + break; + case 0x17: + switch(ASCQ) + { + case 0x00: return "RECOVERED DATA WITH NO ERROR CORRECTION APPLIED"; + case 0x01: return "RECOVERED DATA WITH RETRIES"; + case 0x02: return "RECOVERED DATA WITH POSITIVE HEAD OFFSET"; + case 0x03: return "RECOVERED DATA WITH NEGATIVE HEAD OFFSET"; + case 0x04: return "RECOVERED DATA WITH RETRIES AND/OR CIRC APPLIED"; + case 0x05: return "RECOVERED DATA USING PREVIOUS SECTOR ID"; + case 0x06: return "RECOVERED DATA WITHOUT ECC - DATA AUTO-REALLOCATED"; + case 0x07: return "RECOVERED DATA WITHOUT ECC - RECOMMENDED REASSIGNMENT"; + case 0x08: return "RECOVERED DATA WITHOUT ECC - RECOMMENDED REWRITE"; + case 0x09: return "RECOVERED DATA WITHOUT ECC - DATA REWRITTEN"; + } + + break; + case 0x18: + switch(ASCQ) + { + case 0x00: return "RECOVERED DATA WITH ERROR CORRECTION APPLIED"; + case 0x01: return "RECOVERED DATA WITH ERROR CORRECTION & RETRIES APPLIED"; + case 0x02: return "RECOVERED DATA - DATA AUTO-REALLOCATED"; + case 0x03: return "RECOVERED DATA WITH CIRC"; + case 0x04: return "RECOVERED DATA WITH L-EC"; + case 0x05: return "RECOVERED DATA - RECOMMENDED REASSIGNMENT"; + case 0x06: return "RECOVERED DATA - RECOMMENDED REWRITE"; + case 0x07: return "RECOVERED DATA WITH ECC - DATA REWRITTEN"; + case 0x08: return "RECOVERED DATA WITH LINKING"; + } + + break; + case 0x19: + switch(ASCQ) + { + case 0x00: return "DEFECT LIST ERROR"; + case 0x01: return "DEFECT LIST NOT AVAILABLE"; + case 0x02: return "DEFECT LIST ERROR IN PRIMARY LIST"; + case 0x03: return "DEFECT LIST ERROR IN GROWN LIST"; + } + + break; + case 0x1A: + switch(ASCQ) + { + case 0x00: return "PARAMETER LIST LENGTH ERROR"; + } + + break; + case 0x1B: + switch(ASCQ) + { + case 0x00: return "SYNCHRONOUS DATA TRANSFER ERROR"; + } + + break; + case 0x1C: + switch(ASCQ) + { + case 0x00: return "DEFECT LIST NOT FOUND"; + case 0x01: return "PRIMARY DEFECT LIST NOT FOUND"; + case 0x02: return "GROWN DEFECT LIST NOT FOUND"; + } + + break; + case 0x1D: + switch(ASCQ) + { + case 0x00: return "MISCOMPARE DURING VERIFY OPERATION"; + case 0x01: return "MISCOMPARE VERIFY OF UNMAPPED LBA"; + } + + break; + case 0x1E: + switch(ASCQ) + { + case 0x00: return "RECOVERED ID WITH ECC CORRECTION"; + } + + break; + case 0x1F: + switch(ASCQ) + { + case 0x00: return "PARTIAL DEFECT LIST TRANSFER"; + } + + break; + case 0x20: + switch(ASCQ) + { + case 0x00: return "INVALID COMMAND OPERATION CODE"; + case 0x01: return "ACCESS DENIED - INITIATOR PENDING-ENROLLED"; + case 0x02: return "ACCESS DENIED - NO ACCESS RIGHTS"; + case 0x03: return "ACCESS DENIED - INVALID MGMT ID KEY"; + case 0x04: return "ILLEGAL COMMAND WHILE IN WRITE CAPABLE STATE"; + case 0x05: return "ILLEGAL COMMAND WHILE IN READ CAPABLE STATE"; + case 0x06: return "ILLEGAL COMMAND WHILE IN EXPLICIT ADDRESS MODE"; + case 0x07: return "ILLEGAL COMMAND WHILE IN IMPLICIT ADDRESS MODE"; + case 0x08: return "ACCESS DENIED - ENROLLMENT CONFLICT"; + case 0x09: return "ACCESS DENIED - INVALID LUN IDENTIFIER"; + case 0x0A: return "ACCESS DENIED - INVALID PROXY TOKEN"; + case 0x0B: return "ACCESS DENIED - ACL LUN CONFLICT"; + case 0x0C: return "ILLEGAL COMMAND WHEN NOT IN APPEND-ONLY MODE"; + } + + break; + case 0x21: + switch(ASCQ) + { + case 0x00: return "LOGICAL BLOCK ADDRESS OUT OF RANGE"; + case 0x01: return "INVALID ELEMENT ADDRESS"; + case 0x02: return "INVALID ADDRESS FOR WRITE"; + case 0x03: return "INVALID WRITE CROSSING LAYER JUMP"; + case 0x04: return "UNALIGNED WRITE COMMAND"; + case 0x05: return "WRITE BOUNDARY VIOLATION"; + case 0x06: return "ATTEMPT TO READ INVALID DATA"; + case 0x07: return "READ BOUNDARY VIOLATION"; + } + + break; + case 0x22: + switch(ASCQ) + { + case 0x00: return "ILLEGAL FUNCTION"; + } + + break; + case 0x23: + switch(ASCQ) + { + case 0x00: return "INVALID TOKEN OPERATION, CAUSE NOT REPORTABLE"; + case 0x01: return "INVALID TOKEN OPERATION, UNSUPPORTED TOKEN TYPE"; + case 0x02: return "INVALID TOKEN OPERATION, REMOTE TOKEN USAGE NOT SUPPORTED"; + case 0x03: return "INVALID TOKEN OPERATION, REMOTE ROD TOKEN CREATION NOT SUPPORTED"; + case 0x04: return "INVALID TOKEN OPERATION, TOKEN UNKNOWN"; + case 0x05: return "INVALID TOKEN OPERATION, TOKEN CORRUPT"; + case 0x06: return "INVALID TOKEN OPERATION, TOKEN REVOKED"; + case 0x07: return "INVALID TOKEN OPERATION, TOKEN EXPIRED"; + case 0x08: return "INVALID TOKEN OPERATION, TOKEN CANCELLED"; + case 0x09: return "INVALID TOKEN OPERATION, TOKEN DELETED"; + case 0x0A: return "INVALID TOKEN OPERATION, INVALID TOKEN LENGTH"; + } + + break; + case 0x24: + switch(ASCQ) + { + case 0x00: return "ILLEGAL FIELD IN CDB"; + case 0x01: return "CDB DECRYPTION ERROR"; + case 0x02: return "INVALID CDB FIELD WHILE IN EXPLICIT BLOCK ADDRESS MODEL"; + case 0x03: return "INVALID CDB FIELD WHILE IN IMPLICIT BLOCK ADDRESS MODEL"; + case 0x04: return "SECURITY AUDIT VALUE FROZEN"; + case 0x05: return "SECURITY WORKING KEY FROZEN"; + case 0x06: return "NONCE NOT UNIQUE"; + case 0x07: return "NONCE TIMESTAMP OUT OF RANGE"; + case 0x08: return "INVALID XCDB"; + } + + break; + case 0x25: + switch(ASCQ) + { + case 0x00: return "LOGICAL UNIT NOT SUPPORTED"; + } + + break; + case 0x26: + switch(ASCQ) + { + case 0x00: return "INVALID FIELD IN PARAMETER LIST"; + case 0x01: return "PARAMETER NOT SUPPORTED"; + case 0x02: return "PARAMETER VALUE INVALID"; + case 0x03: return "THRESHOLD PARAMETERS NOT SUPPORTED"; + case 0x04: return "INVALID RELEASE OF PERSISTENT RESERVATION"; + case 0x05: return "DATA DECRYPTION ERROR"; + case 0x06: return "TOO MANY TARGET DESCRIPTORS"; + case 0x07: return "UNSUPPORTED TARGET DESCRIPTOR TYPE CODE"; + case 0x08: return "TOO MANY SEGMENT DESCRIPTORS"; + case 0x09: return "UNSUPPORTED SEGMENT DESCRIPTOR TYPE CODE"; + case 0x0A: return "UNEXPECTED INEXACT SEGMENT"; + case 0x0B: return "INLINE DATA LENGTH EXCEEDED"; + case 0x0C: return "INVALID OPERATION FOR COPY SOURCE OR DESTINATION"; + case 0x0D: return "COPY SEGMENT GRANULARITY VIOLATION"; + case 0x0E: return "INVALID PARAMETER WHILE PORT IS ENABLED"; + case 0x0F: return "INVALID DATA-OUT BUFFER INTEGRITY CHECK VALUE"; + case 0x10: return "DATA DECRYPTION KEY FAIL LIMIT REACHED"; + case 0x11: return "INCOMPLETE KEY-ASSOCIATED DATA SET"; + case 0x12: return "VENDOR SPECIFIC KEY REFERENCE NOT FOUND"; + case 0x13: return "APPLICATION TAG MODE PAGE IS INVALID"; + } + + break; + case 0x27: + switch(ASCQ) + { + case 0x00: return "WRITE PROTECTED"; + case 0x01: return "HARDWARE WRITE PROTECTED"; + case 0x02: return "LOGICAL UNIT SOFTWARE WRITE PROTECTED"; + case 0x03: return "ASSOCIATED WRITE PROTECT"; + case 0x04: return "PERSISTENT WRITE PROTECT"; + case 0x05: return "PERMANENT WRITE PROTECT"; + case 0x06: return "CONDITIONAL WRITE PROTECT"; + case 0x07: return "SPACE ALLOCATION FAILED WRITE PROTECT"; + case 0x08: return "ZONE IS READ ONLY"; + } + + break; + case 0x28: + switch(ASCQ) + { + case 0x00: return "NOT READY TO READY CHANGE (MEDIUM MAY HAVE CHANGED)"; + case 0x01: return "IMPORT OR EXPORT ELEMENT ACCESSED"; + case 0x02: return "FORMAT-LAYER MAY HAVE CHANGED"; + case 0x03: return "IMPORT/EXPORT ELEMENT ACCESSED, MEDIUM CHANGED"; + } + + break; + case 0x29: + switch(ASCQ) + { + case 0x00: return "POWER ON, RESET, OR BUS DEVICE RESET OCCURRED"; + case 0x01: return "POWER ON OCCURRED"; + case 0x02: return "SCSI BUS RESET OCCURRED"; + case 0x03: return "BUS DEVICE RESET FUNCTION OCCURRED"; + case 0x04: return "DEVICE INTERNAL RESET"; + case 0x05: return "TRANSCEIVER MODE CHANGED TO SINGLE-ENDED"; + case 0x06: return "TRANSCEIVER MODE CHANGED TO LVD"; + case 0x07: return "I_T NEXUS LOSS OCCURRED"; + } + + break; + case 0x2A: + switch(ASCQ) + { + case 0x00: return "PARAMETERS CHANGED"; + case 0x01: return "MODE PARAMETERS CHANGED"; + case 0x02: return "LOG PARAMETERS CHANGED"; + case 0x03: return "RESERVATIONS PREEMPTED"; + case 0x04: return "RESERVATIONS RELEASED"; + case 0x05: return "REGISTRATIONS PREEMPTED"; + case 0x06: return "ASYMMETRIC ACCESS STATE CHANGED"; + case 0x07: return "IMPLICIT ASYMMETRIC ACCESS STATE TRANSITION FAILED"; + case 0x08: return "PRIORITY CHANGED"; + case 0x09: return "CAPACITY DATA HAS CHANGED"; + case 0x0A: return "ERROR HISTORY I_T NEXUS CLEARED"; + case 0x0B: return "ERROR HISTORY SNAPSHOT RELEASED"; + case 0x0C: return "ERROR RECOVERY ATTRIBUTES HAVE CHANGED"; + case 0x0D: return "DATA ENCRYPTION CAPABILITIES CHANGED"; + case 0x10: return "TIMESTAMP CHANGED"; + case 0x11: return "DATA ENCRYPTION PARAMETERS CHANGED BY ANOTHER I_T NEXUS"; + case 0x12: return "DATA ENCRYPTION PARAMETERS CHANGED BY VENDOR SPECIFIC EVENT"; + case 0x13: return "DATA ENCRYPTION KEY INSTANCE COUNTER HAS CHANGED"; + case 0x14: return "SA CREATION CAPABILITIES DATA HAS CHANGED"; + case 0x15: return "MEDIUM REMOVAL PREVENTION PREEMPTED"; + } + + break; + case 0x2B: + switch(ASCQ) + { + case 0x00: return "COPY CANNOT EXECUTE SINCE HOST CANNOT DISCONNECT"; + } + + break; + case 0x2C: + switch(ASCQ) + { + case 0x00: return "COMMAND SEQUENCE ERROR"; + case 0x01: return "TOO MANY WINDOWS SPECIFIED"; + case 0x02: return "INVALID COMBINATION OF WINDOWS SPECIFIED"; + case 0x03: return "CURRENT PROGRAM AREA IS NOT EMPTY"; + case 0x04: return "CURRENT PROGRAM AREA IS EMPTY"; + case 0x05: return "ILLEGAL POWER CONDITION REQUEST"; + case 0x06: return "PERSISTENT PREVENT CONFLICT"; + case 0x07: return "PREVIOUS BUSY STATUS"; + case 0x08: return "PREVIOUS TASK SET FULL STATUS"; + case 0x09: return "PREVIOUS RESERVATION CONFLICT STATUS"; + case 0x0A: return "PARTITION OR COLLECTION CONTAINS USER OBJECTS"; + case 0x0B: return "NOT RESERVED"; + case 0x0C: return "ORWRITE GENERATION DOES NOT MATCH"; + case 0x0D: return "RESET WRITE POINTER NOT ALLOWED"; + case 0x0E: return "ZONE IS OFFLINE"; + case 0x0F: return "STREAM NOT OPEN"; + case 0x10: return "UNWRITTEN DATA IN ZONE"; + } + + break; + case 0x2D: + switch(ASCQ) + { + case 0x00: return "OVERWRITE ERROR ON UPDATE IN PLACE"; + } + + break; + case 0x2E: + switch(ASCQ) + { + case 0x00: return "INSUFFICIENT TIME FOR OPERATION"; + case 0x01: return "COMMAND TIMEOUT BEFORE PROCESSING"; + case 0x02: return "COMMAND TIMEOUT DURING PROCESSING"; + case 0x03: return "COMMAND TIMEOUT DURING PROCESSING DUE TO ERROR RECOVERY"; + } + + break; + case 0x2F: + switch(ASCQ) + { + case 0x00: return "COMMANDS CLEARED BY ANOTHER INITIATOR"; + case 0x01: return "COMMANDS CLEARED BY POWER LOSS NOTIFICATION"; + case 0x02: return "COMMANDS CLEARED BY DEVICE SERVER"; + case 0x03: return "SOME COMMANDS CLEARED BY QUEUING LAYER EVENT"; + } + + break; + case 0x30: + switch(ASCQ) + { + case 0x00: return "INCOMPATIBLE MEDIUM INSTALLED"; + case 0x01: return "CANNOT READ MEDIUM - UNKNOWN FORMAT"; + case 0x02: return "CANNOT READ MEDIUM - INCOMPATIBLE FORMAT"; + case 0x03: return "CLEANING CARTRIDGE INSTALLED"; + case 0x04: return "CANNOT WRITE MEDIUM - UNKNOWN FORMAT"; + case 0x05: return "CANNOT WRITE MEDIUM - INCOMPATIBLE FORMAT"; + case 0x06: return "CANNOT FORMAT MEDIUM - INCOMPATIBLE MEDIUM"; + case 0x07: return "CLEANING FAILURE"; + case 0x08: return "CANNOT WRITE - APPLICATION CODE MISMATCH"; + case 0x09: return "CURRENT SESSION NOT FIXATED FOR APPEND"; + case 0x0A: return "CLEANING REQUEST REJECTED"; + case 0x0C: return "WORM MEDIUM - OVERWRITE ATTEMPTED"; + case 0x0D: return "WORM MEDIUM - INTEGRITY CHECK"; + case 0x10: return "MEDIUM NOT FORMATTED"; + case 0x11: return "INCOMPATIBLE VOLUME TYPE"; + case 0x12: return "INCOMPATIBLE VOLUME QUALIFIER"; + case 0x13: return "CLEANING VOLUME EXPIRED"; + } + + break; + case 0x31: + switch(ASCQ) + { + case 0x00: return "MEDIUM FORMAT CORRUPTED"; + case 0x01: return "FORMAT COMMAND FAILED"; + case 0x02: return "ZONED FORMATTING FAILED DUE TO SPARE LINKING"; + case 0x03: return "SANITIZE COMMAND FAILED"; + } + + break; + case 0x32: + switch(ASCQ) + { + case 0x00: return "NO DEFECT SPARE LOCATION AVAILABLE"; + case 0x01: return "DEFECT LIST UPDATE FAILURE"; + } + + break; + case 0x33: + switch(ASCQ) + { + case 0x00: return "TAPE LENGTH ERROR"; + } + + break; + case 0x34: + switch(ASCQ) + { + case 0x00: return "ENCLOSURE FAILURE"; + } + + break; + case 0x35: + switch(ASCQ) + { + case 0x00: return "ENCLOSURE SERVICES FAILURE"; + case 0x01: return "UNSUPPORTED ENCLOSURE FUNCTION"; + case 0x02: return "ENCLOSURE SERVICES UNAVAILABLE"; + case 0x03: return "ENCLOSURE SERVICES TRANSFER FAILURE"; + case 0x04: return "ENCLOSURE SERVICES TRANSFER REFUSED"; + case 0x05: return "ENCLOSURE SERVICES CHECKSUM ERROR"; + } + + break; + case 0x36: + switch(ASCQ) + { + case 0x00: return "RIBBON, INK, OR TONER FAILURE"; + } + + break; + case 0x37: + switch(ASCQ) + { + case 0x00: return "ROUNDED PARAMETER"; + } + + break; + case 0x38: + switch(ASCQ) + { + case 0x00: return "EVENT STATUS NOTIFICATION"; + case 0x02: return "ESN - POWER MANAGEMENT CLASS EVENT"; + case 0x04: return "ESN - MEDIA CLASS EVENT"; + case 0x06: return "ESN - DEVICE BUSY CLASS EVENT"; + case 0x07: return "THIN PROVISIONING SOFT THRESHOLD REACHED"; + } + + break; + case 0x39: + switch(ASCQ) + { + case 0x00: return "SAVING PARAMETERS NOT SUPPORTED"; + } + + break; + case 0x3A: + switch(ASCQ) + { + case 0x00: return "MEDIUM NOT PRESENT"; + case 0x01: return "MEDIUM NOT PRESENT - TRAY CLOSED"; + case 0x02: return "MEDIUM NOT PRESENT - TRAY OPEN"; + case 0x03: return "MEDIUM NOT PRESENT - LOADABLE"; + case 0x04: return "MEDIUM NOT PRESENT - MEDIUM AUXILIARY MEMORY ACCESSIBLE"; + } + + break; + case 0x3B: + switch(ASCQ) + { + case 0x00: return "SEQUENTIAL POSITIONING ERROR"; + case 0x01: return "TAPE POSITION ERROR AT BEGINNING-OF-MEDIUM"; + case 0x02: return "TAPE POSITION ERROR AT END-OF-MEDIUM"; + case 0x03: return "TAPE OR ELECTRONIC VERTICAL FORMS UNIT NOT READY"; + case 0x04: return "SLEW FAILURE"; + case 0x05: return "PAPER JAM"; + case 0x06: return "FAILED TO SENSE TOP-OF-FORM"; + case 0x07: return "FAILED TO SENSE BOTTOM-OF-FORM"; + case 0x08: return "REPOSITION ERROR"; + case 0x09: return "READ PAST END OF MEDIUM"; + case 0x0A: return "READ PAST BEGINNING OF MEDIUM"; + case 0x0B: return "POSITION PAST END OF MEDIUM"; + case 0x0C: return "POSITION PAST BEGINNING OF MEDIUM"; + case 0x0D: return "MEDIUM DESTINATION ELEMENT FULL"; + case 0x0E: return "MEDIUM SOURCE ELEMENT EMPTY"; + case 0x0F: return "END OF MEDIUM REACHED"; + case 0x11: return "MEDIUM MAGAZINE NOT ACCESSIBLE"; + case 0x12: return "MEDIUM MAGAZINE REMOVED"; + case 0x13: return "MEDIUM MAGAZINE INSERTED"; + case 0x14: return "MEDIUM MAGAZINE LOCKED"; + case 0x15: return "MEDIUM MAGAZINE UNLOCKED"; + case 0x16: return "MECHANICAL POSITIONING OR CHANGER ERROR"; + case 0x17: return "READ PAST END OF USER OBJECT"; + case 0x18: return "ELEMENT DISABLED"; + case 0x19: return "ELEMENT ENABLED"; + case 0x1A: return "DATA TRANSFER DEVICE REMOVED"; + case 0x1B: return "DATA TRANSFER DEVICE INSERTED"; + case 0x1C: return "TOO MANY LOGICAL OBJECTS ON PARTITION TO SUPPORT OPERATION"; + } + + break; + case 0x3D: + switch(ASCQ) + { + case 0x00: return "INVALID BITS IN IDENTIFY MESSAGE"; + } + + break; + case 0x3E: + switch(ASCQ) + { + case 0x00: return "LOGICAL UNIT HAS NOT SELF-CONFIGURED YET"; + case 0x01: return "LOGICAL UNIT FAILURE"; + case 0x02: return "TIMEOUT ON LOGICAL UNIT"; + case 0x03: return "LOGICAL UNIT FAILED SELF-TEST"; + case 0x04: return "LOGICAL UNIT UNABLE TO UPDATE SELF-TEST LOG"; + } + + break; + case 0x3F: + switch(ASCQ) + { + case 0x00: return "TARGET OPERATING CONDITIONS HAVE CHANGED"; + case 0x01: return "MICROCODE HAS BEEN CHANGED"; + case 0x02: return "CHANGED OPERATING DEFINITION"; + case 0x03: return "INQUIRY DATA HAS CHANGED"; + case 0x04: return "COMPONENT DEVICE ATTACHED"; + case 0x05: return "DEVICE IDENTIFIED CHANGED"; + case 0x06: return "REDUNDANCY GROUP CREATED OR MODIFIED"; + case 0x07: return "REDUNDANCY GROUP DELETED"; + case 0x08: return "SPARE CREATED OR MODIFIED"; + case 0x09: return "SPARE DELETED"; + case 0x0A: return "VOLUME SET CREATED OR MODIFIED"; + case 0x0B: return "VOLUME SET DELETED"; + case 0x0C: return "VOLUME SET DEASSIGNED"; + case 0x0D: return "VOLUME SET REASSIGNED"; + case 0x0E: return "REPORTED LUNS DATA HAS CHANGED"; + case 0x0F: return "ECHO BUFFER OVERWRITTEN"; + case 0x10: return "MEDIUM LOADABLE"; + case 0x11: return "MEDIUM AUXILIARY MEMORY ACCESSIBLE"; + case 0x12: return "iSCSI IP ADDRESS ADDED"; + case 0x13: return "iSCSI IP ADDRESS REMOVED"; + case 0x14: return "iSCSI IP ADDRESS CHANGED"; + case 0x15: return "INSPECT REFERRALS SENSE DESCRIPTORS"; + case 0x16: return "MICROCODE HAS BEEN CHANGED WITHOUT RESET"; + case 0x17: return "ZONE TRANSITION TO FULL"; + } + + break; + case 0x40: + switch(ASCQ) + { + case 0x00: return "RAM FAILURE"; + default: return $"DIAGNOSTIC FAILURE ON COMPONENT {ASCQ:X2}h"; + } + case 0x41: + switch(ASCQ) + { + case 0x00: return "DATA PATH FAILURE"; + } + + break; + case 0x42: + switch(ASCQ) + { + case 0x00: return "POWER-ON OR SELF-TEST FAILURE"; + } + + break; + case 0x43: + switch(ASCQ) + { + case 0x00: return "MESSAGE ERROR"; + } + + break; + case 0x44: + switch(ASCQ) + { + case 0x00: return "INTERNAL TARGET FAILURE"; + case 0x01: return "PERSISTENT RESERVATION INFORMATION LOST"; + case 0x71: return "ATA DEVICE FAILED SET FEATURES"; + } + + break; + case 0x45: + switch(ASCQ) + { + case 0x00: return "SELECT OR RESELECT FAILURE"; + } + + break; + case 0x46: + switch(ASCQ) + { + case 0x00: return "UNSUCCESSFUL SOFT RESET"; + } + + break; + case 0x47: + switch(ASCQ) + { + case 0x00: return "SCSI PARITY ERROR"; + case 0x01: return "DATA PHASE CRC ERROR DETECTED"; + case 0x02: return "SCSI PARITY ERROR DETECTED DURING ST DATA PHASE"; + case 0x03: return "INFORMATION UNIT iuCRC ERROR DETECTED"; + case 0x04: return "ASYNCHRONOUS INFORMATION PROTECTION ERROR DETECTED"; + case 0x05: return "PROTOCOL SERVICE CRC ERROR"; + case 0x06: return "PHY TEST FUNCTION IN PROGRESS"; + case 0x7F: return "SOME COMMANDS CLEARED BY iSCSI PROTOCOL EVENT"; + } + + break; + case 0x48: + switch(ASCQ) + { + case 0x00: return "INITIATOR DETECTED ERROR MESSAGE RECEIVED"; + } + + break; + case 0x49: + switch(ASCQ) + { + case 0x00: return "INVALID MESSAGE ERROR"; + } + + break; + case 0x4A: + switch(ASCQ) + { + case 0x00: return "COMMAND PHASE ERROR"; + } + + break; + case 0x4B: + switch(ASCQ) + { + case 0x00: return "DATA PHASE ERROR"; + case 0x01: return "INVALID TARGET PORT TRANSFER TAG RECEIVED"; + case 0x02: return "TOO MUCH WRITE DATA"; + case 0x03: return "ACK/NAK TIMEOUT"; + case 0x04: return "NAK RECEIVED"; + case 0x05: return "DATA OFFSET ERROR"; + case 0x06: return "INITIATOR RESPONSE TIMEOUT"; + case 0x07: return "CONNECTION LOST"; + case 0x08: return "DATA-IN BUFFER OVERFLOW - DATA BUFFER SIZE"; + case 0x09: return "DATA-IN BUFFER OVERFLOW - DATA BUFFER DESCRIPTOR AREA"; + case 0x0A: return "DATA-IN BUFFER ERROR"; + case 0x0B: return "DATA-OUT BUFFER OVERFLOW - DATA BUFFER SIZE"; + case 0x0C: return "DATA-OUT BUFFER OVERFLOW - DATA BUFFER DESCRIPTOR AREA"; + case 0x0D: return "DATA-OUT BUFFER ERROR"; + case 0x0E: return "PCIe FABRIC ERROR"; + case 0x0F: return "PCIe COMPLETION TIMEOUT"; + case 0x10: return "PCIe COMPLETION ABORT"; + case 0x11: return "PCIe POISONED TLP RECEIVED"; + case 0x12: return "PCIe ECRC CHECK FAILED"; + case 0x13: return "PCIe UNSUPPORTED REQUEST"; + case 0x14: return "PCIe ACS VIOLATION"; + case 0x15: return "PCIe TLP PREFIX BLOCKED"; + } + + break; + case 0x4C: + switch(ASCQ) + { + case 0x00: return "LOGICAL UNIT FAILED SELF-CONFIGURATION"; + } + + break; + case 0x4E: return $"OVERLAPPED COMMANDS ATTEMPTED FOR TASK TAG {ASCQ:X2}h"; + case 0x50: + switch(ASCQ) + { + case 0x00: return "WRITE APPEND ERROR"; + case 0x01: return "WRITE APPEND POSITION ERROR"; + case 0x02: return "POSITION ERROR RELATED TO TIMING"; + } + + break; + case 0x51: + switch(ASCQ) + { + case 0x00: return "ERASE FAILURE"; + case 0x01: return "ERASE FAILURE - INCOMPLETE ERASE OPERATION DETECTED"; + } + + break; + case 0x52: + switch(ASCQ) + { + case 0x00: return "CARTRIDGE FAULT"; + } + + break; + case 0x53: + switch(ASCQ) + { + case 0x00: return "MEDIA LOAD OR EJECT FAILED"; + case 0x01: return "UNLOAD TAPE FAILURE"; + case 0x02: return "MEDIUM REMOVAL PREVENTED"; + case 0x03: return "MEDIUM REMOVAL PREVENTED BY DATA TRANSFER ELEMENT"; + case 0x04: return "MEDIUM THREAD OR UNTHREAD FAILURE"; + case 0x05: return "VOLUME IDENTIFIER INVALID"; + case 0x06: return "VOLUME IDENTIFIED MISSING"; + case 0x07: return "DUPLICATE VOLUME IDENTIFIER"; + case 0x08: return "ELEMENT STATUS UNKNOWN"; + case 0x09: return "DATA TRANSFER DEVICE ERROR - LOAD FAILED"; + case 0x0A: return "DATA TRANSFER DEVICE ERROR - UNLOAD FAILED"; + case 0x0B: return "DATA TRANSFER DEVICE ERROR - UNLOAD MISSING"; + case 0x0C: return "DATA TRANSFER DEVICE ERROR - EJECT FAILED"; + case 0x0D: return "DATA TRANSFER DEVICE ERROR - LIBRARY COMMUNICATION FAILED"; + } + + break; + case 0x54: + switch(ASCQ) + { + case 0x00: return "SCSI TO HOST SYSTEM INTERFACE FAILURE"; + } + + break; + case 0x55: + switch(ASCQ) + { + case 0x00: return "SYSTEM RESOURCE FAILURE"; + case 0x01: return "SYSTEM BUFFER FULL"; + case 0x02: return "INSUFFICIENT RESERVATION RESOURCES"; + case 0x03: return "INSUFFICIENT RESOURCES"; + case 0x04: return "INSUFFICIENT REGISTRATION RESOURCES"; + case 0x05: return "INSUFFICIENT ACCESS CONTROL RESOURCES"; + case 0x06: return "AUXILIARY MEMORY OUT OF SPACE"; + case 0x07: return "QUOTA ERROR"; + case 0x08: return "MAXIMUM NUMBER OF SUPPLEMENTAL DECRYPTION KEYS EXCEEDED"; + case 0x09: return "MEDIUM AUXILIARY MEMORY NOT ACCESSIBLE"; + case 0x0A: return "DATA CURRENTLY UNAVAILABLE"; + case 0x0B: return "INSUFFICIENT POWER FOR OPERATION"; + case 0x0C: return "INSUFFICIENT RESOURCES TO CREATE ROD"; + case 0x0D: return "INSUFFICIENT RESOURCES TO CREATE ROD TOKEN"; + case 0x0E: return "INSUFFICIENT ZONE RESOURCES"; + case 0x0F: return "INSUFFICIENT ZONE RESOURCES TO COMPLETE WRITE"; + case 0x10: return "MAXIMUM NUMBER OF STREAMS OPEN"; + } + + break; + case 0x57: + switch(ASCQ) + { + case 0x00: return "UNABLE TO RECOVER TABLE-OF-CONTENTS"; + } + + break; + case 0x58: + switch(ASCQ) + { + case 0x00: return "GENERATION DOES NOT EXIST"; + } + + break; + case 0x59: + switch(ASCQ) + { + case 0x00: return "UPDATED BLOCK READ"; + } + + break; + case 0x5A: + switch(ASCQ) + { + case 0x00: return "OPERATOR REQUEST OR STATE CHANGE INPUT"; + case 0x01: return "OPERATOR MEDIUM REMOVAL REQUEST"; + case 0x02: return "OPERATOR SELECTED WRITE PROTECT"; + case 0x03: return "OPERATOR SELECTED WRITE PERMIT"; + } + + break; + case 0x5B: + switch(ASCQ) + { + case 0x00: return "LOG EXCEPTION"; + case 0x01: return "THRESHOLD CONDITION MET"; + case 0x02: return "LOG COUNTER AT MAXIMUM"; + case 0x03: return "LOG LIST CODES EXHAUSTED"; + } + + break; + case 0x5C: + switch(ASCQ) + { + case 0x00: return "RPL STATUS CHANGE"; + case 0x01: return "SPINDLES SYNCHRONIZED"; + case 0x02: return "SPINDLES NOT SYNCHRONIZED"; + case 0x03: return "SPARE AREA EXHAUSTION PREDICTION THRESHOLD EXCEEDED"; + case 0x10: return "HARDWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"; + case 0x11: return "HARDWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"; + case 0x12: return "HARDWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH"; + case 0x13: return "HARDWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"; + case 0x14: return "HARDWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"; + case 0x15: return "HARDWARE IMPENDING FAILURE ACCESS TIME TOO HIGH"; + case 0x16: return "HARDWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH"; + case 0x17: return "HARDWARE IMPENDING FAILURE CHANNEL PARAMETRICS"; + case 0x18: return "HARDWARE IMPENDING FAILURE CONTROLLER DETECTED"; + case 0x19: return "HARDWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE"; + case 0x1A: return "HARDWARE IMPENDING FAILURE SEEK TIME PERFORMANCE"; + case 0x1B: return "HARDWARE IMPENDING FAILURE SPIN-UP RETRY COUNT"; + case 0x1C: return "HARDWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"; + case 0x20: return "CONTROLLER IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"; + case 0x21: return "CONTROLLER IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"; + case 0x22: return "CONTROLLER IMPENDING FAILURE DATA ERROR RATE TOO HIGH"; + case 0x23: return "CONTROLLER IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"; + case 0x24: return "CONTROLLER IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"; + case 0x25: return "CONTROLLER IMPENDING FAILURE ACCESS TIME TOO HIGH"; + case 0x26: return "CONTROLLER IMPENDING FAILURE START UNIT TIMES TOO HIGH"; + case 0x27: return "CONTROLLER IMPENDING FAILURE CHANNEL PARAMETRICS"; + case 0x28: return "CONTROLLER IMPENDING FAILURE CONTROLLER DETECTED"; + case 0x29: return "CONTROLLER IMPENDING FAILURE THROUGHPUT PERFORMANCE"; + case 0x2A: return "CONTROLLER IMPENDING FAILURE SEEK TIME PERFORMANCE"; + case 0x2B: return "CONTROLLER IMPENDING FAILURE SPIN-UP RETRY COUNT"; + case 0x2C: return "CONTROLLER IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"; + case 0x30: return "DATA CHANNEL IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"; + case 0x31: return "DATA CHANNEL IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"; + case 0x32: return "DATA CHANNEL IMPENDING FAILURE DATA ERROR RATE TOO HIGH"; + case 0x33: return "DATA CHANNEL IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"; + case 0x34: return "DATA CHANNEL IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"; + case 0x35: return "DATA CHANNEL IMPENDING FAILURE ACCESS TIME TOO HIGH"; + case 0x36: return "DATA CHANNEL IMPENDING FAILURE START UNIT TIMES TOO HIGH"; + case 0x37: return "DATA CHANNEL IMPENDING FAILURE CHANNEL PARAMETRICS"; + case 0x38: return "DATA CHANNEL IMPENDING FAILURE DATA CHANNEL DETECTED"; + case 0x39: return "DATA CHANNEL IMPENDING FAILURE THROUGHPUT PERFORMANCE"; + case 0x3A: return "DATA CHANNEL IMPENDING FAILURE SEEK TIME PERFORMANCE"; + case 0x3B: return "DATA CHANNEL IMPENDING FAILURE SPIN-UP RETRY COUNT"; + case 0x3C: return "DATA CHANNEL IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"; + case 0x40: return "SERVO IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"; + case 0x41: return "SERVO IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"; + case 0x42: return "SERVO IMPENDING FAILURE DATA ERROR RATE TOO HIGH"; + case 0x43: return "SERVO IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"; + case 0x44: return "SERVO IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"; + case 0x45: return "SERVO IMPENDING FAILURE ACCESS TIME TOO HIGH"; + case 0x46: return "SERVO IMPENDING FAILURE START UNIT TIMES TOO HIGH"; + case 0x47: return "SERVO IMPENDING FAILURE CHANNEL PARAMETRICS"; + case 0x48: return "SERVO IMPENDING FAILURE SERVO DETECTED"; + case 0x49: return "SERVO IMPENDING FAILURE THROUGHPUT PERFORMANCE"; + case 0x4A: return "SERVO IMPENDING FAILURE SEEK TIME PERFORMANCE"; + case 0x4B: return "SERVO IMPENDING FAILURE SPIN-UP RETRY COUNT"; + case 0x4C: return "SERVO IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"; + case 0x50: return "SPINDLE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"; + case 0x51: return "SPINDLE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"; + case 0x52: return "SPINDLE IMPENDING FAILURE DATA ERROR RATE TOO HIGH"; + case 0x53: return "SPINDLE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"; + case 0x54: return "SPINDLE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"; + case 0x55: return "SPINDLE IMPENDING FAILURE ACCESS TIME TOO HIGH"; + case 0x56: return "SPINDLE IMPENDING FAILURE START UNIT TIMES TOO HIGH"; + case 0x57: return "SPINDLE IMPENDING FAILURE CHANNEL PARAMETRICS"; + case 0x58: return "SPINDLE IMPENDING FAILURE SPINDLE DETECTED"; + case 0x59: return "SPINDLE IMPENDING FAILURE THROUGHPUT PERFORMANCE"; + case 0x5A: return "SPINDLE IMPENDING FAILURE SEEK TIME PERFORMANCE"; + case 0x5B: return "SPINDLE IMPENDING FAILURE SPIN-UP RETRY COUNT"; + case 0x5C: return "SPINDLE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"; + case 0x60: return "FIRMWARE IMPENDING FAILURE GENERAL HARD DRIVE FAILURE"; + case 0x61: return "FIRMWARE IMPENDING FAILURE DRIVE ERROR RATE TOO HIGH"; + case 0x62: return "FIRMWARE IMPENDING FAILURE DATA ERROR RATE TOO HIGH"; + case 0x63: return "FIRMWARE IMPENDING FAILURE SEEK ERROR RATE TOO HIGH"; + case 0x64: return "FIRMWARE IMPENDING FAILURE TOO MANY BLOCK REASSIGNS"; + case 0x65: return "FIRMWARE IMPENDING FAILURE ACCESS TIME TOO HIGH"; + case 0x66: return "FIRMWARE IMPENDING FAILURE START UNIT TIMES TOO HIGH"; + case 0x67: return "FIRMWARE IMPENDING FAILURE CHANNEL PARAMETRICS"; + case 0x68: return "FIRMWARE IMPENDING FAILURE FIRMWARE DETECTED"; + case 0x69: return "FIRMWARE IMPENDING FAILURE THROUGHPUT PERFORMANCE"; + case 0x6A: return "FIRMWARE IMPENDING FAILURE SEEK TIME PERFORMANCE"; + case 0x6B: return "FIRMWARE IMPENDING FAILURE SPIN-UP RETRY COUNT"; + case 0x6C: return "FIRMWARE IMPENDING FAILURE DRIVE CALIBRATION RETRY COUNT"; + case 0xFF: return "FAILURE PREDICTION THRESHOLD EXCEEDED (FALSE)"; + } + + break; + case 0x5E: + switch(ASCQ) + { + case 0x00: return "LOW POWER CONDITION ON"; + case 0x01: return "IDLE CONDITION ACTIVATED BY TIMER"; + case 0x02: return "STANDBY CONDITION ACTIVATED BY TIMER"; + case 0x03: return "IDLE CONDITION ACTIVATED BY COMMAND"; + case 0x04: return "STANDBY CONDITION ACTIVATED BY COMMAND"; + case 0x05: return "IDLE_B CONDITION ACTIVATED BY TIMER"; + case 0x06: return "IDLE_B CONDITION ACTIVATED BY COMMAND"; + case 0x07: return "IDLE_C CONDITION ACTIVATED BY TIMER"; + case 0x08: return "IDLE_C CONDITION ACTIVATED BY COMMAND"; + case 0x09: return "STANDBY_Y CONDITION ACTIVATED BY TIMER"; + case 0x0A: return "STANDBY_Y CONDITION ACTIVATED BY COMMAND"; + case 0x41: return "POWER STATE CHANGED TO ACTIVE"; + case 0x42: return "POWER STATE CHANGED TO IDLE"; + case 0x43: return "POWER STATE CHANGED TO STANDBY"; + case 0x45: return "POWER STATE CHANGED TO SLEEP"; + case 0x47: return "POWER STATE CHANGED TO DEVICE CONTROL"; + } + + break; + case 0x60: + switch(ASCQ) + { + case 0x00: return "LAMP FAILURE"; + } + + break; + case 0x61: + switch(ASCQ) + { + case 0x00: return "VIDEO ACQUISTION ERROR"; + case 0x01: return "UNABLE TO ACQUIRE VIDEO"; + case 0x02: return "OUT OF FOCUS"; + } + + break; + case 0x62: + switch(ASCQ) + { + case 0x00: return "SCAN HEAD POSITIONING ERROR"; + } + + break; + case 0x63: + switch(ASCQ) + { + case 0x00: return "END OF USER AREA ENCOUNTERED ON THIS TRACK"; + case 0x01: return "PACKET DOES NOT FIT IN AVAILABLE SPACE"; + } + + break; + case 0x64: + switch(ASCQ) + { + case 0x00: return "ILLEGAL MODE FOR THIS TRACK"; + case 0x01: return "INVALID PACKET SIZE"; + } + + break; + case 0x65: + switch(ASCQ) + { + case 0x00: return "VOLTAGE FAULT"; + } + + break; + case 0x66: + switch(ASCQ) + { + case 0x00: return "AUTOMATIC DOCUMENT FEEDER COVER UP"; + case 0x01: return "AUTOMATIC DOCUMENT FEEDER LIFT UP"; + case 0x02: return "DOCUMENT JAM IN AUTOMATIC DOCUMENT FEEDER"; + case 0x03: return "DOCUMENT MISS FEED AUTOMATIC IN DOCUMENT FEEDER"; + } + + break; + case 0x67: + switch(ASCQ) + { + case 0x00: return "CONFIGURATION FAILURE"; + case 0x01: return "CONFIGURATION OF INCAPABLE LOGICAL UNITS FAILED"; + case 0x02: return "ADD LOGICAL UNIT FAILED"; + case 0x03: return "MODIFICATION OF LOGICAL UNIT FAILED"; + case 0x04: return "EXCHANGE OF LOGICAL UNIT FAILED"; + case 0x05: return "REMOVE OF LOGICAL UNIT FAILED"; + case 0x06: return "ATTACHMENT OF LOGICAL UNIT FAILED"; + case 0x07: return "CREATION OF LOGICAL UNIT FAILED"; + case 0x08: return "ASSIGN FAILURE OCCURRED"; + case 0x09: return "MULTIPLY ASSIGNED LOGICAL UNIT"; + case 0x0A: return "SET TARGET PORT GROUPS COMMAND FAILED"; + case 0x0B: return "ATA DEVICE FEATURE NOT ENABLED"; + } + + break; + case 0x68: + switch(ASCQ) + { + case 0x00: return "LOGICAL UNIT NOT CONFIGURED"; + case 0x01: return "SUBSIDIARY LOGICAL UNIT NOT CONFIGURED"; + } + + break; + case 0x69: + switch(ASCQ) + { + case 0x00: return "DATA LOSS ON LOGICAL UNIT"; + case 0x01: return "MULTIPLE LOGICAL UNIT FAILURES"; + case 0x02: return "PARITY/DATA MISMATCH"; + } + + break; + case 0x6A: + switch(ASCQ) + { + case 0x00: return "INFORMATIONAL, REFER TO LOG"; + } + + break; + case 0x6B: + switch(ASCQ) + { + case 0x00: return "STATE CHANGE HAS OCCURRED"; + case 0x01: return "REDUNDANCY LEVEL GOT BETTER"; + case 0x02: return "REDUNDANCY LEVEL GOT WORSE"; + } + + break; + case 0x6C: + switch(ASCQ) + { + case 0x00: return "REBUILD FAILURE OCCURRED"; + } + + break; + case 0x6D: + switch(ASCQ) + { + case 0x00: return "RECALCULATE FAILURE OCCURRED"; + } + + break; + case 0x6E: + switch(ASCQ) + { + case 0x00: return "COMMAND TO LOGICAL UNIT FAILED"; + } + + break; + case 0x6F: + switch(ASCQ) + { + case 0x00: return "COPY PROTECTION KEY EXCHANGE FAILURE - AUTHENTICATION FAILURE"; + case 0x01: return "COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT PRESENT"; + case 0x02: return "COPY PROTECTION KEY EXCHANGE FAILURE - KEY NOT ESTABLISHED"; + case 0x03: return "READ OF SCRAMBLED SECTOR WITHOUT AUTHENTICATION"; + case 0x04: return "MEDIA REGION CODE IS MISMATCHED TO LOGICAL UNIT REGION"; + case 0x05: return "DRIVE REGION MUST BE PERMANENT/REGION RESET COUNT ERROR"; + case 0x06: return "INSUFFICIENT BLOCK COUNT FOR BINDING NONCE RECORDING"; + case 0x07: return "CONFLICT IN BINDING NONCE RECORDING"; + } + + break; + case 0x70: return $"DECOMPRESSION EXCEPTION SHORT ALGORITHM ID OF {ASCQ:X2}h"; + case 0x71: + switch(ASCQ) + { + case 0x00: return "DECOMPRESSIONG EXCEPTION LONG ALGORITHM ID"; + } + + break; + case 0x72: + switch(ASCQ) + { + case 0x00: return "SESSION FIXATION ERROR"; + case 0x01: return "SESSION FIXATION ERROR WRITING LEAD-IN"; + case 0x02: return "SESSION FIXATION ERROR WRITING LEAD-OUT"; + case 0x03: return "SESSION FIXATION ERROR - INCOMPLETE TRACK IN SESSION"; + case 0x04: return "EMPTY OR PARTIALLY WRITTEN RESERVED TRACK"; + case 0x05: return "NO MORE TRACK RESERVATIONS ALLOWED"; + case 0x06: return "RMZ EXTENSION IS NOT ALLOWED"; + case 0x07: return "NO MORE TEST ZONE EXTENSIONS ARE ALLOWED"; + } + + break; + case 0x73: + switch(ASCQ) + { + case 0x00: return "CD CONTROL ERROR"; + case 0x01: return "POWER CALIBRATION AREA ALMOST FULL"; + case 0x02: return "POWER CALIBRATION AREA IS FULL"; + case 0x03: return "POWER CALIBRATION AREA ERROR"; + case 0x04: return "PROGRAM MEMORY AREA UPDATE FAILURE"; + case 0x05: return "PROGRAM MEMORY AREA IS FULL"; + case 0x06: return "RMA/PMA IS ALMOST FULL"; + case 0x10: return "CURRENT POWER CALIBRATION AREA ALMOST FULL"; + case 0x11: return "CURRENT POWER CALIBRATION AREA IS FULL"; + case 0x17: return "RDZ IS FULL"; + } + + break; + case 0x74: + switch(ASCQ) + { + case 0x00: return "SECURITY ERROR"; + case 0x01: return "UNABLE TO DECRYPT DATA"; + case 0x02: return "UNENCRYPTED DATA ENCOUNTERED WHILE DECRYPTING"; + case 0x03: return "INCORRECT DATA ENCRYPTION KEY"; + case 0x04: return "CRYPTOGRAPHIC INTEGRITY VALIDATION FAILED"; + case 0x05: return "ERROR DECRYPTING DATA"; + case 0x06: return "UNKNOWN SIGNATURE VERIFICATION KEY"; + case 0x07: return "ENCRYPTION PARAMETERS NOT USEABLE"; + case 0x08: return "DIGITAL SIGNATURE VALIDATION FAILURE"; + case 0x09: return "ENCRYPTION MODE MISMATCH ON READ"; + case 0x0A: return "ENCRYPTED BLOCK NOT RAW READ ENABLED"; + case 0x0B: return "INCORRECT ENCRYPTION PARAMETERS"; + case 0x0C: return "UNABLE TO DECRYPT PARAMETER LIST"; + case 0x0D: return "ENCRYPTION ALGORITHM DISABLED"; + case 0x10: return "SA CREATION PARAMETER VALUE INVALID"; + case 0x11: return "SA CREATION PARAMETER VALUE REJECTED"; + case 0x12: return "INVALID SA USAGE"; + case 0x21: return "DATA ENCRYPTION CONFIGURATION PREVENTED"; + case 0x30: return "SA CREATION PARAMETER NOT SUPPORTED"; + case 0x40: return "AUTHENTICATION FAILED"; + case 0x61: return "EXTERNAL DATA ENCRYPTION KEY MANAGER ACCESS ERROR"; + case 0x62: return "EXTERNAL DATA ENCRYPTION KEY MANAGER ERROR"; + case 0x63: return "EXTERNAL DATA ENCRYPTION KEY NOT FOUND"; + case 0x64: return "EXTERNAL DATA ENCRYPTION REQUEST NOT AUTHORIZED"; + case 0x6E: return "EXTERNAL DATA ENCRYPTION CONTROL TIMEOUT"; + case 0x6F: return "EXTERNAL DATA ENCRYPTION CONTROL ERROR"; + case 0x71: return "LOGICAL UNIT ACCESS NOT AUTHORIZED"; + case 0x79: return "SECURITY CONFLICT IN TRANSLATED DEVICE"; + } + + break; + } + + return ASC >= 0x80 + ? ASCQ >= 0x80 + ? $"VENDOR-SPECIFIC ASC {ASC:X2}h WITH VENDOR-SPECIFIC ASCQ {ASCQ:X2}h" + : $"VENDOR-SPECIFIC ASC {ASC:X2}h WITH ASCQ {ASCQ:X2}h" + : ASCQ >= 0x80 + ? $"ASC {ASC:X2}h WITH VENDOR-SPECIFIC ASCQ {ASCQ:X2}h" + : $"ASC {ASC:X2}h WITH ASCQ {ASCQ:X2}h"; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/Types.cs b/Aaru.Decoders/SCSI/Types.cs new file mode 100644 index 000000000..f53717f87 --- /dev/null +++ b/Aaru.Decoders/SCSI/Types.cs @@ -0,0 +1,587 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Types.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Contains various SCSI type values. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Diagnostics.CodeAnalysis; + +namespace Aaru.Decoders.SCSI +{ + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum MediumTypes : byte + { + Default = 0x00, + + #region Medium Types defined in ECMA-111 for Direct-Access devices + /// ECMA-54: 200 mm Flexible Disk Cartridge using Two-Frequency Recording at 13262 ftprad on One Side + ECMA54 = 0x09, + /// + /// ECMA-59 & ANSI X3.121-1984: 200 mm Flexible Disk Cartridge using Two-Frequency Recording at 13262 ftprad + /// on Both Sides + /// + ECMA59 = 0x0A, + /// ECMA-69: 200 mm Flexible Disk Cartridge using MFM Recording at 13262 ftprad on Both Sides + ECMA69 = 0x0B, + /// ECMA-66: 130 mm Flexible Disk Cartridge using Two-Frequency Recording at 7958 ftprad on One Side + ECMA66 = 0x0E, + /// + /// ECMA-70 & ANSI X3.125-1985: 130 mm Flexible Disk Cartridge using MFM Recording at 7958 ftprad on Both + /// Sides; 1,9 Tracks per mm + /// + ECMA70 = 0x12, + /// + /// ECMA-78 & ANSI X3.126-1986: 130 mm Flexible Disk Cartridge using MFM Recording at 7958 ftprad on Both + /// Sides; 3,8 Tracks per mm + /// + ECMA78 = 0x16, + /// + /// ECMA-99 & ISO 8630-1985: 130 mm Flexible Disk Cartridge using MFM Recording at 13262 ftprad on Both Sides; + /// 3,8 Tracks per mm + /// + ECMA99 = 0x1A, + /// + /// ECMA-100 & ANSI X3.137: 90 mm Flexible Disk Cartridge using MFM Recording at 7859 ftprad on Both Sides; + /// 5,3 Tracks per mm + /// + ECMA100 = 0x1E, + #endregion Medium Types defined in ECMA-111 for Direct-Access devices + + #region Medium Types defined in SCSI-2 for Direct-Access devices + /// Unspecified single sided flexible disk + Unspecified_SS = 0x01, + /// Unspecified double sided flexible disk + Unspecified_DS = 0x02, + /// ANSI X3.73-1980: 200 mm, 6631 ftprad, 1,9 Tracks per mm, 1 side + X3_73 = 0x05, + /// ANSI X3.73-1980: 200 mm, 6631 ftprad, 1,9 Tracks per mm, 2 sides + X3_73_DS = 0x06, + /// ANSI X3.80-1980: 130 mm, 3979 ftprad, 1,9 Tracks per mm, 1 side + X3_82 = 0x0D, + /// 6,3 mm tape with 12 tracks at 394 ftpmm + Tape12 = 0x40, + /// 6,3 mm tape with 24 tracks at 394 ftpmm + Tape24 = 0x44, + #endregion Medium Types defined in SCSI-2 for Direct-Access devices + + #region Medium Types defined in SCSI-3 SBC-1 for Optical devices + /// Read-only medium + ReadOnly = 0x01, + /// Write-once Read-many medium + WORM = 0x02, + /// Erasable medium + Erasable = 0x03, + /// Combination of read-only and write-once medium + RO_WORM = 0x04, + /// Combination of read-only and erasable medium + RO_RW = 0x05, + /// Combination of write-once and erasable medium + WORM_RW = 0x06, + #endregion Medium Types defined in SCSI-3 SBC-1 for Optical devices + + #region Medium Types defined in SCSI-2 for MultiMedia devices + /// 120 mm CD-ROM + CDROM = 0x01, + /// 120 mm Compact Disc Digital Audio + CDDA = 0x02, + /// 120 mm Compact Disc with data and audio + MixedCD = 0x03, + /// 80 mm CD-ROM + CDROM_80 = 0x05, + /// 80 mm Compact Disc Digital Audio + CDDA_80 = 0x06, + /// 80 mm Compact Disc with data and audio + MixedCD_80 = 0x07, + #endregion Medium Types defined in SCSI-2 for MultiMedia devices + + #region Medium Types defined in SFF-8020i + /// Unknown medium type + Unknown_CD = 0x00, + /// 120 mm Hybrid disc (Photo CD) + HybridCD = 0x04, + /// Unknown size CD-R + Unknown_CDR = 0x10, + /// 120 mm CD-R with data only + CDR = 0x11, + /// 120 mm CD-R with audio only + CDR_DA = 0x12, + /// 120 mm CD-R with data and audio + CDR_Mixed = 0x13, + /// 120 mm Hybrid CD-R (Photo CD) + HybridCDR = 0x14, + /// 80 mm CD-R with data only + CDR_80 = 0x15, + /// 80 mm CD-R with audio only + CDR_DA_80 = 0x16, + /// 80 mm CD-R with data and audio + CDR_Mixed_80 = 0x17, + /// 80 mm Hybrid CD-R (Photo CD) + HybridCDR_80 = 0x18, + /// Unknown size CD-RW + Unknown_CDRW = 0x20, + /// 120 mm CD-RW with data only + CDRW = 0x21, + /// 120 mm CD-RW with audio only + CDRW_DA = 0x22, + /// 120 mm CD-RW with data and audio + CDRW_Mixed = 0x23, + /// 120 mm Hybrid CD-RW (Photo CD) + HybridCDRW = 0x24, + /// 80 mm CD-RW with data only + CDRW_80 = 0x25, + /// 80 mm CD-RW with audio only + CDRW_DA_80 = 0x26, + /// 80 mm CD-RW with data and audio + CDRW_Mixed_80 = 0x27, + /// 80 mm Hybrid CD-RW (Photo CD) + HybridCDRW_80 = 0x28, + /// Unknown size HD disc + Unknown_HD = 0x30, + /// 120 mm HD disc + HD = 0x31, + /// 80 mm HD disc + HD_80 = 0x35, + /// No disc inserted, tray closed or caddy inserted + NoDisc = 0x70, + /// Tray open or no caddy inserted + TrayOpen = 0x71, + /// Tray closed or caddy inserted but medium error + MediumError = 0x72, + #endregion Medium Types defined in SFF-8020i + + #region Medium Types defined in USB Mass Storage Class - UFI Command Specification + /// 3.5-inch, 135 tpi, 12362 bits/radian, double-sided MFM (aka 1.25Mb) + Type3Floppy = 0x93, + /// 3.5-inch, 135 tpi, 15916 bits/radian, double-sided MFM (aka 1.44Mb) + HDFloppy = 0x94, + #endregion Medium Types defined in USB Mass Storage Class - UFI Command Specification + + #region Medium Types defined in INF-8070 + /// Unknown type block device + UnknownBlockDevice = 0x40, + /// Read-only block device + ReadOnlyBlockDevice = 0x41, + /// Read/Write block device + ReadWriteBlockDevice = 0x42, + #endregion Medium Types defined in INF-8070 + + #region Medium Types found in vendor documents + /// LTO WORM as reported by HP drives + LTOWORM = 0x01, + /// LTO cleaning cartridge as reported by Certance/Seagate drives + LTOCleaning = 0x01, + /// Direct-overwrite magneto-optical + DOW = 0x07, + /// LTO Ultrium + LTO = 0x18, + /// LTO Ultrium-2 + LTO2 = 0x28, + /// DC-2900SL + DC2900SL = 0x31, + /// MLR-1 + MLR1 = 0x33, + /// DDS-3 + DDS3 = 0x33, + /// DC-9200 + DC9200 = 0x34, + /// DDS-4 + DDS4 = 0x34, + /// DAT-72 + DAT72 = 0x35, + /// LTO Ultrium-3 + LTO3 = 0x38, + /// LTO Ultrium-3 WORM + LTO3WORM = 0x3C, + /// DDS cleaning cartridge + DDSCleaning = 0x3F, + /// DC-9250 + DC9250 = 0x40, + /// SLR-32 + SLR32 = 0x43, + /// MLR-1SL + MLR1SL = 0x44, + /// SLRtape-50 + SLRtape50 = 0x47, + /// LTO Ultrium-4 + LTO4 = 0x48, + /// LTO Ultrium-4 WORM + LTO4WORM = 0x4C, + /// SLRtape-50SL + SLRtape50SL = 0x50, + /// SLR-32SL + SLR32SL = 0x54, + /// SLR-5 + SLR5 = 0x55, + /// SLR-5SL + SLR5SL = 0x56, + /// LTO Ultrium-5 + LTO5 = 0x58, + /// LTO Ultrium-5 WORM + LTO5WORM = 0x5C, + /// SLRtape-7 + SLRtape7 = 0x63, + /// SLRtape-7SL + SLRtape7SL = 0x64, + /// SLRtape-24 + SLRtape24 = 0x65, + /// SLRtape-24SL + SLRtape24SL = 0x66, + /// LTO Ultrium-6 + LTO6 = 0x68, + /// LTO Ultrium-6 WORM + LTO6WORM = 0x6C, + /// SLRtape-140 + SLRtape140 = 0x70, + /// SLRtape-40 + SLRtape40 = 0x73, + /// SLRtape-60 + SLRtape60 = 0x74, + /// SLRtape-75 + SLRtape75 = 0x74, + /// SLRtape-100 + SLRtape100 = 0x75, + /// SLR-40 or SLR-60 or SLR-100 + SLR40_60_100 = 0x76, + /// LTO Ultrium-7 + LTO7 = 0x78, + /// LTO Ultrium-7 WORM + LTO7WORM = 0x7C, + /// HP LTO emulating a CD + LTOCD = 0x80, + /// Exatape 15m + Exatape15m = 0x81, + /// IBM MagStar + MagStar = 0x81, + /// VXA + VXA = 0x81, + /// CompactTape I + CT1 = 0x82, + /// Exatape 28m + Exatape28m = 0x82, + /// CompactTape II + CT2 = 0x82, + /// VXA-2 + VXA2 = 0x82, + /// VXA-3 + VXA3 = 0x82, + /// Exatape 54m + Exatape54m = 0x83, + /// DLTtape III + DLTtapeIII = 0x83, + /// Exatape 80m + Exatape80m = 0x84, + /// DLTtape IIIxt + DLTtapeIIIxt = 0x84, + /// Exatape 106m + Exatape106m = 0x85, + /// DLTtape IV + DLTtapeIV = 0x85, + /// Travan 5 + Travan5 = 0x85, + /// Exatape 106m XL + Exatape106mXL = 0x86, + /// SuperDLT I + SDLT1 = 0x86, + /// SuperDLT II + SDLT2 = 0x87, + /// VStape I + VStapeI = 0x90, + /// DLTtape S4 + DLTtapeS4 = 0x91, + /// Travan 7 + Travan7 = 0x95, + /// Exatape 22m + Exatape22m = 0xC1, + /// Exatape 40m + Exatape40m = 0xC2, + /// Exatape 76m + Exatape76m = 0xC3, + /// Exatape 112m + Exatape112m = 0xC4, + /// Exatape 22m AME + Exatape22mAME = 0xD1, + /// Exatape 170m + Exatape170m = 0xD2, + /// Exatape 125m + Exatape125m = 0xD3, + /// Exatape 45m + Exatape45m = 0xD4, + /// Exatape 225m + Exatape225m = 0xD5, + /// Exatape 150m + Exatape150m = 0xD6, + /// Exatape 75m + Exatape75m = 0xD7, + #endregion Medium Types found in vendor documents + + #region Medium Types found testing a Hi-MD drive + /// Hi-MD + HiMD = 0x44, + #endregion Medium Types found testing a Hi-MD drive + } + + [SuppressMessage("ReSharper", "InconsistentNaming")] + public enum DensityType : byte + { + Default = 0x00, + + #region Density Types defined in ECMA-111 for Direct-Access devices + /// 7958 flux transitions per radian + Flux7958 = 0x01, + /// 13262 flux transitions per radian + Flux13262 = 0x02, + /// 15916 flux transitions per radian + Flux15916 = 0x03, + #endregion Density Types defined in ECMA-111 for Direct-Access devices + + #region Density Types defined in ECMA-111 for Sequential-Access devices + /// ECMA-62 & ANSI X3.22-1983: 12,7 mm 9-Track Magnetic Tape, 32 ftpmm, NRZI, 32 cpmm + ECMA62 = 0x01, + /// ECMA-62 & ANSI X3.39-1986: 12,7 mm 9-Track Magnetic Tape, 126 ftpmm, Phase Encoding, 63 cpmm + ECMA62_Phase = 0x02, + /// ECMA-62 & ANSI X3.54-1986: 12,7 mm 9-Track Magnetic Tape, 356 ftpmm, NRZI, 245 cpmm GCR + ECMA62_GCR = 0x03, + /// ECMA-79 & ANSI X3.116-1986: 6,30 mm Magnetic Tape Cartridge using MFM Recording at 252 ftpmm + ECMA79 = 0x07, + /// + /// Draft ECMA & ANSI X3B5/87-099: 12,7 mm Magnetic Tape Cartridge using IFM Recording on 18 Tracks at 1944 + /// ftpmm, GCR (IBM 3480, 3490, 3490E) + /// + IBM3480 = 0x09, + /// ECMA-46 & ANSI X3.56-1986: 6,30 mm Magnetic Tape Cartridge, Phase Encoding, 63 bpmm + ECMA46 = 0x0B, + /// ECMA-98: 6,30 mm Magnetic Tape Cartridge, NRZI Recording, 394 ftpmm + ECMA98 = 0x0E, + #endregion Density Types defined in ECMA-111 for Sequential-Access devices + + #region Density Types defined in SCSI-2 for Sequential-Access devices + /// ANXI X3.136-1986: 6,35 mm 4 or 9-Track Magnetic Tape Cartridge, 315 bpmm, GCR (QIC-24) + X3_136 = 0x05, + /// ANXI X3.157-1987: 12,7 mm 9-Track Magnetic Tape, 126 bpmm, Phase Encoding + X3_157 = 0x06, + /// ANXI X3.158-1987: 3,81 mm 4-Track Magnetic Tape Cassette, 315 bpmm, GCR + X3_158 = 0x08, + /// ANXI X3B5/86-199: 12,7 mm 22-Track Magnetic Tape Cartridge, 262 bpmm, MFM + X3B5_86 = 0x0A, + /// HI-TC1: 12,7 mm 24-Track Magnetic Tape Cartridge, 500 bpmm, GCR + HiTC1 = 0x0C, + /// HI-TC2: 12,7 mm 24-Track Magnetic Tape Cartridge, 999 bpmm, GCR + HiTC2 = 0x0D, + /// QIC-120: 6,3 mm 15-Track Magnetic Tape Cartridge, 394 bpmm, GCR + QIC120 = 0x0F, + /// QIC-150: 6,3 mm 18-Track Magnetic Tape Cartridge, 394 bpmm, GCR + QIC150 = 0x10, + /// QIC-320: 6,3 mm 26-Track Magnetic Tape Cartridge, 630 bpmm, GCR + QIC320 = 0x11, + /// QIC-1350: 6,3 mm 30-Track Magnetic Tape Cartridge, 2034 bpmm, RLL + QIC1350 = 0x12, + /// ANXI X3B5/88-185A: 3,81 mm Magnetic Tape Cassette, 2400 bpmm, DDS + X3B5_88 = 0x13, + /// ANXI X3.202-1991: 8 mm Magnetic Tape Cassette, 1703 bpmm, RLL + X3_202 = 0x14, + /// ECMA TC17: 8 mm Magnetic Tape Cassette, 1789 bpmm, RLL + ECMA_TC17 = 0x15, + /// ANXI X3.193-1990: 12,7 mm 48-Track Magnetic Tape Cartridge, 394 bpmm, MFM + X3_193 = 0x16, + /// ANXI X3B5/97-174: 12,7 mm 48-Track Magnetic Tape Cartridge, 1673 bpmm, MFM + X3B5_91 = 0x17, + #endregion Density Types defined in SCSI-2 for Sequential-Access devices + + #region Density Types defined in SCSI-2 for MultiMedia devices + /// User data only + User = 0x01, + /// User data plus auxiliary data field + UserAuxiliary = 0x02, + /// 4-byt tag field, user data plus auxiliary data + UserAuxiliaryTag = 0x03, + /// Audio information only + Audio = 0x04, + #endregion Density Types defined in SCSI-2 for MultiMedia devices + + #region Density Types defined in SCSI-2 for Optical devices + /// ISO/IEC 10090: 86 mm Read/Write single-sided optical disc with 12500 tracks + ISO10090 = 0x01, + /// 89 mm Read/Write double-sided optical disc with 12500 tracks + D581 = 0x02, + /// ANSI X3.212: 130 mm Read/Write double-sided optical disc with 18750 tracks + X3_212 = 0x03, + /// ANSI X3.191: 130 mm Write-Once double-sided optical disc with 30000 tracks + X3_191 = 0x04, + /// ANSI X3.214: 130 mm Write-Once double-sided optical disc with 20000 tracks + X3_214 = 0x05, + /// ANSI X3.211: 130 mm Write-Once double-sided optical disc with 18750 tracks + X3_211 = 0x06, + /// 200 mm optical disc + D407 = 0x07, + /// ISO/IEC 13614: 300 mm double-sided optical disc + ISO13614 = 0x08, + /// ANSI X3.200: 356 mm double-sided optical disc with 56350 tracks + X3_200 = 0x09, + #endregion Density Types defined in SCSI-2 for Optical devices + + #region Density Types found in vendor documents + /// QIC-11 + QIC11 = 0x04, + /// CompactTape I + CT1 = 0x0A, + /// Exabyte 8200 format + Ex8200 = 0x14, + /// Exabyte 8500 format + Ex8500 = 0x15, + /// CompactTape II + CT2 = 0x16, + /// DLTtape III 42500 bpi + DLT3_42k = 0x17, + /// DLTtape III 56 track + DLT3_56t = 0x18, + /// DLTtape III 62500 bpi + DLT3_62k = 0x19, + /// DLTtape IV + DLT4 = 0x1A, + /// DLTtape IV 85937 bpi + DLT4_85k = 0x1B, + /// DDS-2 + DDS2 = 0x24, + /// DDS-3 + DDS3 = 0x25, + /// DDS-4 + DDS4 = 0x26, + /// Exabyte Mammoth + Mammoth = 0x27, + /// IBM 3490 & 3490E + IBM3490E = 0x28, + /// Exabyte Mammoth-2 + Mammoth2 = 0x28, + /// IBM 3590 + IBM3590 = 0x29, + /// IBM 3590E + IBM3590E = 0x2A, + /// AIT-1 + AIT1 = 0x30, + /// AIT-2 + AIT2 = 0x31, + /// AIT-3 + AIT3 = 0x32, + /// DLTtape IV 123090 bpi + DLT4_123k = 0x40, + /// Ultrium-1 + LTO1 = 0x40, + /// Super AIT-1 + SAIT1 = 0x40, + /// DLTtape IV 85937 bpi + DLT4_98k = 0x41, + /// Ultrium-2 as reported by the Certance drive + LTO2Old = 0x41, + /// Ultrium-2 + LTO2 = 0x42, + /// T9840 + T9840 = 0x42, + /// T9940 + T9940 = 0x43, + /// Ultrium- + LTO3 = 0x44, + /// T9840C + T9840C = 0x45, + /// Travan 5 + Travan5 = 0x46, + /// Ultrium-4 + LTO4 = 0x46, + /// T9840D + T9840D = 0x46, + /// DAT-72 + DAT72 = 0x47, + /// Super DLTtape I 133000 bpi + SDLT1_133k = 0x48, + /// Super DLTtape I + SDLT1 = 0x49, + /// T10000A + T10000A = 0x4A, + /// Super DLTtape II + SDLT2 = 0x4A, + /// DLTtape S4 + DLTS4 = 0x4B, + /// T10000B + T10000B = 0x4B, + /// T10000C + T10000C = 0x4C, + /// T10000D + T10000D = 0x4D, + /// VStape I + VStape1 = 0x40, + /// Ultrium-5 + LTO5 = 0x58, + /// Ultrium-6 + LTO6 = 0x5A, + /// Ultrium-7 + LTO7 = 0x5C, + /// DLTtape III 62500 bpi secondary code + DLT3_62kAlt = 0x80, + /// VXA-1 + VXA1 = 0x80, + /// DLTtape III compressed + DLT3c = 0x81, + /// VXA-2 + VXA2 = 0x81, + /// DLTtape IV secondary code + DLT4Alt = 0x82, + /// VXA-3 + VXA3 = 0x82, + /// DLTtape IV compressed + DLT4c = 0x83, + /// DLTtape IV 85937 bpi secondary code + DLT4_85kAlt = 0x84, + /// DLTtape IV 85937 bpi compressed + DLT4c_85k = 0x85, + /// DLTtape IV 123090 bpi secondary code + DLT4_123kAlt = 0x86, + /// DLTtape IV 123090 bpi compressed + DLT4c_123k = 0x87, + /// DLTtape IV 98250 bpi secondary code + DLT4_98kAlt = 0x88, + /// DLTtape IV 98250 bpi compressed + DLT4c_98k = 0x89, + /// Exabyte compressed 8200 format + Ex8500c = 0x8C, + /// Exabyte compressed 8500 format + Ex8200c = 0x90, + /// Super DLTtape I secondary code + SDLT1Alt = 0x90, + /// Super DLTtape I compressed + SDLT1c = 0x91, + /// Super DLTtape I 133000 bpi secondary code + SDLT1_133kAlt = 0x92, + /// Super DLTtape I 133000 bpi compressed + SDLT1c_133k = 0x93, + /// VStape I secondary code + VStape1Alt = 0x98, + /// VStape I compressed + VStape1c = 0x99, + #endregion Density Types found in vendor documents + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SCSI/VendorString.cs b/Aaru.Decoders/SCSI/VendorString.cs new file mode 100644 index 000000000..f5410f8ff --- /dev/null +++ b/Aaru.Decoders/SCSI/VendorString.cs @@ -0,0 +1,843 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : VendorString.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Contains SCSI vendor strings. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.Decoders.SCSI +{ + public static class VendorString + { + public static string Prettify(string scsiVendorString) + { + switch(scsiVendorString) + { + case "0B4C": return "MOOSIK Ltd."; + case "13FE": return "PHISON"; + case "2AI": return "2AI (Automatisme et Avenir Informatique)"; + case "3M": return "3M Company"; + case "3nhtech": return "3NH Technologies"; + case "3PARdata": return "3PARdata, Inc."; + case "A-Max": return "A-Max Technology Co., Ltd"; + case "ABSOLUTE": return "Absolute Analysis"; + case "ACARD": return "ACARD Technology Corp."; + case "Accusys": return "Accusys INC."; + case "Acer": return "Acer, Inc."; + case "ACL": return "Automated Cartridge Librarys, Inc."; + case "Actifio": return "Actifio"; + case "Acuid": return "Acuid Corporation Ltd."; + case "AcuLab": return "AcuLab, Inc. (Tulsa, OK)"; + case "ADAPTEC": return "Adaptec"; + case "ADIC": return "Advanced Digital Information Corporation"; + case "ADSI": return "Adaptive Data Systems, Inc. (a Western Digital subsidiary)"; + case "ADTX": return "ADTX Co., Ltd."; + case "ADVA": return "ADVA Optical Networking AG"; + case "AEM": return "AEM Performance Electronics"; + case "AERONICS": return "Aeronics, Inc."; + case "AGFA": return "AGFA"; + case "Agilent": return "Agilent Technologies"; + case "AIC": return "Advanced Industrial Computer, Inc."; + case "AIPTEK": return "AIPTEK International Inc."; + case "Alcohol": return "Alcohol Soft"; + case "ALCOR": return "Alcor Micro, Corp."; + case "AMCC": return "Applied Micro Circuits Corporation"; + case "AMCODYNE": return "Amcodyne"; + case "Amgeon": return "Amgeon LLC"; + case "AMI": return "American Megatrends, Inc."; + case "AMPEX": return "Ampex Data Systems"; + case "Amphenol": return "Amphenol"; + case "Amtl": return "Tenlon Technology Co.,Ltd"; + case "ANAMATIC": return "Anamartic Limited (England)"; + case "Ancor": return "Ancor Communications, Inc."; + case "ANCOT": return "ANCOT Corp."; + case "ANDATACO": return "Andataco"; + case "andiamo": return "Andiamo Systems, Inc."; + case "ANOBIT": return "Anobit"; + case "ANRITSU": return "Anritsu Corporation"; + case "ANTONIO": return "Antonio Precise Products Manufactory Ltd."; + case "AoT": return "Art of Technology AG"; + case "APPLE": return "Apple Computer, Inc."; + case "ARCHIVE": return "Archive"; + case "ARDENCE": return "Ardence Inc"; + case "Areca": return "Areca Technology Corporation"; + case "Arena": return "MaxTronic International Co., Ltd."; + case "Argent": return "Argent Data Systems, Inc."; + case "ARIO": return "Ario Data Networks, Inc."; + case "ARISTOS": return "Aristos Logic Corp."; + case "ARK": return "ARK Research Corporation"; + case "ARL:UT@A": return "Applied Research Laboratories : University of Texas at Austin"; + case "ARTECON": return "Artecon Inc."; + case "Artistic": return "Artistic Licence (UK) Ltd"; + case "ARTON": return "Arton Int."; + case "ASACA": return "ASACA Corp."; + case "ASC": return "Advanced Storage Concepts, Inc."; + case "ASPEN": return "Aspen Peripherals"; + case "AST": return "AST Research"; + case "ASTEK": return "Astek Corporation"; + case "ASTK": return "Alcatel STK A/S"; + case "AStor": return "AccelStor, Inc."; + case "ASTUTE": return "Astute Networks, Inc."; + case "AT&T": return "AT&T"; + case "ATA": return "SCSI / ATA Translator Software (Organization Not Specified)"; + case "ATARI": return "Atari Corporation"; + case "ATech": return "ATech electronics"; + case "ATG CYG": return "ATG Cygnet Inc."; + case "ATL": return "Quantum|ATL Products"; + case "ATTO": return "ATTO Technology Inc."; + case "ATTRATEC": return "Attratech Ltd liab. Co"; + case "ATX": return "Alphatronix"; + case "AURASEN": return "Aurasen Limited"; + case "Avago": return "Avago Technologies"; + case "AVC": return "AVC Technology Ltd"; + case "AVIDVIDR": return "AVID Technologies, Inc."; + case "AVR": return "Advanced Vision Research"; + case "AXSTOR": return "AXSTOR"; + case "Axxana": return "Axxana Ltd."; + case "B*BRIDGE": return "Blockbridge Networks LLC"; + case "BALLARD": return "Ballard Synergy Corp."; + case "Barco": return "Barco"; + case "BAROMTEC": return "Barom Technologies Co., Ltd."; + case "Bassett": return "Bassett Electronic Systems Ltd"; + case "BC Hydro": return "BC Hydro"; + case "BDT": return "BDT AG"; + case "BECEEM": return "Beceem Communications, Inc"; + case "BENQ": return "BENQ Corporation."; + case "BERGSWD": return "Berg Software Design"; + case "BEZIER": return "Bezier Systems, Inc."; + case "BHTi": return "Breece Hill Technologies"; + case "biodata": return "Biodata Devices SL"; + case "BIOS": return "BIOS Corporation"; + case "BIR": return "Bio-Imaging Research, Inc."; + case "BiT": return "BiT Microsystems"; + case "BITMICRO": return "BiT Microsystems, Inc."; + case "Blendlgy": return "Blendology Limited"; + case "BLOOMBAS": return "Bloombase Technologies Limited"; + case "BlueArc": return "BlueArc Corporation"; + case "bluecog": return "bluecog"; + case "BME-HVT": return "Broadband Infocommunicatons and Electromagnetic Theory Department"; + case "BNCHMARK": return "Benchmark Tape Systems Corporation"; + case "Bosch": return "Robert Bosch GmbH"; + case "Botman": return "Botmanfamily Electronics"; + case "BoxHill": return "Box Hill Systems Corporation"; + case "BRDGWRKS": return "Bridgeworks Ltd."; + case "BREA": return "BREA Technologies, Inc."; + case "BREECE": return "Breece Hill LLC"; + case "BreqLabs": return "BreqLabs Inc."; + case "Broadcom": return "Broadcom Corporation"; + case "BROCADE": return "Brocade Communications Systems, Incorporated"; + case "BUFFALO": return "BUFFALO INC."; + case "BULL": return "Bull Peripherals Corp."; + case "BUSLOGIC": return "BusLogic Inc."; + case "BVIRTUAL": return "B-Virtual N.V."; + case "CACHEIO": return "CacheIO LLC"; + case "CalComp": return "CalComp, A Lockheed Company"; + case "CALCULEX": return "CALCULEX, Inc."; + case "CALIPER": return "Caliper (California Peripheral Corp.)"; + case "CAMBEX": return "Cambex Corporation"; + case "CAMEOSYS": return "Cameo Systems Inc."; + case "CANDERA": return "Candera Inc."; + case "CAPTION": return "CAPTION BANK"; + case "CAST": return "Advanced Storage Tech"; + case "CATALYST": return "Catalyst Enterprises"; + case "CCDISK": return "iSCSI Cake"; + case "CDC": return "Control Data or MPI"; + case "CDP": return "Columbia Data Products"; + case "Celsia": return "A M Bromley Limited"; + case "CenData": return "Central Data Corporation"; + case "Cereva": return "Cereva Networks Inc."; + case "CERTANCE": return "Certance"; + case "Chantil": return "Chantil Technology"; + case "CHEROKEE": return "Cherokee Data Systems"; + case "CHINON": return "Chinon"; + case "CHRISTMA": return "Christmann Informationstechnik + Medien GmbH & Co KG"; + case "CIE&YED": return "YE Data, C.Itoh Electric Corp."; + case "CIPHER": return "Cipher Data Products"; + case "Ciprico": return "Ciprico, Inc."; + case "CIRRUSL": return "Cirrus Logic Inc."; + case "CISCO": return "Cisco Systems, Inc."; + case "CLEARSKY": return "ClearSky Data, Inc."; + case "CLOVERLF": return "Cloverleaf Communications, Inc"; + case "CLS": return "Celestica"; + case "CMD": return "CMD Technology Inc."; + case "CMTechno": return "CMTech"; + case "CNGR SFW": return "Congruent Software, Inc."; + case "CNSi": return "Chaparral Network Storage, Inc."; + case "CNT": return "Computer Network Technology"; + case "COBY": return "Coby Electronics Corporation, USA"; + case "COGITO": return "Cogito"; + case "COMAY": return "Corerise Electronics"; + case "COMPAQ": return "Compaq Computer Corporation"; + case "COMPELNT": return "Compellent Technologies, Inc."; + case "COMPORT": return "Comport Corp."; + case "COMPSIG": return "Computer Signal Corporation"; + case "COMPTEX": return "Comptex Pty Limited"; + case "CONNER": return "Conner Peripherals"; + case "COPANSYS": return "COPAN SYSTEMS INC"; + case "CORAID": return "Coraid, Inc"; + case "CORE": return "Core International, Inc."; + case "CORERISE": return "Corerise Electronics"; + case "COVOTE": return "Covote GmbH & Co KG"; + case "COWON": return "COWON SYSTEMS, Inc."; + case "CPL": return "Cross Products Ltd"; + case "CPU TECH": return "CPU Technology, Inc."; + case "CREO": return "Creo Products Inc."; + case "CROSFLD": return "Crosfield Electronics"; + case "CROSSRDS": return "Crossroads Systems, Inc."; + case "crosswlk": return "Crosswalk, Inc."; + case "CSCOVRTS": return "Cisco - Veritas"; + case "CSM, INC": return "Computer SM, Inc."; + case "Cunuqui": return "CUNUQUI SLU"; + case "CYBERNET": return "Cybernetics"; + case "Cygnal": return "Dekimo"; + case "CYPRESS": return "Cypress Semiconductor Corp."; + case "D Bit": return "Digby's Bitpile, Inc. DBA D Bit"; + case "DALSEMI": return "Dallas Semiconductor"; + case "DANEELEC": return "Dane-Elec"; + case "DANGER": return "Danger Inc."; + case "DAT-MG": return "DAT Manufacturers Group"; + case "Data Com": return "Data Com Information Systems Pty. Ltd."; + case "DATABOOK": return "Databook, Inc."; + case "DATACOPY": return "Datacopy Corp."; + case "DataCore": return "DataCore Software Corporation"; + case "DataG": return "DataGravity"; + case "DATAPT": return "Datapoint Corp."; + case "DATARAM": return "Dataram Corporation"; + case "DATC": return "Datum Champion Technology Co., Ltd"; + case "DAVIS": return "Daviscomms (S) Pte Ltd"; + case "DCS": return "ShenZhen DCS Group Co.,Ltd"; + case "DDN": return "DataDirect Networks, Inc."; + case "DDRDRIVE": return "DDRdrive LLC"; + case "DE": return "Dimension Engineering LLC"; + case "DEC": return "Digital Equipment Corporation"; + case "DEI": return "Digital Engineering, Inc."; + case "DELL": return "Dell, Inc."; + case "Dell(tm)": return "Dell, Inc"; + case "DELPHI": return "Delphi Data Div. of Sparks Industries, Inc."; + case "DENON": return "Denon/Nippon Columbia"; + case "DenOptix": return "DenOptix, Inc."; + case "DEST": return "DEST Corp."; + case "DFC": return "DavioFranke.com"; + case "DFT": return "Data Fault Tolerance System CO.,LTD."; + case "DGC": return "Data General Corp."; + case "DIGIDATA": return "Digi-Data Corporation"; + case "DigiIntl": return "Digi International"; + case "Digital": return "Digital Equipment Corporation"; + case "DILOG": return "Distributed Logic Corp."; + case "DISC": return "Document Imaging Systems Corp."; + case "DiscSoft": return "Disc Soft Ltd"; + case "DLNET": return "Driveline"; + case "DNS": return "Data and Network Security"; + case "DNUK": return "Digital Networks Uk Ltd"; + case "DotHill": return "Dot Hill Systems Corp."; + case "DP": return "Dell, Inc."; + case "DPT": return "Distributed Processing Technology"; + case "Drewtech": return "Drew Technologies, Inc."; + case "DROBO": return "Data Robotics, Inc."; + case "DSC": return "DigitalStream Corporation"; + case "DSI": return "Data Spectrum, Inc."; + case "DSM": return "Deterner Steuerungs- und Maschinenbau GmbH & Co."; + case "DSNET": return "Cleversafe, Inc."; + case "DT": return "Double-Take Software, INC."; + case "DTC QUME": return "Data Technology Qume"; + case "DXIMAGIN": return "DX Imaging"; + case "E-Motion": return "E-Motion LLC"; + case "EARTHLAB": return "EarthLabs"; + case "EarthLCD": return "Earth Computer Technologies, Inc."; + case "ECCS": return "ECCS, Inc."; + case "ECMA": return "European Computer Manufacturers Association"; + case "EDS": return "Embedded Data Systems"; + case "EIM": return "InfoCore"; + case "ELE Intl": return "ELE International"; + case "ELEGANT": return "Elegant Invention, LLC"; + case "Elektron": return "Elektron Music Machines MAV AB"; + case "elipsan": return "Elipsan UK Ltd."; + case "Elms": return "Elms Systems Corporation"; + case "ELSE": return "ELSE Ltd."; + case "ELSEC": return "Littlemore Scientific"; + case "EMASS": return "EMASS, Inc."; + case "EMC": return "EMC Corp."; + case "EMiT": return "EMiT Conception Eletronique"; + case "EMTEC": return "EMTEC Magnetics"; + case "EMULEX": return "Emulex"; + case "ENERGY-B": return "Energybeam Corporation"; + case "ENGENIO": return "Engenio Information Technologies, Inc."; + case "ENMOTUS": return "Enmotus Inc"; + case "Entacore": return "Entacore"; + case "EPOS": return "EPOS Technologies Ltd."; + case "EPSON": return "Epson"; + case "EQLOGIC": return "EqualLogic"; + case "Eris/RSI": return "RSI Systems, Inc."; + case "ETERNE": return "EterneData Technology Co.,Ltd.(China PRC.)"; + case "EuroLogc": return "Eurologic Systems Limited"; + case "evolve": return "Evolution Technologies, Inc"; + case "EXABYTE": return "Exabyte Corp."; + case "EXATEL": return "Exatelecom Co., Ltd."; + case "EXAVIO": return "Exavio, Inc."; + case "Exsequi": return "Exsequi Ltd"; + case "Exxotest": return "Annecy Electronique"; + case "FAIRHAVN": return "Fairhaven Health, LLC"; + case "FALCON": return "FalconStor, Inc."; + case "FDS": return "Formation Data Systems"; + case "FFEILTD": return "FujiFilm Electonic Imaging Ltd"; + case "Fibxn": return "Fiberxon, Inc."; + case "FID": return "First International Digital, Inc."; + case "FILENET": return "FileNet Corp."; + case "FirmFact": return "Firmware Factory Ltd"; + case "FLYFISH": return "Flyfish Technologies"; + case "FOXCONN": return "Foxconn Technology Group"; + case "FRAMDRV": return "FRAMEDRIVE Corp."; + case "FREECION": return "Nable Communications, Inc."; + case "FRESHDTK": return "FreshDetect GmbH"; + case "FSC": return "Fujitsu Siemens Computers"; + case "FTPL": return "Frontline Technologies Pte Ltd"; + case "FUJI": return "Fuji Electric Co., Ltd. (Japan)"; + case "FUJIFILM": return "Fuji Photo Film, Co., Ltd."; + case "FUJITSU": return "Fujitsu"; + case "FUNAI": return "Funai Electric Co., Ltd."; + case "FUSIONIO": return "Fusion-io Inc."; + case "FUTURED": return "Future Domain Corp."; + case "G&D": return "Giesecke & Devrient GmbH"; + case "G.TRONIC": return "Globaltronic - Electronica e Telecomunicacoes, S.A."; + case "Gadzoox": return "Gadzoox Networks, Inc."; + case "Gammaflx": return "Gammaflux L.P."; + case "GDI": return "Generic Distribution International"; + case "GEMALTO": return "gemalto"; + case "Gen_Dyn": return "General Dynamics"; + case "Generic": return "Generic Technology Co., Ltd."; + case "GENSIG": return "General Signal Networks"; + case "GEO": return "Green Energy Options Ltd"; + case "GIGATAPE": return "GIGATAPE GmbH"; + case "GIGATRND": return "GigaTrend Incorporated"; + case "Global": return "Global Memory Test Consortium"; + case "Gnutek": return "Gnutek Ltd."; + case "Goidelic": return "Goidelic Precision, Inc."; + case "GoldKey": return "GoldKey Security Corporation"; + case "GoldStar": return "LG Electronics Inc."; + case "GOOGLE": return "Google, Inc."; + case "GORDIUS": return "Gordius"; + case "GOULD": return "Gould"; + case "HAGIWARA": return "Hagiwara Sys-Com Co., Ltd."; + case "HAPP3": return "Inventec Multimedia and Telecom co., ltd"; + case "HDS": return "Horizon Data Systems, Inc."; + case "Helldyne": return "Helldyne, Inc"; + case "Heydays": return "Mazo Technology Co., Ltd."; + case "HGST": return "HGST a Western Digital Company"; + case "HI-TECH": return "HI-TECH Software Pty. Ltd."; + case "HITACHI": return "Hitachi America Ltd or Nissei Sangyo America Ltd"; + case "HL-DT-ST": return "Hitachi-LG Data Storage, Inc."; + case "HONEYWEL": return "Honeywell Inc."; + case "Hoptroff": return "HexWax Ltd"; + case "HORIZONT": return "Horizontigo Software"; + case "HP": return "Hewlett Packard"; + case "HPE": return "Hewlett Packard Enterprise"; + case "HPI": return "HP Inc."; + case "HPQ": return "Hewlett Packard"; + case "HUALU": return "CHINA HUALU GROUP CO., LTD"; + case "HUASY": return "Huawei Symantec Technologies Co., Ltd."; + case "HYLINX": return "Hylinx Ltd."; + case "HYUNWON": return "HYUNWON inc"; + case "i-cubed": return "i-cubed ltd."; + case "IBM": return "International Business Machines"; + case "Icefield": return "Icefield Tools Corporation"; + case "Iceweb": return "Iceweb Storage Corp"; + case "ICL": return "ICL"; + case "ICP": return "ICP vortex Computersysteme GmbH"; + case "IDE": return "International Data Engineering, Inc."; + case "IDG": return "Interface Design Group"; + case "IET": return "ISCSI ENTERPRISE TARGET"; + case "IFT": return "Infortrend Technology, Inc."; + case "IGR": return "Intergraph Corp."; + case "IMAGINE": return "Imagine Communications Corp."; + case "IMAGO": return "IMAGO SOFTWARE SL"; + case "IMATION": return "Imation"; + case "IMPLTD": return "Integrated Micro Products Ltd."; + case "IMPRIMIS": return "Imprimis Technology Inc."; + case "INCIPNT": return "Incipient Technologies Inc."; + case "INCITS": return "InterNational Committee for Information Technology"; + case "INDCOMP": return "Industrial Computing Limited"; + case "Indigita": return "Indigita Corporation"; + case "INFOCORE": return "InfoCore"; + case "INITIO": return "Initio Corporation"; + case "INRANGE": return "INRANGE Technologies Corporation"; + case "Insight": return "L-3 Insight Technology Inc"; + case "INSITE": return "Insite Peripherals"; + case "integrix": return "Integrix, Inc."; + case "INTEL": return "Intel Corporation"; + case "Intransa": return "Intransa, Inc."; + case "IOC": return "I/O Concepts, Inc."; + case "iofy": return "iofy Corporation"; + case "IOMEGA": return "Iomega"; + case "IOT": return "IO Turbine, Inc."; + case "iPaper": return "intelliPaper, LLC"; + case "iqstor": return "iQstor Networks, Inc."; + case "iQue": return "iQue"; + case "ISi": return "Information Storage inc."; + case "Isilon": return "Isilon Systems, Inc."; + case "ISO": return "International Standards Organization"; + case "iStor": return "iStor Networks, Inc."; + case "ITC": return "International Tapetronics Corporation"; + case "iTwin": return "iTwin Pte Ltd"; + case "IVIVITY": return "iVivity, Inc."; + case "IVMMLTD": return "InnoVISION Multimedia Ltd."; + case "JABIL001": return "Jabil Circuit"; + case "JETWAY": return "Jetway Information Co., Ltd"; + case "JMR": return "JMR Electronics Inc."; + case "JOFEMAR": return "Jofemar"; + case "JOLLYLOG": return "Jolly Logic"; + case "JPC Inc.": return "JPC Inc."; + case "JSCSI": return "jSCSI Project"; + case "Juniper": return "Juniper Networks"; + case "JVC": return "JVC Information Products Co."; + case "KASHYA": return "Kashya, Inc."; + case "KENNEDY": return "Kennedy Company"; + case "KENWOOD": return "KENWOOD Corporation"; + case "KEWL": return "Shanghai KEWL Imp&Exp Co., Ltd."; + case "Key Tech": return "Key Technologies, Inc"; + case "KMNRIO": return "Kaminario Technologies Ltd."; + case "KODAK": return "Eastman Kodak"; + case "KONAN": return "Konan"; + case "koncepts": return "koncepts International Ltd."; + case "KONICA": return "Konica Japan"; + case "KOVE": return "KOVE"; + case "KSCOM": return "KSCOM Co. Ltd.,"; + case "KUDELSKI": return "Nagravision SA - Kudelski Group"; + case "Kyocera": return "Kyocera Corporation"; + case "Lapida": return "Gonmalo Electronics"; + case "LAPINE": return "Lapine Technology"; + case "LASERDRV": return "LaserDrive Limited"; + case "LASERGR": return "Lasergraphics, Inc."; + case "LeapFrog": return "LeapFrog Enterprises, Inc."; + case "LEFTHAND": return "LeftHand Networks"; + case "Leica": return "Leica Camera AG"; + case "Lexar": return "Lexar Media, Inc."; + case "LEYIO": return "LEYIO"; + case "LG": return "LG Electronics Inc."; + case "LGE": return "LG Electronics Inc."; + case "LIBNOVA": return "LIBNOVA, SL Digital Preservation Systems"; + case "LION": return "Lion Optics Corporation"; + case "LMS": return "Laser Magnetic Storage International Company"; + case "LoupTech": return "Loup Technologies, Inc."; + case "LSI": return "LSI Corp. (was LSI Logic Corp.)"; + case "LSILOGIC": return "LSI Logic Storage Systems, Inc."; + case "LTO-CVE": return "Linear Tape - Open, Compliance Verification Entity"; + case "LUXPRO": return "Luxpro Corporation"; + case "MacroSAN": return "MacroSAN Technologies Co., Ltd."; + case "Malakite": return "Malachite Technologies (New VID is: Sandial)"; + case "MarcBoon": return "marcboon.com"; + case "Marner": return "Marner Storage Technologies, Inc."; + case "MARVELL": return "Marvell Semiconductor, Inc."; + case "Matrix": return "Matrix Orbital Corp."; + case "MATSHITA": return "Matsushita"; + case "MAXELL": return "Hitachi Maxell, Ltd."; + case "MAXIM-IC": return "Maxim Integrated Products"; + case "MaxOptix": return "Maxoptix Corp."; + case "MAXSTRAT": return "Maximum Strategy, Inc."; + case "MAXTOR": return "Maxtor Corp."; + case "MaXXan": return "MaXXan Systems, Inc."; + case "MAYCOM": return "maycom Co., Ltd."; + case "MBEAT": return "K-WON C&C Co.,Ltd"; + case "MCC": return "Measurement Computing Corporation"; + case "McDATA": return "McDATA Corporation"; + case "MCUBE": return "Mcube Technology Co., Ltd."; + case "MDI": return "Micro Design International, Inc."; + case "MEADE": return "Meade Instruments Corporation"; + case "mediamat": return "mediamatic"; + case "MegaElec": return "Mega Electronics Ltd"; + case "MEII": return "Mountain Engineering II, Inc."; + case "MELA": return "Mitsubishi Electronics America"; + case "MELCO": return "Mitsubishi Electric (Japan)"; + case "mellanox": return "Mellanox Technologies Ltd."; + case "MEMOREX": return "Memorex Telex Japan Ltd."; + case "MEMREL": return "Memrel Corporation"; + case "MEMTECH": return "MemTech Technology"; + case "Mendocin": return "Mendocino Software"; + case "MendoCno": return "Mendocino Software"; + case "MERIDATA": return "Oy Meridata Finland Ltd"; + case "METHODEI": return "Methode Electronics India pvt ltd"; + case "METRUM": return "Metrum, Inc."; + case "MHTL": return "Matsunichi Hi-Tech Limited"; + case "MICROBTX": return "Microbotics Inc."; + case "Microchp": return "Microchip Technology, Inc."; + case "MICROLIT": return "Microlite Corporation"; + case "MICRON": return "Micron Technology, Inc."; + case "MICROP": return "Micropolis"; + case "MICROTEK": return "Microtek Storage Corp"; + case "Minitech": return "Minitech (UK) Limited"; + case "Minolta": return "Minolta Corporation"; + case "MINSCRIB": return "Miniscribe"; + case "MiraLink": return "MiraLink Corporation"; + case "Mirifica": return "Mirifica s.r.l."; + case "MITSUMI": return "Mitsumi Electric Co., Ltd."; + case "MKM": return "Mitsubishi Kagaku Media Co., LTD."; + case "Mobii": return "Mobii Systems (Pty.) Ltd."; + case "MOL": return "Petrosoft Sdn. Bhd."; + case "MOSAID": return "Mosaid Technologies Inc."; + case "MOTOROLA": return "Motorola"; + case "MP-400": return "Daiwa Manufacturing Limited"; + case "MPC": return "MPC Corporation"; + case "MPCCORP": return "MPC Computers"; + case "MPEYE": return "Touchstone Technology Co., Ltd"; + case "MPIO": return "DKT Co.,Ltd"; + case "MPM": return "Mitsubishi Paper Mills, Ltd."; + case "MPMan": return "MPMan.com, Inc."; + case "MSFT": return "Microsoft Corporation"; + case "MSI": return "Micro-Star International Corp."; + case "MST": return "Morning Star Technologies, Inc."; + case "MSystems": return "M-Systems Flash Disk Pioneers"; + case "MTI": return "MTI Technology Corporation"; + case "MTNGATE": return "MountainGate Data Systems"; + case "MXI": return "Memory Experts International"; + case "nac": return "nac Image Technology Inc."; + case "NAGRA": return "Nagravision SA - Kudelski Group"; + case "NAI": return "North Atlantic Industries"; + case "NAKAMICH": return "Nakamichi Corporation"; + case "NatInst": return "National Instruments"; + case "NatSemi": return "National Semiconductor Corp."; + case "NCITS": return "InterNational Committee for Information Technology Standards (INCITS)"; + case "NCL": return "NCL America"; + case "NCR": return "NCR Corporation"; + case "NDBTECH": return "NDB Technologie Inc."; + case "Neartek": return "Neartek, Inc."; + case "NEC": return "NEC"; + case "NETAPP": return "NetApp, Inc. (was Network Appliance)"; + case "NetBSD": return "The NetBSD Foundation"; + case "Netcom": return "Netcom Storage"; + case "NETENGIN": return "NetEngine, Inc."; + case "NEWISYS": return "Newisys Data Storage"; + case "Newtech": return "Newtech Co., Ltd."; + case "NEXSAN": return "Nexsan Technologies, Ltd."; + case "NFINIDAT": return "Infinidat Ltd."; + case "NHR": return "NH Research, Inc."; + case "Nike": return "Nike, Inc."; + case "Nimble": return "Nimble Storage"; + case "NISCA": return "NISCA Inc."; + case "NISHAN": return "Nishan Systems Inc."; + case "Nitz": return "Nitz Associates, Inc."; + case "NKK": return "NKK Corp."; + case "NRC": return "Nakamichi Research Corporation"; + case "NSD": return "Nippon Systems Development Co.,Ltd."; + case "NSM": return "NSM Jukebox GmbH"; + case "nStor": return "nStor Technologies, Inc."; + case "NT": return "Northern Telecom"; + case "NUCONNEX": return "NuConnex"; + case "NUSPEED": return "NuSpeed, Inc."; + case "NVIDIA": return "NVIDIA Corporation"; + case "NVMe": return "NVM Express Working Group"; + case "OAI": return "Optical Access International"; + case "OCE": return "Oce Graphics"; + case "ODS": return "ShenZhen DCS Group Co.,Ltd"; + case "OHDEN": return "Ohden Co., Ltd."; + case "OKI": return "OKI Electric Industry Co.,Ltd (Japan)"; + case "Olidata": return "Olidata S.p.A."; + case "OMI": return "Optical Media International"; + case "OMNIFI": return "Rockford Corporation - Omnifi Media"; + case "OMNIS": return "OMNIS Company (FRANCE)"; + case "Ophidian": return "Ophidian Designs"; + case "opslag": return "Tyrone Systems"; + case "Optelec": return "Optelec BV"; + case "Optiarc": return "Sony Optiarc Inc."; + case "OPTIMEM": return "Cipher/Optimem"; + case "OPTOTECH": return "Optotech"; + case "ORACLE": return "Oracle Corporation"; + case "ORANGE": return "Orange Micro, Inc."; + case "ORCA": return "Orca Technology"; + case "Origin": return "Origin Energy"; + case "OSI": return "Optical Storage International"; + case "OSNEXUS": return "OS NEXUS, Inc."; + case "OTL": return "OTL Engineering"; + case "OVERLAND": return "Overland Storage Inc."; + case "pacdigit": return "Pacific Digital Corp"; + case "Packard": return "Parkard Bell"; + case "Panasas": return "Panasas, Inc."; + case "PARALAN": return "Paralan Corporation"; + case "PASCOsci": return "Pasco Scientific"; + case "PATHLGHT": return "Pathlight Technology, Inc."; + case "PCS": return "Pro Charging Systems, LLC"; + case "PerStor": return "Perstor"; + case "PERTEC": return "Pertec Peripherals Corporation"; + case "PFTI": return "Performance Technology Inc."; + case "PFU": return "PFU Limited"; + case "Phigment": return "Phigment Technologies"; + case "PHILIPS": return "Philips Electronics"; + case "PICO": return "Packard Instrument Company"; + case "PIK": return "TECHNILIENT & MCS"; + case "Pillar": return "Pillar Data Systems"; + case "PIONEER": return "Pioneer Electronic Corp."; + case "Pirus": return "Pirus Networks"; + case "PIVOT3": return "Pivot3, Inc."; + case "PLASMON": return "Plasmon Data"; + case "Pliant": return "Pliant Technology, Inc."; + case "PMCSIERA": return "PMC-Sierra"; + case "PME": return "Precision Measurement Engineering"; + case "PNNMed": return "PNN Medical SA"; + case "POKEN": return "Poken SA"; + case "POLYTRON": return "PT. HARTONO ISTANA TEKNOLOGI"; + case "PRAIRIE": return "PrairieTek"; + case "PREPRESS": return "PrePRESS Solutions"; + case "PRESOFT": return "PreSoft Architects"; + case "PRESTON": return "Preston Scientific"; + case "PRIAM": return "Priam"; + case "PRIMAGFX": return "Primagraphics Ltd"; + case "PRIMOS": return "Primos"; + case "PROCOM": return "Procom Technology"; + case "PROLIFIC": return "Prolific Technology Inc."; + case "PROMISE": return "PROMISE TECHNOLOGY, Inc"; + case "PROSTOR": return "ProStor Systems, Inc."; + case "PROSUM": return "PROSUM"; + case "PROWARE": return "Proware Technology Corp."; + case "PTI": return "Peripheral Technology Inc."; + case "PTICO": return "Pacific Technology International"; + case "PURE": return "PURE Storage"; + case "Qi-Hardw": return "Qi Hardware"; + case "QIC": return "Quarter-Inch Cartridge Drive Standards, Inc."; + case "QLogic": return "QLogic Corporation"; + case "QNAP": return "QNAP Systems"; + case "Qsan": return "QSAN Technology, Inc."; + case "QUALSTAR": return "Qualstar"; + case "QUANTEL": return "Quantel Ltd."; + case "QUANTUM": return "Quantum Corp."; + case "QUIX": return "Quix Computerware AG"; + case "R-BYTE": return "R-Byte, Inc."; + case "RACALREC": return "Racal Recorders"; + case "RADITEC": return "Radikal Technologies Deutschland GmbH"; + case "RADSTONE": return "Radstone Technology"; + case "RAIDINC": return "RAID Inc."; + case "RASSYS": return "Rasilient Systems Inc."; + case "RASVIA": return "Rasvia Systems, Inc."; + case "rave-mp": return "Go Video"; + case "RDKMSTG": return "MMS Dipl. Ing. Rolf-Dieter Klein"; + case "RDStor": return "Rorke China"; + case "Readboy": return "Readboy Ltd Co."; + case "Realm": return "Realm Systems"; + case "realtek": return "Realtek Semiconductor Corp."; + case "REDUXIO": return "Reduxio Systems Ltd."; + case "rehanltd": return "Rehan Electronics Ltd"; + case "REKA": return "REKA HEALTH PTE LTD"; + case "RELDATA": return "RELDATA Inc"; + case "RENAGmbH": return "RENA GmbH"; + case "ReThinkM": return "RETHINK MEDICAL, INC"; + case "Revivio": return "Revivio, Inc."; + case "RGBLaser": return "RGB Lasersysteme GmbH"; + case "RGI": return "Raster Graphics, Inc."; + case "RHAPSODY": return "Rhapsody Networks, Inc."; + case "RHS": return "Racal-Heim Systems GmbH"; + case "RICOH": return "Ricoh"; + case "RODIME": return "Rodime"; + case "Rorke": return "RD DATA Technology (ShenZhen) Limited"; + case "Royaltek": return "RoyalTek company Ltd."; + case "RPS": return "RPS"; + case "RTI": return "Reference Technology"; + case "S-D": return "Sauer-Danfoss"; + case "S-flex": return "Storageflex Inc"; + case "S-SYSTEM": return "S-SYSTEM"; + case "S1": return "storONE"; + case "SAMSUNG": return "Samsung Electronics Co., Ltd."; + case "SAN": return "Storage Area Networks, Ltd."; + case "Sandial": return "Sandial Systems, Inc."; + case "SanDisk": return "SanDisk Corporation"; + case "SANKYO": return "Sankyo Seiki"; + case "SANRAD": return "SANRAD Inc."; + case "SANYO": return "SANYO Electric Co., Ltd."; + case "SC.Net": return "StorageConnections.Net"; + case "SCALE": return "Scale Computing, Inc."; + case "SCIENTEK": return "SCIENTEK CORP"; + case "SCInc.": return "Storage Concepts, Inc."; + case "SCREEN": return "Dainippon Screen Mfg. Co., Ltd."; + case "SDI": return "Storage Dimensions, Inc."; + case "SDS": return "Solid Data Systems"; + case "SEAC": return "SeaChange International, Inc."; + case "SEAGATE": return "Seagate"; + case "SEAGRAND": return "SEAGRAND In Japan"; + case "Seanodes": return "Seanodes"; + case "Sec. Key": return "SecureKey Technologies Inc."; + case "SEQUOIA": return "Sequoia Advanced Technologies, Inc."; + case "SGI": return "Silicon Graphics International"; + case "Shannon": return "Shannon Systems Co., Ltd."; + case "Shinko": return "Shinko Electric Co., Ltd."; + case "SIEMENS": return "Siemens"; + case "SigmaTel": return "SigmaTel, Inc."; + case "SII": return "Seiko Instruments Inc."; + case "SIMPLE": return "SimpleTech, Inc."; + case "SIVMSD": return "IMAGO SOFTWARE SL"; + case "SKhynix": return "SK hynix Inc."; + case "SLCNSTOR": return "SiliconStor, Inc."; + case "SLI": return "Sierra Logic, Inc."; + case "SMCI": return "Super Micro Computer, Inc."; + case "SmrtStor": return "Smart Storage Systems"; + case "SMS": return "Scientific Micro Systems/OMTI"; + case "SMSC": return "SMSC Storage, Inc."; + case "SMX": return "Smartronix, Inc."; + case "SNYSIDE": return "Sunnyside Computing Inc."; + case "SoftLock": return "Softlock Digital Security Provider"; + case "SolidFir": return "SolidFire, Inc."; + case "SONIC": return "Sonic Solutions"; + case "SoniqCas": return "SoniqCast"; + case "SONY": return "Sony Corporation Japan"; + case "SOUL": return "Soul Storage Technology (Wuxi) Co., Ltd"; + case "SPD": return "Storage Products Distribution, Inc."; + case "SPECIAL": return "Special Computing Co."; + case "SPECTRA": return "Spectra Logic, a Division of Western Automation Labs, Inc."; + case "SPERRY": return "Sperry"; + case "Spintso": return "Spintso International AB"; + case "STARBORD": return "Starboard Storage Systems, Inc."; + case "STARWIND": return "StarWind Software, Inc."; + case "STEC": return "STEC, Inc."; + case "Sterling": return "Sterling Diagnostic Imaging, Inc."; + case "STK": return "Storage Technology Corporation"; + case "STNWOOD": return "Stonewood Group"; + case "STONEFLY": return "StoneFly Networks, Inc."; + case "STOR": return "StorageNetworks, Inc."; + case "STORAPP": return "StorageApps, Inc."; + case "STORCIUM": return "Intelligent Systems Services Inc."; + case "STORCOMP": return "Storage Computer Corporation"; + case "STORM": return "Storm Technology, Inc."; + case "StorMagc": return "StorMagic"; + case "Stratus": return "Stratus Technologies"; + case "StrmLgc": return "StreamLogic Corp."; + case "SUMITOMO": return "Sumitomo Electric Industries, Ltd."; + case "SUN": return "Sun Microsystems, Inc."; + case "SUNCORP": return "SunCorporation"; + case "suntx": return "Suntx System Co., Ltd"; + case "SUSE": return "SUSE Linux"; + case "Swinxs": return "Swinxs BV"; + case "SYMANTEC": return "Symantec Corporation"; + case "SYMBIOS": return "Symbios Logic Inc."; + case "SYMWAVE": return "Symwave, Inc."; + case "SYNCSORT": return "Syncsort Incorporated"; + case "SYNERWAY": return "Synerway"; + case "SYNOLOGY": return "Synology, Inc."; + case "SyQuest": return "SyQuest Technology, Inc."; + case "SYSGEN": return "Sysgen"; + case "T-MITTON": return "Transmitton England"; + case "T-MOBILE": return "T-Mobile USA, Inc."; + case "T11": return "INCITS Technical Committee T11"; + case "TALARIS": return "Talaris Systems, Inc."; + case "TALLGRAS": return "Tallgrass Technologies"; + case "TANDBERG": return "Tandberg Data A/S"; + case "TANDEM": return "Tandem"; + case "TANDON": return "Tandon"; + case "TCL": return "TCL Shenzhen ASIC MIcro-electronics Ltd"; + case "TDK": return "TDK Corporation"; + case "TEAC": return "TEAC Japan"; + case "TECOLOTE": return "Tecolote Designs"; + case "TEGRA": return "Tegra Varityper"; + case "Teilch": return "Teilch"; + case "Tek": return "Tektronix"; + case "TELLERT": return "Tellert Elektronik GmbH"; + case "TENTIME": return "Laura Technologies, Inc."; + case "TFDATACO": return "TimeForge"; + case "TGEGROUP": return "TGE Group Co.,LTD."; + case "Thecus": return "Thecus Technology Corp."; + case "TI-DSG": return "Texas Instruments"; + case "TiGi": return "TiGi Corporation"; + case "TILDESGN": return "Tildesign bv"; + case "Tite": return "Tite Technology Limited"; + case "TKS Inc.": return "TimeKeeping Systems, Inc."; + case "TLMKS": return "Telemakus LLC"; + case "TMS": return "Texas Memory Systems, Inc."; + case "TMS100": return "TechnoVas"; + case "TOLISGRP": return "The TOLIS Group"; + case "TOSHIBA": return "Toshiba Japan"; + case "TOYOU": return "TOYOU FEIJI ELECTRONICS CO.,LTD."; + case "Tracker": return "Tracker, LLC"; + case "TRIOFLEX": return "Trioflex Oy"; + case "TRIPACE": return "Tripace"; + case "TRLogger": return "TrueLogger Ltd."; + case "TROIKA": return "Troika Networks, Inc."; + case "TRULY": return "TRULY Electronics MFG. LTD."; + case "TRUSTED": return "Trusted Data Corporation"; + case "TSSTcorp": return "Toshiba Samsung Storage Technology Corporation"; + case "TZM": return "TZ Medical"; + case "UD-DVR": return "Bigstone Project."; + case "UDIGITAL": return "United Digital Limited"; + case "UIT": return "United Infomation Technology"; + case "ULTRA": return "UltraStor Corporation"; + case "UNISTOR": return "Unistor Networks, Inc."; + case "UNISYS": return "Unisys"; + case "USCORE": return "Underscore, Inc."; + case "USDC": return "US Design Corp."; + case "Top VASCO": return "Vasco Data Security"; + case "VDS": return "Victor Data Systems Co., Ltd."; + case "VELDANA": return "VELDANA MEDICAL SA"; + case "VENTANA": return "Ventana Medical Systems"; + case "Verari": return "Verari Systems, Inc."; + case "VERBATIM": return "Verbatim Corporation"; + case "Vercet": return "Vercet LLC"; + case "VERITAS": return "VERITAS Software Corporation"; + case "Vexata": return "Vexata Inc"; + case "VEXCEL": return "VEXCEL IMAGING GmbH"; + case "VICOMSL1": return "Vicom Systems, Inc."; + case "VicomSys": return "Vicom Systems, Inc."; + case "VIDEXINC": return "Videx, Inc."; + case "VIOLIN": return "Violin Memory, Inc."; + case "VIRIDENT": return "Virident Systems, Inc."; + case "VITESSE": return "Vitesse Semiconductor Corporation"; + case "VIXEL": return "Vixel Corporation"; + case "VLS": return "Van Lent Systems BV"; + case "VMAX": return "VMAX Technologies Corp."; + case "VMware": return "VMware Inc."; + case "Vobis": return "Vobis Microcomputer AG"; + case "VOLTAIRE": return "Voltaire Ltd."; + case "VRC": return "Vermont Research Corp."; + case "VRugged": return "Vanguard Rugged Storage"; + case "VTGadget": return "Vermont Gadget Company"; + case "Waitec": return "Waitec NV"; + case "WangDAT": return "WangDAT"; + case "WANGTEK": return "Wangtek"; + case "Wasabi": return "Wasabi Systems"; + case "WAVECOM": return "Wavecom"; + case "WD": return "Western Digital Corporation"; + case "WDC": return "Western Digital Corporation"; + case "WDIGTL": return "Western Digital"; + case "WDTI": return "Western Digital Technologies, Inc."; + case "WEARNES": return "Wearnes Technology Corporation"; + case "WeeraRes": return "Weera Research Pte Ltd"; + case "Wildflwr": return "Wildflower Technologies, Inc."; + case "WSC0001": return "Wisecom, Inc."; + case "X3": return "InterNational Committee for Information Technology Standards (INCITS)"; + case "XEBEC": return "Xebec Corporation"; + case "XENSRC": return "XenSource, Inc."; + case "Xerox": return "Xerox Corporation"; + case "XIOtech": return "XIOtech Corporation"; + case "XIRANET": return "Xiranet Communications GmbH"; + case "XIV": return "XIV"; + case "XtremIO": return "XtremIO"; + case "XYRATEX": return "Xyratex"; + case "YINHE": return "NUDT Computer Co."; + case "YIXUN": return "Yixun Electronic Co.,Ltd."; + case "YOTTA": return "YottaYotta, Inc."; + case "Zarva": return "Zarva Digital Technology Co., Ltd."; + case "ZETTA": return "Zetta Systems, Inc."; + case "ZTE": return "ZTE Corporation"; + case "ZVAULT": return "Zetavault"; + default: return scsiVendorString; + } + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SecureDigital/CID.cs b/Aaru.Decoders/SecureDigital/CID.cs new file mode 100644 index 000000000..2c293fae8 --- /dev/null +++ b/Aaru.Decoders/SecureDigital/CID.cs @@ -0,0 +1,129 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CID.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SecureDigital CID. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Helpers; + +namespace Aaru.Decoders.SecureDigital +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public class CID + { + public string ApplicationID; + public byte CRC; + public byte Manufacturer; + public ushort ManufacturingDate; + public string ProductName; + public byte ProductRevision; + public uint ProductSerialNumber; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Decoders + { + public static CID DecodeCID(uint[] response) + { + if(response?.Length != 4) + return null; + + byte[] data = new byte[16]; + + byte[] tmp = BitConverter.GetBytes(response[0]); + Array.Copy(tmp, 0, data, 0, 4); + tmp = BitConverter.GetBytes(response[1]); + Array.Copy(tmp, 0, data, 4, 4); + tmp = BitConverter.GetBytes(response[2]); + Array.Copy(tmp, 0, data, 8, 4); + tmp = BitConverter.GetBytes(response[3]); + Array.Copy(tmp, 0, data, 12, 4); + + return DecodeCID(data); + } + + public static CID DecodeCID(byte[] response) + { + if(response?.Length != 16) + return null; + + var cid = new CID + { + Manufacturer = response[0], + ProductRevision = response[8], + ProductSerialNumber = Swapping.Swap(BitConverter.ToUInt32(response, 9)), + ManufacturingDate = (ushort)(((response[13] & 0x0F) << 8) + response[14]), + CRC = (byte)((response[15] & 0xFE) >> 1) + }; + + byte[] tmp = new byte[2]; + Array.Copy(response, 1, tmp, 0, 2); + cid.ApplicationID = StringHandlers.CToString(tmp); + tmp = new byte[5]; + Array.Copy(response, 3, tmp, 0, 5); + cid.ProductName = StringHandlers.CToString(tmp); + + return cid; + } + + public static string PrettifyCID(CID cid) + { + if(cid == null) + return null; + + var sb = new StringBuilder(); + + sb.AppendLine("SecureDigital Device Identification Register:"); + sb.AppendFormat("\tManufacturer: {0}", VendorString.Prettify(cid.Manufacturer)).AppendLine(); + sb.AppendFormat("\tApplication ID: {0}", cid.ApplicationID).AppendLine(); + sb.AppendFormat("\tProduct name: {0}", cid.ProductName).AppendLine(); + + sb.AppendFormat("\tProduct revision: {0:X2}.{1:X2}", (cid.ProductRevision & 0xF0) >> 4, + cid.ProductRevision & 0x0F).AppendLine(); + + sb.AppendFormat("\tProduct serial number: {0}", cid.ProductSerialNumber).AppendLine(); + + sb.AppendFormat("\tDevice manufactured month {0} of {1}", (cid.ManufacturingDate & 0xF00) >> 8, + (cid.ManufacturingDate & 0xFF) + 2000).AppendLine(); + + sb.AppendFormat("\tCID CRC: 0x{0:X2}", cid.CRC).AppendLine(); + + return sb.ToString(); + } + + public static string PrettifyCID(uint[] response) => PrettifyCID(DecodeCID(response)); + + public static string PrettifyCID(byte[] response) => PrettifyCID(DecodeCID(response)); + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SecureDigital/CSD.cs b/Aaru.Decoders/SecureDigital/CSD.cs new file mode 100644 index 000000000..ecace4518 --- /dev/null +++ b/Aaru.Decoders/SecureDigital/CSD.cs @@ -0,0 +1,654 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CSD.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SecureDigital CSD. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SecureDigital +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public class CSD + { + public ushort Classes; + public bool Copy; + public byte CRC; + public bool DSRImplemented; + public bool EraseBlockEnable; + public byte EraseSectorSize; + public byte FileFormat; + public bool FileFormatGroup; + public byte NSAC; + public bool PermanentWriteProtect; + public byte ReadBlockLength; + public byte ReadCurrentAtVddMax; + public byte ReadCurrentAtVddMin; + public bool ReadMisalignment; + public bool ReadsPartialBlocks; + public uint Size; + public byte SizeMultiplier; + public byte Speed; + public byte Structure; + public byte TAAC; + public bool TemporaryWriteProtect; + public byte WriteBlockLength; + public byte WriteCurrentAtVddMax; + public byte WriteCurrentAtVddMin; + public bool WriteMisalignment; + public bool WriteProtectGroupEnable; + public byte WriteProtectGroupSize; + public bool WritesPartialBlocks; + public byte WriteSpeedFactor; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Decoders + { + public static CSD DecodeCSD(uint[] response) + { + if(response?.Length != 4) + return null; + + byte[] data = new byte[16]; + + byte[] tmp = BitConverter.GetBytes(response[0]); + Array.Copy(tmp, 0, data, 0, 4); + tmp = BitConverter.GetBytes(response[1]); + Array.Copy(tmp, 0, data, 4, 4); + tmp = BitConverter.GetBytes(response[2]); + Array.Copy(tmp, 0, data, 8, 4); + tmp = BitConverter.GetBytes(response[3]); + Array.Copy(tmp, 0, data, 12, 4); + + return DecodeCSD(data); + } + + public static CSD DecodeCSD(byte[] response) + { + if(response?.Length != 16) + return null; + + var csd = new CSD + { + Structure = (byte)((response[0] & 0xC0) >> 6), + TAAC = response[1], + NSAC = response[2], + Speed = response[3], + Classes = (ushort)((response[4] << 4) + ((response[5] & 0xF0) >> 4)), + ReadBlockLength = (byte)(response[5] & 0x0F), + ReadsPartialBlocks = (response[6] & 0x80) == 0x80, + WriteMisalignment = (response[6] & 0x40) == 0x40, + ReadMisalignment = (response[6] & 0x20) == 0x20, + DSRImplemented = (response[6] & 0x10) == 0x10, + EraseBlockEnable = (response[10] & 0x40) == 0x40, + EraseSectorSize = (byte)(((response[10] & 0x3F) << 1) + ((response[11] & 0x80) >> 7)), + WriteProtectGroupSize = (byte)(response[11] & 0x7F), + WriteProtectGroupEnable = (response[12] & 0x80) == 0x80, + WriteSpeedFactor = (byte)((response[12] & 0x1C) >> 2), + WriteBlockLength = (byte)(((response[12] & 0x03) << 2) + ((response[13] & 0xC0) >> 6)), + WritesPartialBlocks = (response[13] & 0x20) == 0x20, + FileFormatGroup = (response[14] & 0x80) == 0x80, + Copy = (response[14] & 0x40) == 0x40, + PermanentWriteProtect = (response[14] & 0x20) == 0x20, + TemporaryWriteProtect = (response[14] & 0x10) == 0x10, + FileFormat = (byte)((response[14] & 0x0C) >> 2), + CRC = (byte)((response[15] & 0xFE) >> 1) + }; + + if(csd.Structure == 0) + { + csd.Size = (ushort)(((response[6] & 0x03) << 10) + (response[7] << 2) + ((response[8] & 0xC0) >> 6)); + + csd.ReadCurrentAtVddMin = (byte)((response[8] & 0x38) >> 3); + csd.ReadCurrentAtVddMax = (byte)(response[8] & 0x07); + csd.WriteCurrentAtVddMin = (byte)((response[9] & 0xE0) >> 5); + csd.WriteCurrentAtVddMax = (byte)((response[9] & 0x1C) >> 2); + csd.SizeMultiplier = (byte)(((response[9] & 0x03) << 1) + ((response[10] & 0x80) >> 7)); + } + else + csd.Size = (uint)(((response[7] & 0x3F) << 16) + (response[8] << 8) + response[9]); + + return csd; + } + + public static string PrettifyCSD(CSD csd) + { + if(csd == null) + return null; + + double unitFactor = 0; + double multiplier = 0; + string unit = ""; + + var sb = new StringBuilder(); + sb.AppendLine("SecureDigital Device Specific Data Register:"); + + switch(csd.Structure) + { + case 0: + sb.AppendLine("\tRegister version 1.0"); + + break; + case 1: + sb.AppendLine("\tRegister version 2.0"); + + break; + } + + switch(csd.TAAC & 0x07) + { + case 0: + unit = "ns"; + unitFactor = 1; + + break; + case 1: + unit = "ns"; + unitFactor = 10; + + break; + case 2: + unit = "ns"; + unitFactor = 100; + + break; + case 3: + unit = "μs"; + unitFactor = 1; + + break; + case 4: + unit = "μs"; + unitFactor = 10; + + break; + case 5: + unit = "μs"; + unitFactor = 100; + + break; + case 6: + unit = "ms"; + unitFactor = 1; + + break; + case 7: + unit = "ms"; + unitFactor = 10; + + break; + } + + switch((csd.TAAC & 0x78) >> 3) + { + case 0: + multiplier = 0; + + break; + case 1: + multiplier = 1; + + break; + case 2: + multiplier = 1.2; + + break; + case 3: + multiplier = 1.3; + + break; + case 4: + multiplier = 1.5; + + break; + case 5: + multiplier = 2; + + break; + case 6: + multiplier = 2.5; + + break; + case 7: + multiplier = 3; + + break; + case 8: + multiplier = 3.5; + + break; + case 9: + multiplier = 4; + + break; + case 10: + multiplier = 4.5; + + break; + case 11: + multiplier = 5; + + break; + case 12: + multiplier = 5.5; + + break; + case 13: + multiplier = 6; + + break; + case 14: + multiplier = 7; + + break; + case 15: + multiplier = 8; + + break; + } + + double result = unitFactor * multiplier; + sb.AppendFormat("\tAsynchronous data access time is {0}{1}", result, unit).AppendLine(); + + sb.AppendFormat("\tClock dependent part of data access is {0} clock cycles", csd.NSAC * 100).AppendLine(); + + unit = "MBit/s"; + + switch(csd.Speed & 0x07) + { + case 0: + unitFactor = 0.1; + + break; + case 1: + unitFactor = 1; + + break; + case 2: + unitFactor = 10; + + break; + case 3: + unitFactor = 100; + + break; + default: + unit = "unknown"; + unitFactor = 0; + + break; + } + + switch((csd.Speed & 0x78) >> 3) + { + case 0: + multiplier = 0; + + break; + case 1: + multiplier = 1; + + break; + case 2: + multiplier = 1.2; + + break; + case 3: + multiplier = 1.3; + + break; + case 4: + multiplier = 1.5; + + break; + case 5: + multiplier = 2; + + break; + case 6: + multiplier = 2.6; + + break; + case 7: + multiplier = 3; + + break; + case 8: + multiplier = 3.5; + + break; + case 9: + multiplier = 4; + + break; + case 10: + multiplier = 4.5; + + break; + case 11: + multiplier = 5.2; + + break; + case 12: + multiplier = 5.5; + + break; + case 13: + multiplier = 6; + + break; + case 14: + multiplier = 7; + + break; + case 15: + multiplier = 8; + + break; + } + + result = unitFactor * multiplier; + sb.AppendFormat("\tDevice's transfer speed: {0}{1}", result, unit).AppendLine(); + + unit = ""; + + for(int cl = 0, mask = 1; cl <= 11; cl++, mask <<= 1) + if((csd.Classes & mask) == mask) + unit += $" {cl}"; + + sb.AppendFormat("\tDevice support command classes {0}", unit).AppendLine(); + sb.AppendFormat("\tRead block length is {0} bytes", Math.Pow(2, csd.ReadBlockLength)).AppendLine(); + + if(csd.ReadsPartialBlocks) + sb.AppendLine("\tDevice allows reading partial blocks"); + + if(csd.WriteMisalignment) + sb.AppendLine("\tWrite commands can cross physical block boundaries"); + + if(csd.ReadMisalignment) + sb.AppendLine("\tRead commands can cross physical block boundaries"); + + if(csd.DSRImplemented) + sb.AppendLine("\tDevice implements configurable driver stage"); + + if(csd.Structure == 0) + { + result = (csd.Size + 1) * Math.Pow(2, csd.SizeMultiplier + 2); + sb.AppendFormat("\tDevice has {0} blocks", (int)result).AppendLine(); + + result = (csd.Size + 1) * Math.Pow(2, csd.SizeMultiplier + 2) * Math.Pow(2, csd.ReadBlockLength); + + if(result > 1073741824) + sb.AppendFormat("\tDevice has {0} GiB", result / 1073741824.0).AppendLine(); + else if(result > 1048576) + sb.AppendFormat("\tDevice has {0} MiB", result / 1048576.0).AppendLine(); + else if(result > 1024) + sb.AppendFormat("\tDevice has {0} KiB", result / 1024.0).AppendLine(); + else + sb.AppendFormat("\tDevice has {0} bytes", result).AppendLine(); + } + else + { + sb.AppendFormat("\tDevice has {0} blocks", (csd.Size + 1) * 1024).AppendLine(); + result = ((ulong)csd.Size + 1) * 1024 * 512; + + if(result > 1099511627776) + sb.AppendFormat("\tDevice has {0} TiB", result / 1099511627776.0).AppendLine(); + else if(result > 1073741824) + sb.AppendFormat("\tDevice has {0} GiB", result / 1073741824.0).AppendLine(); + else if(result > 1048576) + sb.AppendFormat("\tDevice has {0} MiB", result / 1048576.0).AppendLine(); + else if(result > 1024) + sb.AppendFormat("\tDevice has {0} KiB", result / 1024.0).AppendLine(); + else + sb.AppendFormat("\tDevice has {0} bytes", result).AppendLine(); + } + + if(csd.Structure == 0) + { + switch(csd.ReadCurrentAtVddMin & 0x07) + { + case 0: + sb.AppendLine("\tDevice uses a maximum of 0.5mA for reading at minimum voltage"); + + break; + case 1: + sb.AppendLine("\tDevice uses a maximum of 1mA for reading at minimum voltage"); + + break; + case 2: + sb.AppendLine("\tDevice uses a maximum of 5mA for reading at minimum voltage"); + + break; + case 3: + sb.AppendLine("\tDevice uses a maximum of 10mA for reading at minimum voltage"); + + break; + case 4: + sb.AppendLine("\tDevice uses a maximum of 25mA for reading at minimum voltage"); + + break; + case 5: + sb.AppendLine("\tDevice uses a maximum of 35mA for reading at minimum voltage"); + + break; + case 6: + sb.AppendLine("\tDevice uses a maximum of 60mA for reading at minimum voltage"); + + break; + case 7: + sb.AppendLine("\tDevice uses a maximum of 100mA for reading at minimum voltage"); + + break; + } + + switch(csd.ReadCurrentAtVddMax & 0x07) + { + case 0: + sb.AppendLine("\tDevice uses a maximum of 1mA for reading at maximum voltage"); + + break; + case 1: + sb.AppendLine("\tDevice uses a maximum of 5mA for reading at maximum voltage"); + + break; + case 2: + sb.AppendLine("\tDevice uses a maximum of 10mA for reading at maximum voltage"); + + break; + case 3: + sb.AppendLine("\tDevice uses a maximum of 25mA for reading at maximum voltage"); + + break; + case 4: + sb.AppendLine("\tDevice uses a maximum of 35mA for reading at maximum voltage"); + + break; + case 5: + sb.AppendLine("\tDevice uses a maximum of 45mA for reading at maximum voltage"); + + break; + case 6: + sb.AppendLine("\tDevice uses a maximum of 80mA for reading at maximum voltage"); + + break; + case 7: + sb.AppendLine("\tDevice uses a maximum of 200mA for reading at maximum voltage"); + + break; + } + + switch(csd.WriteCurrentAtVddMin & 0x07) + { + case 0: + sb.AppendLine("\tDevice uses a maximum of 0.5mA for writing at minimum voltage"); + + break; + case 1: + sb.AppendLine("\tDevice uses a maximum of 1mA for writing at minimum voltage"); + + break; + case 2: + sb.AppendLine("\tDevice uses a maximum of 5mA for writing at minimum voltage"); + + break; + case 3: + sb.AppendLine("\tDevice uses a maximum of 10mA for writing at minimum voltage"); + + break; + case 4: + sb.AppendLine("\tDevice uses a maximum of 25mA for writing at minimum voltage"); + + break; + case 5: + sb.AppendLine("\tDevice uses a maximum of 35mA for writing at minimum voltage"); + + break; + case 6: + sb.AppendLine("\tDevice uses a maximum of 60mA for writing at minimum voltage"); + + break; + case 7: + sb.AppendLine("\tDevice uses a maximum of 100mA for writing at minimum voltage"); + + break; + } + + switch(csd.WriteCurrentAtVddMax & 0x07) + { + case 0: + sb.AppendLine("\tDevice uses a maximum of 1mA for writing at maximum voltage"); + + break; + case 1: + sb.AppendLine("\tDevice uses a maximum of 5mA for writing at maximum voltage"); + + break; + case 2: + sb.AppendLine("\tDevice uses a maximum of 10mA for writing at maximum voltage"); + + break; + case 3: + sb.AppendLine("\tDevice uses a maximum of 25mA for writing at maximum voltage"); + + break; + case 4: + sb.AppendLine("\tDevice uses a maximum of 35mA for writing at maximum voltage"); + + break; + case 5: + sb.AppendLine("\tDevice uses a maximum of 45mA for writing at maximum voltage"); + + break; + case 6: + sb.AppendLine("\tDevice uses a maximum of 80mA for writing at maximum voltage"); + + break; + case 7: + sb.AppendLine("\tDevice uses a maximum of 200mA for writing at maximum voltage"); + + break; + } + + if(csd.EraseBlockEnable) + sb.AppendLine("\tDevice can erase multiple blocks"); + + // TODO: Check specification + sb.AppendFormat("\tDevice must erase a minimum of {0} blocks at a time", + Convert.ToUInt32(csd.EraseSectorSize) + 1).AppendLine(); + + if(csd.WriteProtectGroupEnable) + { + sb.AppendLine("\tDevice can write protect regions"); + + // TODO: Check specification + // unitFactor = Convert.ToDouble(csd.WriteProtectGroupSize); + + sb.AppendFormat("\tDevice can write protect a minimum of {0} blocks at a time", (int)(result + 1)). + AppendLine(); + } + else + sb.AppendLine("\tDevice can't write protect regions"); + } + + sb.AppendFormat("\tWriting is {0} times slower than reading", Math.Pow(2, csd.WriteSpeedFactor)). + AppendLine(); + + sb.AppendFormat("\tWrite block length is {0} bytes", Math.Pow(2, csd.WriteBlockLength)).AppendLine(); + + if(csd.WritesPartialBlocks) + sb.AppendLine("\tDevice allows writing partial blocks"); + + if(!csd.Copy) + sb.AppendLine("\tDevice contents are original"); + + if(csd.PermanentWriteProtect) + sb.AppendLine("\tDevice is permanently write protected"); + + if(csd.TemporaryWriteProtect) + sb.AppendLine("\tDevice is temporarily write protected"); + + if(!csd.FileFormatGroup) + switch(csd.FileFormat) + { + case 0: + sb.AppendLine("\tDevice is formatted like a hard disk"); + + break; + case 1: + sb.AppendLine("\tDevice is formatted like a floppy disk using Microsoft FAT"); + + break; + case 2: + sb.AppendLine("\tDevice uses Universal File Format"); + + break; + default: + sb.AppendFormat("\tDevice uses unknown file format code {0}", csd.FileFormat).AppendLine(); + + break; + } + else + sb.AppendFormat("\tDevice uses unknown file format code {0} and file format group 1", csd.FileFormat). + AppendLine(); + + sb.AppendFormat("\tCSD CRC: 0x{0:X2}", csd.CRC).AppendLine(); + + return sb.ToString(); + } + + public static string PrettifyCSD(uint[] response) => PrettifyCSD(DecodeCSD(response)); + + public static string PrettifyCSD(byte[] response) => PrettifyCSD(DecodeCSD(response)); + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SecureDigital/OCR.cs b/Aaru.Decoders/SecureDigital/OCR.cs new file mode 100644 index 000000000..c92b71088 --- /dev/null +++ b/Aaru.Decoders/SecureDigital/OCR.cs @@ -0,0 +1,144 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : OCR.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SecureDigital OCR. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Helpers; + +namespace Aaru.Decoders.SecureDigital +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "UnassignedField.Global"), + SuppressMessage("ReSharper", "NotAccessedField.Global")] + public class OCR + { + public bool CCS; + public bool LowPower; + public bool OneEight; + public bool PowerUp; + public bool ThreeFive; + public bool ThreeFour; + public bool ThreeOne; + public bool ThreeThree; + public bool ThreeTwo; + public bool ThreeZero; + public bool TwoEight; + public bool TwoNine; + public bool TwoSeven; + public bool UHS; + } + + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static partial class Decoders + { + public static OCR DecodeOCR(uint response) + { + response = Swapping.Swap(response); + + return new OCR + { + PowerUp = (response & 0x80000000) == 0x80000000, + CCS = (response & 0x40000000) == 0x40000000, + UHS = (response & 0x20000000) == 0x20000000, + OneEight = (response & 0x01000000) == 0x01000000, + ThreeFive = (response & 0x00800000) == 0x00800000, + ThreeFour = (response & 0x00400000) == 0x00400000, + ThreeThree = (response & 0x00200000) == 0x00200000, + ThreeTwo = (response & 0x00100000) == 0x00100000, + ThreeOne = (response & 0x00080000) == 0x00080000, + ThreeZero = (response & 0x00040000) == 0x00040000, + TwoNine = (response & 0x00020000) == 0x00020000, + TwoEight = (response & 0x00010000) == 0x00010000, + TwoSeven = (response & 0x00008000) == 0x00008000, + LowPower = (response & 0x00000080) == 0x00000080 + }; + } + + public static OCR DecodeOCR(byte[] response) => + response?.Length != 4 ? null : DecodeOCR(BitConverter.ToUInt32(response, 0)); + + public static string PrettifyOCR(OCR ocr) + { + if(ocr == null) + return null; + + var sb = new StringBuilder(); + sb.AppendLine("SecureDigital Operation Conditions Register:"); + + if(!ocr.PowerUp) + sb.AppendLine("\tDevice is powering up"); + + if(ocr.CCS) + sb.AppendLine("\tDevice is SDHC, SDXC or higher"); + + if(ocr.UHS) + sb.AppendLine("\tDevice is UHS-II or higher"); + + if(ocr.ThreeFive) + sb.AppendLine("\tDevice can work with supply 3.5~3.6V"); + + if(ocr.ThreeFour) + sb.AppendLine("\tDevice can work with supply 3.4~3.5V"); + + if(ocr.ThreeThree) + sb.AppendLine("\tDevice can work with supply 3.3~3.4V"); + + if(ocr.ThreeTwo) + sb.AppendLine("\tDevice can work with supply 3.2~3.3V"); + + if(ocr.ThreeOne) + sb.AppendLine("\tDevice can work with supply 3.1~3.2V"); + + if(ocr.TwoNine) + sb.AppendLine("\tDevice can work with supply 2.9~3.0V"); + + if(ocr.TwoEight) + sb.AppendLine("\tDevice can work with supply 2.8~2.9V"); + + if(ocr.TwoSeven) + sb.AppendLine("\tDevice can work with supply 2.7~2.8V"); + + if(ocr.OneEight) + sb.AppendLine("\tDevice can switch to work with 1.8V supply"); + + if(ocr.LowPower) + sb.AppendLine("\tDevice is in low power mode"); + + return sb.ToString(); + } + + public static string PrettifyOCR(byte[] response) => PrettifyOCR(DecodeOCR(response)); + + public static string PrettifyOCR(uint response) => PrettifyOCR(DecodeOCR(response)); + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SecureDigital/SCR.cs b/Aaru.Decoders/SecureDigital/SCR.cs new file mode 100644 index 000000000..f5aefda68 --- /dev/null +++ b/Aaru.Decoders/SecureDigital/SCR.cs @@ -0,0 +1,232 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : SCR.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SecureDigital SCR. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; + +namespace Aaru.Decoders.SecureDigital +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public class SCR + { + public BusWidth BusWidth; + public CommandSupport CommandSupport; + public bool DataStatusAfterErase; + public byte ExtendedSecurity; + public byte[] ManufacturerReserved; + public byte Security; + public byte Spec; + public bool Spec3; + public bool Spec4; + public byte SpecX; + public byte Structure; + } + + [Flags] + public enum BusWidth : byte + { + OneBit = 1 << 0, FourBit = 1 << 2 + } + + [Flags] + public enum CommandSupport : byte + { + SpeedClassControl = 1 << 0, SetBlockCount = 1 << 1, ExtensionRegisterSingleBlock = 1 << 2, + ExtensionRegisterMultiBlock = 1 << 3 + } + + [SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "InconsistentNaming")] + public static partial class Decoders + { + public static SCR DecodeSCR(uint[] response) + { + if(response?.Length != 2) + return null; + + byte[] data = new byte[8]; + + byte[] tmp = BitConverter.GetBytes(response[0]); + Array.Copy(tmp, 0, data, 0, 4); + tmp = BitConverter.GetBytes(response[1]); + Array.Copy(tmp, 0, data, 4, 4); + + return DecodeSCR(data); + } + + public static SCR DecodeSCR(byte[] response) + { + if(response?.Length != 8) + return null; + + var scr = new SCR + { + Structure = (byte)((response[0] & 0xF0) >> 4), + Spec = (byte)(response[0] & 0x0F), + DataStatusAfterErase = (response[1] & 0x80) == 0x80, + Security = (byte)((response[1] & 0x70) >> 4), + BusWidth = (BusWidth)(response[1] & 0x0F), + Spec3 = (response[2] & 0x80) == 0x80, + ExtendedSecurity = (byte)((response[2] & 0x78) >> 3), + Spec4 = (response[2] & 0x04) == 0x04, + SpecX = (byte)(((response[2] & 0x03) << 2) + ((response[3] & 0xC0) >> 6)), + CommandSupport = (CommandSupport)(response[3] & 0x0F), + ManufacturerReserved = new byte[4] + }; + + Array.Copy(response, 4, scr.ManufacturerReserved, 0, 4); + + return scr; + } + + public static string PrettifySCR(SCR scr) + { + if(scr == null) + return null; + + var sb = new StringBuilder(); + sb.AppendLine("SecureDigital Device Configuration Register:"); + + if(scr.Structure != 0) + sb.AppendFormat("\tUnknown register version {0}", scr.Structure).AppendLine(); + + switch(scr.Spec) + { + case 0 when scr.Spec3 == false && scr.Spec4 == false && scr.SpecX == 0: + sb.AppendLine("\tDevice follows SecureDigital Physical Layer Specification version 1.0x"); + + break; + case 1 when scr.Spec3 == false && scr.Spec4 == false && scr.SpecX == 0: + sb.AppendLine("\tDevice follows SecureDigital Physical Layer Specification version 1.10"); + + break; + case 2 when scr.Spec3 == false && scr.Spec4 == false && scr.SpecX == 0: + sb.AppendLine("\tDevice follows SecureDigital Physical Layer Specification version 2.00"); + + break; + case 2 when scr.Spec3 && scr.Spec4 == false && scr.SpecX == 0: + sb.AppendLine("\tDevice follows SecureDigital Physical Layer Specification version 3.0x"); + + break; + case 2 when scr.Spec3 && scr.Spec4 && scr.SpecX == 0: + sb.AppendLine("\tDevice follows SecureDigital Physical Layer Specification version 4.xx"); + + break; + case 2 when scr.Spec3: + switch(scr.SpecX) + { + case 1: + sb.AppendLine("\tDevice follows SecureDigital Physical Layer Specification version 5.xx"); + + break; + case 2: + sb.AppendLine("\tDevice follows SecureDigital Physical Layer Specification version 6.xx"); + + break; + case 3: + sb.AppendLine("\tDevice follows SecureDigital Physical Layer Specification version 7.xx"); + + break; + case 4: + sb.AppendLine("\tDevice follows SecureDigital Physical Layer Specification version 8.xx"); + + break; + } + + break; + default: + sb. + AppendFormat("\tDevice follows SecureDigital Physical Layer Specification with unknown version {0}.{1}.{2}.{3}", + scr.Spec, scr.Spec3, scr.Spec4, scr.SpecX).AppendLine(); + + break; + } + + switch(scr.Security) + { + case 0: + sb.AppendLine("\tDevice does not support CPRM"); + + break; + case 1: + sb.AppendLine("\tDevice does not use CPRM"); + + break; + case 2: + sb.AppendLine("\tDevice uses CPRM according to specification version 1.01"); + + break; + case 3: + sb.AppendLine("\tDevice uses CPRM according to specification version 2.00"); + + break; + case 4: + sb.AppendLine("\tDevice uses CPRM according to specification version 3.xx"); + + break; + default: + sb.AppendFormat("\tDevice uses unknown CPRM specification with code {0}", scr.Security). + AppendLine(); + + break; + } + + if(scr.BusWidth.HasFlag(BusWidth.OneBit)) + sb.AppendLine("\tDevice supports 1-bit data bus"); + + if(scr.BusWidth.HasFlag(BusWidth.FourBit)) + sb.AppendLine("\tDevice supports 4-bit data bus"); + + if(scr.ExtendedSecurity != 0) + sb.AppendLine("\tDevice supports extended security"); + + if(scr.CommandSupport.HasFlag(CommandSupport.ExtensionRegisterMultiBlock)) + sb.AppendLine("\tDevice supports extension register multi-block commands"); + + if(scr.CommandSupport.HasFlag(CommandSupport.ExtensionRegisterSingleBlock)) + sb.AppendLine("\tDevice supports extension register single-block commands"); + + if(scr.CommandSupport.HasFlag(CommandSupport.SetBlockCount)) + sb.AppendLine("\tDevice supports set block count command"); + + if(scr.CommandSupport.HasFlag(CommandSupport.SpeedClassControl)) + sb.AppendLine("\tDevice supports speed class control command"); + + return sb.ToString(); + } + + public static string PrettifySCR(uint[] response) => PrettifySCR(DecodeSCR(response)); + + public static string PrettifySCR(byte[] response) => PrettifySCR(DecodeSCR(response)); + } +} \ No newline at end of file diff --git a/Aaru.Decoders/SecureDigital/VendorString.cs b/Aaru.Decoders/SecureDigital/VendorString.cs new file mode 100644 index 000000000..8198d6faa --- /dev/null +++ b/Aaru.Decoders/SecureDigital/VendorString.cs @@ -0,0 +1,51 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : VendorString.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes SecureDigital vendor code. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.Decoders.SecureDigital +{ + /// Decodes SecureDigital vendors + public static class VendorString + { + /// Converts the byte value of a SecureDigital vendor ID to the manufacturer's name string + /// SD vendor ID + /// Manufacturer + public static string Prettify(byte sdVendorId) => sdVendorId switch + { + 0x41 => "Kingston", + 0x02 => "Kingston", + 0x03 => "Sandisk", + 0x27 => "CnMemory", + 0xAA => "QEMU", + _ => $"Unknown manufacturer ID 0x{sdVendorId:X2}" + }; + } +} \ No newline at end of file diff --git a/Aaru.Decoders/Sega/CD.cs b/Aaru.Decoders/Sega/CD.cs new file mode 100644 index 000000000..15340d885 --- /dev/null +++ b/Aaru.Decoders/Sega/CD.cs @@ -0,0 +1,385 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CD.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes Sega CD (aka Mega CD) IP.BIN. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Runtime.InteropServices; +using System.Text; +using Aaru.Console; +using Marshal = Aaru.Helpers.Marshal; + +namespace Aaru.Decoders.Sega +{ + /// Represents the IP.BIN from a SEGA CD / MEGA CD + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class CD + { + /// Decodes an IP.BIN sector in SEGA CD / MEGA CD format + /// IP.BIN sector + /// Decoded IP.BIN + public static IPBin? DecodeIPBin(byte[] ipbin_sector) + { + if(ipbin_sector == null) + return null; + + if(ipbin_sector.Length < 512) + return null; + + IPBin ipbin = Marshal.ByteArrayToStructureLittleEndian(ipbin_sector); + + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.volume_name = \"{0}\"", + Encoding.ASCII.GetString(ipbin.volume_name)); + + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.system_name = \"{0}\"", + Encoding.ASCII.GetString(ipbin.system_name)); + + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.volume_version = \"{0:X}\"", + ipbin.volume_version); + + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.volume_type = 0x{0:X8}", + ipbin.volume_type); + + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.system_version = 0x{0:X8}", + ipbin.system_version); + + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.ip_address = 0x{0:X8}", ipbin.ip_address); + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.ip_loadsize = {0}", ipbin.ip_loadsize); + + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.ip_entry_address = 0x{0:X8}", + ipbin.ip_entry_address); + + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.ip_work_ram_size = {0}", + ipbin.ip_work_ram_size); + + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.sp_address = 0x{0:X8}", ipbin.sp_address); + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.sp_loadsize = {0}", ipbin.sp_loadsize); + + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.sp_entry_address = 0x{0:X8}", + ipbin.sp_entry_address); + + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.sp_work_ram_size = {0}", + ipbin.sp_work_ram_size); + + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.release_date = \"{0}\"", + Encoding.ASCII.GetString(ipbin.release_date)); + + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.release_date2 = \"{0}\"", + Encoding.ASCII.GetString(ipbin.release_date2)); + + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.developer_code = \"{0}\"", + Encoding.ASCII.GetString(ipbin.developer_code)); + + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.domestic_title = \"{0}\"", + Encoding.ASCII.GetString(ipbin.domestic_title)); + + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.overseas_title = \"{0}\"", + Encoding.ASCII.GetString(ipbin.overseas_title)); + + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.product_code = \"{0}\"", + Encoding.ASCII.GetString(ipbin.product_code)); + + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.peripherals = \"{0}\"", + Encoding.ASCII.GetString(ipbin.peripherals)); + + AaruConsole.DebugWriteLine("SegaCD IP.BIN Decoder", "segacd_ipbin.region_codes = \"{0}\"", + Encoding.ASCII.GetString(ipbin.region_codes)); + + string id = Encoding.ASCII.GetString(ipbin.SegaHardwareID); + + return id == "SEGADISCSYSTEM " || id == "SEGADATADISC " || id == "SEGAOS " ? ipbin + : (IPBin?)null; + } + + /// Pretty prints a decoded IP.BIN in SEGA CD / MEGA CD format + /// Decoded IP.BIN + /// Description of the IP.BIN contents + public static string Prettify(IPBin? decoded) + { + if(decoded == null) + return null; + + IPBin ipbin = decoded.Value; + + var IPBinInformation = new StringBuilder(); + + IPBinInformation.AppendLine("--------------------------------"); + IPBinInformation.AppendLine("SEGA IP.BIN INFORMATION:"); + IPBinInformation.AppendLine("--------------------------------"); + + // Decoding all data + DateTime ipbindate = DateTime.MinValue; + CultureInfo provider = CultureInfo.InvariantCulture; + + try + { + ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(ipbin.release_date), "MMddyyyy", provider); + } + catch + { + try + { + ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(ipbin.release_date2), "yyyy.MMM", + provider); + } + #pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body + catch + { + // ignored + } + #pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body + } + + /* + switch (Encoding.ASCII.GetString(application_type)) + { + case "GM": + IPBinInformation.AppendLine("Disc is a game."); + break; + case "AI": + IPBinInformation.AppendLine("Disc is an application."); + break; + default: + IPBinInformation.AppendLine("Disc is from unknown type."); + break; + } + */ + + IPBinInformation.AppendFormat("Volume name: {0}", Encoding.ASCII.GetString(ipbin.volume_name)).AppendLine(); + + //IPBinInformation.AppendFormat("Volume version: {0}", Encoding.ASCII.GetString(ipbin.volume_version)).AppendLine(); + //IPBinInformation.AppendFormat("{0}", Encoding.ASCII.GetString(ipbin.volume_type)).AppendLine(); + IPBinInformation.AppendFormat("System name: {0}", Encoding.ASCII.GetString(ipbin.system_name)).AppendLine(); + + //IPBinInformation.AppendFormat("System version: {0}", Encoding.ASCII.GetString(ipbin.system_version)).AppendLine(); + IPBinInformation.AppendFormat("Initial program address: 0x{0:X8}", ipbin.ip_address).AppendLine(); + IPBinInformation.AppendFormat("Initial program load size: {0} bytes", ipbin.ip_loadsize).AppendLine(); + + IPBinInformation.AppendFormat("Initial program entry address: 0x{0:X8}", ipbin.ip_entry_address). + AppendLine(); + + IPBinInformation.AppendFormat("Initial program work RAM: {0} bytes", ipbin.ip_work_ram_size).AppendLine(); + IPBinInformation.AppendFormat("System program address: 0x{0:X8}", ipbin.sp_address).AppendLine(); + IPBinInformation.AppendFormat("System program load size: {0} bytes", ipbin.sp_loadsize).AppendLine(); + + IPBinInformation.AppendFormat("System program entry address: 0x{0:X8}", ipbin.sp_entry_address). + AppendLine(); + + IPBinInformation.AppendFormat("System program work RAM: {0} bytes", ipbin.sp_work_ram_size).AppendLine(); + + if(ipbindate != DateTime.MinValue) + IPBinInformation.AppendFormat("Release date: {0}", ipbindate).AppendLine(); + + //IPBinInformation.AppendFormat("Release date (other format): {0}", Encoding.ASCII.GetString(release_date2)).AppendLine(); + IPBinInformation.AppendFormat("Hardware ID: {0}", Encoding.ASCII.GetString(ipbin.hardware_id)).AppendLine(); + + IPBinInformation.AppendFormat("Developer code: {0}", Encoding.ASCII.GetString(ipbin.developer_code)). + AppendLine(); + + IPBinInformation.AppendFormat("Domestic title: {0}", Encoding.ASCII.GetString(ipbin.domestic_title)). + AppendLine(); + + IPBinInformation.AppendFormat("Overseas title: {0}", Encoding.ASCII.GetString(ipbin.overseas_title)). + AppendLine(); + + IPBinInformation.AppendFormat("Product code: {0}", Encoding.ASCII.GetString(ipbin.product_code)). + AppendLine(); + + IPBinInformation.AppendFormat("Peripherals:").AppendLine(); + + foreach(byte peripheral in ipbin.peripherals) + switch((char)peripheral) + { + case 'A': + IPBinInformation.AppendLine("Game supports analog controller."); + + break; + case 'B': + IPBinInformation.AppendLine("Game supports trackball."); + + break; + case 'G': + IPBinInformation.AppendLine("Game supports light gun."); + + break; + case 'J': + IPBinInformation.AppendLine("Game supports JoyPad."); + + break; + case 'K': + IPBinInformation.AppendLine("Game supports keyboard."); + + break; + case 'M': + IPBinInformation.AppendLine("Game supports mouse."); + + break; + case 'O': + IPBinInformation.AppendLine("Game supports Master System's JoyPad."); + + break; + case 'P': + IPBinInformation.AppendLine("Game supports printer interface."); + + break; + case 'R': + IPBinInformation.AppendLine("Game supports serial (RS-232C) interface."); + + break; + case 'T': + IPBinInformation.AppendLine("Game supports tablet interface."); + + break; + case 'V': + IPBinInformation.AppendLine("Game supports paddle controller."); + + break; + case ' ': break; + default: + IPBinInformation.AppendFormat("Game supports unknown peripheral {0}.", peripheral).AppendLine(); + + break; + } + + IPBinInformation.AppendLine("Regions supported:"); + + foreach(byte region in ipbin.region_codes) + switch((char)region) + { + case 'J': + IPBinInformation.AppendLine("Japanese NTSC."); + + break; + case 'U': + IPBinInformation.AppendLine("USA NTSC."); + + break; + case 'E': + IPBinInformation.AppendLine("Europe PAL."); + + break; + case ' ': break; + default: + IPBinInformation.AppendFormat("Game supports unknown region {0}.", region).AppendLine(); + + break; + } + + return IPBinInformation.ToString(); + } + + // TODO: Check if it is big or little endian + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct IPBin + { + /// Must be "SEGADISCSYSTEM " or "SEGADATADISC " or "SEGAOS " + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] SegaHardwareID; + /// 0x010, Varies + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] + public byte[] volume_name; + /// 0x01B, 0x00 + public byte spare_space1; + /// 0x01C, Volume version in BCD. <100 = Prerelease. + public ushort volume_version; + /// 0x01E, Bit 0 = 1 => CD-ROM. Rest should be 0. + public ushort volume_type; + /// 0x020, Unknown, varies! + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] + public byte[] system_name; + /// 0x02B, 0x00 + public byte spare_space2; + /// 0x02C, Should be 1 + public ushort system_version; + /// 0x02E, 0x0000 + public ushort spare_space3; + /// 0x030, Initial program address + public uint ip_address; + /// 0x034, Load size of initial program + public uint ip_loadsize; + /// 0x038, Initial program entry address + public uint ip_entry_address; + /// 0x03C, Initial program work RAM size in bytes + public uint ip_work_ram_size; + /// 0x040, System program address + public uint sp_address; + /// 0x044, Load size of system program + public uint sp_loadsize; + /// 0x048, System program entry address + public uint sp_entry_address; + /// 0x04C, System program work RAM size in bytes + public uint sp_work_ram_size; + /// 0x050, MMDDYYYY + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] release_date; + /// 0x058, Seems to be all 0x20s + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] + public byte[] unknown1; + /// 0x05F, 0x00 ? + public byte spare_space4; + /// 0x060, System Reserved Area + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 160)] + public byte[] system_reserved; + /// 0x100, Hardware ID + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] hardware_id; + /// 0x113 or 0x110, "SEGA" or "T-xx" + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] + public byte[] developer_code; + /// 0x118, Another release date, this with month in letters? + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] release_date2; + /// 0x120, Domestic version of the game title + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)] + public byte[] domestic_title; + /// 0x150, Overseas version of the game title + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)] + public byte[] overseas_title; + /// 0x180, Official product code + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 13)] + public byte[] product_code; + /// 0x190, Supported peripherals, see above + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] peripherals; + /// 0x1A0, 0x20 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] spare_space6; + /// 0x1B0, Inside here should be modem information, but I need to get a modem-enabled game + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] + public byte[] spare_space7; + /// 0x1F0, Region codes, space-filled + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] region_codes; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/Sega/Dreamcast.cs b/Aaru.Decoders/Sega/Dreamcast.cs new file mode 100644 index 000000000..efd70a026 --- /dev/null +++ b/Aaru.Decoders/Sega/Dreamcast.cs @@ -0,0 +1,327 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Dreamcast.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes Sega Dreamcast IP.BIN. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Runtime.InteropServices; +using System.Text; +using Aaru.Console; +using Marshal = Aaru.Helpers.Marshal; + +namespace Aaru.Decoders.Sega +{ + /// Represents the IP.BIN from a SEGA Dreamcast + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class Dreamcast + { + /// Decodes an IP.BIN sector in Dreamcast format + /// IP.BIN sector + /// Decoded IP.BIN + public static IPBin? DecodeIPBin(byte[] ipbin_sector) + { + if(ipbin_sector == null) + return null; + + if(ipbin_sector.Length < 512) + return null; + + IPBin ipbin = Marshal.ByteArrayToStructureLittleEndian(ipbin_sector); + + AaruConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.maker_id = \"{0}\"", + Encoding.ASCII.GetString(ipbin.maker_id)); + + AaruConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.spare_space1 = \"{0}\"", + (char)ipbin.spare_space1); + + AaruConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.dreamcast_media = \"{0}\"", + Encoding.ASCII.GetString(ipbin.dreamcast_media)); + + AaruConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.disc_no = {0}", + (char)ipbin.disc_no); + + AaruConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.disc_no_separator = \"{0}\"", + (char)ipbin.disc_no_separator); + + AaruConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.disc_total_nos = \"{0}\"", + (char)ipbin.disc_total_nos); + + AaruConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.spare_space2 = \"{0}\"", + Encoding.ASCII.GetString(ipbin.spare_space2)); + + AaruConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.region_codes = \"{0}\"", + Encoding.ASCII.GetString(ipbin.region_codes)); + + AaruConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.peripherals = \"{0}\"", + Encoding.ASCII.GetString(ipbin.peripherals)); + + AaruConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.product_no = \"{0}\"", + Encoding.ASCII.GetString(ipbin.product_no)); + + AaruConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.product_version = \"{0}\"", + Encoding.ASCII.GetString(ipbin.product_version)); + + AaruConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.release_date = \"{0}\"", + Encoding.ASCII.GetString(ipbin.release_date)); + + AaruConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.spare_space3 = \"{0}\"", + (char)ipbin.spare_space3); + + AaruConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.boot_filename = \"{0}\"", + Encoding.ASCII.GetString(ipbin.boot_filename)); + + AaruConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.producer = \"{0}\"", + Encoding.ASCII.GetString(ipbin.producer)); + + AaruConsole.DebugWriteLine("Dreamcast IP.BIN Decoder", "dreamcast_ipbin.product_name = \"{0}\"", + Encoding.ASCII.GetString(ipbin.product_name)); + + return Encoding.ASCII.GetString(ipbin.SegaHardwareID) == "SEGA SEGAKATANA " ? ipbin : (IPBin?)null; + } + + /// Pretty prints a decoded IP.BIN in Dreamcast format + /// Decoded IP.BIN + /// Description of the IP.BIN contents + public static string Prettify(IPBin? decoded) + { + if(decoded == null) + return null; + + IPBin ipbin = decoded.Value; + + var IPBinInformation = new StringBuilder(); + + IPBinInformation.AppendLine("--------------------------------"); + IPBinInformation.AppendLine("SEGA IP.BIN INFORMATION:"); + IPBinInformation.AppendLine("--------------------------------"); + + // Decoding all data + DateTime ipbindate; + CultureInfo provider = CultureInfo.InvariantCulture; + ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(ipbin.release_date), "yyyyMMdd", provider); + + IPBinInformation.AppendFormat("Product name: {0}", Encoding.ASCII.GetString(ipbin.product_name)). + AppendLine(); + + IPBinInformation.AppendFormat("Product version: {0}", Encoding.ASCII.GetString(ipbin.product_version)). + AppendLine(); + + IPBinInformation.AppendFormat("Product CRC: 0x{0:X8}", ipbin.dreamcast_crc).AppendLine(); + IPBinInformation.AppendFormat("Producer: {0}", Encoding.ASCII.GetString(ipbin.producer)).AppendLine(); + + IPBinInformation.AppendFormat("Disc media: {0}", Encoding.ASCII.GetString(ipbin.dreamcast_media)). + AppendLine(); + + IPBinInformation.AppendFormat("Disc number {0} of {1}", (char)ipbin.disc_no, (char)ipbin.disc_total_nos). + AppendLine(); + + IPBinInformation.AppendFormat("Release date: {0}", ipbindate).AppendLine(); + + switch(Encoding.ASCII.GetString(ipbin.boot_filename)) + { + case "1ST_READ.BIN": + IPBinInformation.AppendLine("Disc boots natively."); + + break; + case "0WINCE.BIN ": + IPBinInformation.AppendLine("Disc boots using Windows CE."); + + break; + default: + IPBinInformation.AppendFormat("Disc boots using unknown loader: {0}.", + Encoding.ASCII.GetString(ipbin.boot_filename)).AppendLine(); + + break; + } + + IPBinInformation.AppendLine("Regions supported:"); + + foreach(byte region in ipbin.region_codes) + switch((char)region) + { + case 'J': + IPBinInformation.AppendLine("Japanese NTSC."); + + break; + case 'U': + IPBinInformation.AppendLine("North America NTSC."); + + break; + case 'E': + IPBinInformation.AppendLine("Europe PAL."); + + break; + case ' ': break; + default: + IPBinInformation.AppendFormat("Game supports unknown region {0}.", region).AppendLine(); + + break; + } + + int iPeripherals = int.Parse(Encoding.ASCII.GetString(ipbin.peripherals), NumberStyles.HexNumber); + + if((iPeripherals & 0x00000001) == 0x00000001) + IPBinInformation.AppendLine("Game uses Windows CE."); + + IPBinInformation.AppendFormat("Peripherals:").AppendLine(); + + if((iPeripherals & 0x00000010) == 0x00000010) + IPBinInformation.AppendLine("Game supports the VGA Box."); + + if((iPeripherals & 0x00000100) == 0x00000100) + IPBinInformation.AppendLine("Game supports other expansion."); + + if((iPeripherals & 0x00000200) == 0x00000200) + IPBinInformation.AppendLine("Game supports Puru Puru pack."); + + if((iPeripherals & 0x00000400) == 0x00000400) + IPBinInformation.AppendLine("Game supports Mike Device."); + + if((iPeripherals & 0x00000800) == 0x00000800) + IPBinInformation.AppendLine("Game supports Memory Card."); + + if((iPeripherals & 0x00001000) == 0x00001000) + IPBinInformation.AppendLine("Game requires A + B + Start buttons and D-Pad."); + + if((iPeripherals & 0x00002000) == 0x00002000) + IPBinInformation.AppendLine("Game requires C button."); + + if((iPeripherals & 0x00004000) == 0x00004000) + IPBinInformation.AppendLine("Game requires D button."); + + if((iPeripherals & 0x00008000) == 0x00008000) + IPBinInformation.AppendLine("Game requires X button."); + + if((iPeripherals & 0x00010000) == 0x00010000) + IPBinInformation.AppendLine("Game requires Y button."); + + if((iPeripherals & 0x00020000) == 0x00020000) + IPBinInformation.AppendLine("Game requires Z button."); + + if((iPeripherals & 0x00040000) == 0x00040000) + IPBinInformation.AppendLine("Game requires expanded direction buttons."); + + if((iPeripherals & 0x00080000) == 0x00080000) + IPBinInformation.AppendLine("Game requires analog R trigger."); + + if((iPeripherals & 0x00100000) == 0x00100000) + IPBinInformation.AppendLine("Game requires analog L trigger."); + + if((iPeripherals & 0x00200000) == 0x00200000) + IPBinInformation.AppendLine("Game requires analog horizontal controller."); + + if((iPeripherals & 0x00400000) == 0x00400000) + IPBinInformation.AppendLine("Game requires analog vertical controller."); + + if((iPeripherals & 0x00800000) == 0x00800000) + IPBinInformation.AppendLine("Game requires expanded analog horizontal controller."); + + if((iPeripherals & 0x01000000) == 0x01000000) + IPBinInformation.AppendLine("Game requires expanded analog vertical controller."); + + if((iPeripherals & 0x02000000) == 0x02000000) + IPBinInformation.AppendLine("Game supports Gun."); + + if((iPeripherals & 0x04000000) == 0x04000000) + IPBinInformation.AppendLine("Game supports Keyboard."); + + if((iPeripherals & 0x08000000) == 0x08000000) + IPBinInformation.AppendLine("Game supports Mouse."); + + if((iPeripherals & 0xEE) != 0) + IPBinInformation.AppendFormat("Game supports unknown peripherals mask {0:X2}", iPeripherals & 0xEE); + + return IPBinInformation.ToString(); + } + + /// SEGA IP.BIN format for Dreamcast + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct IPBin + { + /// Must be "SEGA SEGAKATANA " + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] SegaHardwareID; + /// 0x010, "SEGA ENTERPRISES" + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] maker_id; + /// 0x020, CRC of product_no and product_version + public uint dreamcast_crc; + /// 0x024, " " + public byte spare_space1; + /// 0x025, "GD-ROM" + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + public byte[] dreamcast_media; + /// 0x02B, Disc number + public byte disc_no; + /// 0x02C, '/' + public byte disc_no_separator; + /// 0x02D, Total number of discs + public byte disc_total_nos; + /// 0x02E, " " + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] spare_space2; + /// 0x030, Region codes, space-filled + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] region_codes; + /// 0x038, Supported peripherals, bitwise + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] + public byte[] peripherals; + /// 0x03F, ' ' + public byte spare_space3; + /// 0x040, Product number + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] + public byte[] product_no; + /// 0x04A, Product version + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + public byte[] product_version; + /// 0x050, YYYYMMDD + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] release_date; + /// 0x058, " " + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] spare_space4; + /// 0x060, Usually "1ST_READ.BIN" or "0WINCE.BIN " + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] boot_filename; + /// 0x06C, " " + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] spare_space5; + /// 0x070, Game producer, space-filled + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] producer; + /// 0x080, Game name, space-filled + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] + public byte[] product_name; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/Sega/Saturn.cs b/Aaru.Decoders/Sega/Saturn.cs new file mode 100644 index 000000000..6408b28b7 --- /dev/null +++ b/Aaru.Decoders/Sega/Saturn.cs @@ -0,0 +1,245 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Saturn.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes Sega Saturn IP.BIN. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Runtime.InteropServices; +using System.Text; +using Aaru.Console; +using Marshal = Aaru.Helpers.Marshal; + +namespace Aaru.Decoders.Sega +{ + /// Represents the IP.BIN from a SEGA Saturn + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] + public static class Saturn + { + /// Decodes an IP.BIN sector in Saturn format + /// IP.BIN sector + /// Decoded IP.BIN + public static IPBin? DecodeIPBin(byte[] ipbin_sector) + { + if(ipbin_sector == null) + return null; + + if(ipbin_sector.Length < 512) + return null; + + IPBin ipbin = Marshal.ByteArrayToStructureLittleEndian(ipbin_sector); + + AaruConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.maker_id = \"{0}\"", + Encoding.ASCII.GetString(ipbin.maker_id)); + + AaruConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.product_no = \"{0}\"", + Encoding.ASCII.GetString(ipbin.product_no)); + + AaruConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.product_version = \"{0}\"", + Encoding.ASCII.GetString(ipbin.product_version)); + + AaruConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.release_datedate = \"{0}\"", + Encoding.ASCII.GetString(ipbin.release_date)); + + AaruConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.saturn_media = \"{0}\"", + Encoding.ASCII.GetString(ipbin.saturn_media)); + + AaruConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.disc_no = {0}", (char)ipbin.disc_no); + + AaruConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.disc_no_separator = \"{0}\"", + (char)ipbin.disc_no_separator); + + AaruConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.disc_total_nos = {0}", + (char)ipbin.disc_total_nos); + + AaruConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.release_date = \"{0}\"", + Encoding.ASCII.GetString(ipbin.release_date)); + + AaruConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.spare_space1 = \"{0}\"", + Encoding.ASCII.GetString(ipbin.spare_space1)); + + AaruConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.region_codes = \"{0}\"", + Encoding.ASCII.GetString(ipbin.region_codes)); + + AaruConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.peripherals = \"{0}\"", + Encoding.ASCII.GetString(ipbin.peripherals)); + + AaruConsole.DebugWriteLine("Saturn IP.BIN Decoder", "saturn_ipbin.product_name = \"{0}\"", + Encoding.ASCII.GetString(ipbin.product_name)); + + return Encoding.ASCII.GetString(ipbin.SegaHardwareID) == "SEGA SEGASATURN " ? ipbin : (IPBin?)null; + } + + /// Pretty prints a decoded IP.BIN in Saturn format + /// Decoded IP.BIN + /// Description of the IP.BIN contents + public static string Prettify(IPBin? decoded) + { + if(decoded == null) + return null; + + IPBin ipbin = decoded.Value; + + var IPBinInformation = new StringBuilder(); + + IPBinInformation.AppendLine("--------------------------------"); + IPBinInformation.AppendLine("SEGA IP.BIN INFORMATION:"); + IPBinInformation.AppendLine("--------------------------------"); + + // Decoding all data + DateTime ipbindate; + CultureInfo provider = CultureInfo.InvariantCulture; + ipbindate = DateTime.ParseExact(Encoding.ASCII.GetString(ipbin.release_date), "yyyyMMdd", provider); + + IPBinInformation.AppendFormat("Product name: {0}", Encoding.ASCII.GetString(ipbin.product_name)). + AppendLine(); + + IPBinInformation.AppendFormat("Product number: {0}", Encoding.ASCII.GetString(ipbin.product_no)). + AppendLine(); + + IPBinInformation.AppendFormat("Product version: {0}", Encoding.ASCII.GetString(ipbin.product_version)). + AppendLine(); + + IPBinInformation.AppendFormat("Release date: {0}", ipbindate).AppendLine(); + + IPBinInformation.AppendFormat("Disc number {0} of {1}", (char)ipbin.disc_no, (char)ipbin.disc_total_nos). + AppendLine(); + + IPBinInformation.AppendFormat("Peripherals:").AppendLine(); + + foreach(byte peripheral in ipbin.peripherals) + switch((char)peripheral) + { + case 'A': + IPBinInformation.AppendLine("Game supports analog controller."); + + break; + case 'J': + IPBinInformation.AppendLine("Game supports JoyPad."); + + break; + case 'K': + IPBinInformation.AppendLine("Game supports keyboard."); + + break; + case 'M': + IPBinInformation.AppendLine("Game supports mouse."); + + break; + case 'S': + IPBinInformation.AppendLine("Game supports analog steering controller."); + + break; + case 'T': + IPBinInformation.AppendLine("Game supports multitap."); + + break; + case ' ': break; + default: + IPBinInformation.AppendFormat("Game supports unknown peripheral {0}.", peripheral).AppendLine(); + + break; + } + + IPBinInformation.AppendLine("Regions supported:"); + + foreach(byte region in ipbin.region_codes) + switch((char)region) + { + case 'J': + IPBinInformation.AppendLine("Japanese NTSC."); + + break; + case 'U': + IPBinInformation.AppendLine("North America NTSC."); + + break; + case 'E': + IPBinInformation.AppendLine("Europe PAL."); + + break; + case 'T': + IPBinInformation.AppendLine("Asia NTSC."); + + break; + case ' ': break; + default: + IPBinInformation.AppendFormat("Game supports unknown region {0}.", region).AppendLine(); + + break; + } + + return IPBinInformation.ToString(); + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct IPBin + { + /// Must be "SEGA SEGASATURN " + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] SegaHardwareID; + /// 0x010, "SEGA ENTERPRISES" + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] maker_id; + /// 0x020, Product number + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] + public byte[] product_no; + /// 0x02A, Product version + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + public byte[] product_version; + /// 0x030, YYYYMMDD + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] release_date; + /// 0x038, "CD-" + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] saturn_media; + /// 0x03B, Disc number + public byte disc_no; + /// // 0x03C, '/' + public byte disc_no_separator; + /// // 0x03D, Total number of discs + public byte disc_total_nos; + /// 0x03E, " " + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] spare_space1; + /// 0x040, Region codes, space-filled + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] region_codes; + /// 0x050, Supported peripherals, see above + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] peripherals; + /// 0x060, Game name, space-filled + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 112)] + public byte[] product_name; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/Xbox/DMI.cs b/Aaru.Decoders/Xbox/DMI.cs new file mode 100644 index 000000000..79bc6c868 --- /dev/null +++ b/Aaru.Decoders/Xbox/DMI.cs @@ -0,0 +1,283 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : DMI.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes Xbox discs DMI structure. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Helpers; + +namespace Aaru.Decoders.Xbox +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class DMI + { + public static bool IsXbox(byte[] dmi) + { + if(dmi?.Length != 2052) + return false; + + // Version is 1 + if(BitConverter.ToUInt32(dmi, 4) != 1) + return false; + + // Catalogue number is two letters, five numbers, one letter + for(int i = 12; i < 14; i++) + if(dmi[i] < 0x41 || + dmi[i] > 0x5A) + return false; + + for(int i = 14; i < 19; i++) + if(dmi[i] < 0x30 || + dmi[i] > 0x39) + return false; + + if(dmi[19] < 0x41 || + dmi[19] > 0x5A) + return false; + + long timestamp = BitConverter.ToInt64(dmi, 20); + + // Game cannot exist before the Xbox + return timestamp >= 0x1BD164833DFC000; + } + + public static bool IsXbox360(byte[] dmi) + { + if(dmi?.Length != 2052) + return false; + + uint signature = BitConverter.ToUInt32(dmi, 0x7EC); + + // "XBOX" swapped as .NET is little endian + return signature == 0x584F4258; + } + + public static XboxDMI? DecodeXbox(byte[] response) + { + bool isXbox = IsXbox(response); + + if(!isXbox) + return null; + + var dmi = new XboxDMI + { + DataLength = (ushort)((response[0] << 8) + response[1]), + Reserved1 = response[2], + Reserved2 = response[3], + Version = BitConverter.ToUInt32(response, 4), + Timestamp = BitConverter.ToInt64(response, 20) + }; + + byte[] tmp = new byte[8]; + Array.Copy(response, 12, tmp, 0, 8); + dmi.CatalogNumber = StringHandlers.CToString(tmp); + + return dmi; + } + + public static Xbox360DMI? DecodeXbox360(byte[] response) + { + bool isX360 = IsXbox360(response); + + if(!isX360) + return null; + + var dmi = new Xbox360DMI + { + DataLength = (ushort)((response[0] << 8) + response[1]), + Reserved1 = response[2], + Reserved2 = response[3], + Version = BitConverter.ToUInt32(response, 4), + Timestamp = BitConverter.ToInt64(response, 20), + MediaID = new byte[16] + }; + + Array.Copy(response, 36, dmi.MediaID, 0, 16); + byte[] tmp = new byte[16]; + Array.Copy(response, 68, tmp, 0, 16); + dmi.CatalogNumber = StringHandlers.CToString(tmp); + + return dmi.CatalogNumber == null || dmi.CatalogNumber.Length < 13 ? (Xbox360DMI?)null : dmi; + } + + public static string PrettifyXbox(XboxDMI? dmi) + { + if(dmi == null) + return null; + + XboxDMI decoded = dmi.Value; + var sb = new StringBuilder(); + + sb.Append("Catalogue number: "); + + for(int i = 0; i < 2; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + + sb.Append("-"); + + for(int i = 2; i < 7; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + + sb.Append("-"); + sb.AppendFormat("{0}", decoded.CatalogNumber[7]); + sb.AppendLine(); + + sb.AppendFormat("Timestamp: {0}", DateTime.FromFileTimeUtc(decoded.Timestamp)).AppendLine(); + + return sb.ToString(); + } + + public static string PrettifyXbox360(Xbox360DMI? dmi) + { + if(dmi == null) + return null; + + Xbox360DMI decoded = dmi.Value; + var sb = new StringBuilder(); + + sb.Append("Catalogue number: "); + + for(int i = 0; i < 2; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + + sb.Append("-"); + + for(int i = 2; i < 6; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + + sb.Append("-"); + + for(int i = 6; i < 8; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + + sb.Append("-"); + + switch(decoded.CatalogNumber.Length) + { + case 13: + for(int i = 8; i < 10; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + + sb.Append("-"); + + for(int i = 10; i < 13; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + + break; + case 14: + for(int i = 8; i < 11; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + + sb.Append("-"); + + for(int i = 11; i < 14; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + + break; + default: + for(int i = 8; i < decoded.CatalogNumber.Length - 3; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + + sb.Append("-"); + + for(int i = decoded.CatalogNumber.Length - 3; i < decoded.CatalogNumber.Length; i++) + sb.AppendFormat("{0}", decoded.CatalogNumber[i]); + + break; + } + + sb.AppendLine(); + + sb.Append("Media ID: "); + + for(int i = 0; i < 12; i++) + sb.AppendFormat("{0:X2}", decoded.MediaID[i]); + + sb.Append("-"); + + for(int i = 12; i < 16; i++) + sb.AppendFormat("{0:X2}", decoded.MediaID[i]); + + sb.AppendLine(); + + sb.AppendFormat("Timestamp: {0}", DateTime.FromFileTimeUtc(decoded.Timestamp)).AppendLine(); + + return sb.ToString(); + } + + public static string PrettifyXbox(byte[] response) => PrettifyXbox(DecodeXbox(response)); + + public static string PrettifyXbox360(byte[] response) => PrettifyXbox360(DecodeXbox360(response)); + + public struct XboxDMI + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + + /// Bytes 4 to 7 0x01 in XGD + public uint Version; + + /// Bytes 12 to 16 Catalogue number in XX-XXXXX-X + public string CatalogNumber; + + /// Bytes 20 to 27 DMI timestamp + public long Timestamp; + } + + public struct Xbox360DMI + { + /// Bytes 0 to 1 Data length + public ushort DataLength; + /// Byte 2 Reserved + public byte Reserved1; + /// Byte 3 Reserved + public byte Reserved2; + + /// Bytes 4 to 7 0x02 in XGD2 and XGD3 + public uint Version; + + /// Bytes 20 to 27 DMI timestamp + public long Timestamp; + + /// Bytes 36 to 51 Media ID in hex XXXXXXXXXXXX-XXXXXXXX + public byte[] MediaID; + + /// Bytes 68 to 83 Catalogue number in XX-XXXX-XX-XXY-XXX, Y not always exists + public string CatalogNumber; + } + } +} \ No newline at end of file diff --git a/Aaru.Decoders/Xbox/SS.cs b/Aaru.Decoders/Xbox/SS.cs new file mode 100644 index 000000000..03b9dc57f --- /dev/null +++ b/Aaru.Decoders/Xbox/SS.cs @@ -0,0 +1,403 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : SS.cs +// Author(s) : Natalia Portillo +// +// Component : Device structures decoders. +// +// --[ Description ] ---------------------------------------------------------- +// +// Decodes Xbox security sectors +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Aaru.Decoders.DVD; + +namespace Aaru.Decoders.Xbox +{ + [SuppressMessage("ReSharper", "InconsistentNaming"), SuppressMessage("ReSharper", "MemberCanBeInternal"), + SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "NotAccessedField.Global")] + public static class SS + { + public static SecuritySector? Decode(byte[] response) + { + if(response == null) + return null; + + if(response.Length < 2048) + return null; + + var ss = new SecuritySector + { + DiskCategory = (DiskCategory)((response[0] & 0xF0) >> 4), + PartVersion = (byte)(response[0] & 0x0F), + DiscSize = (DVDSize)((response[1] & 0xF0) >> 4), + MaximumRate = (MaximumRateField)(response[1] & 0x0F), + Reserved3 = (response[2] & 0x80) == 0x80, + Layers = (byte)((response[2] & 0x60) >> 5), + TrackPath = (response[2] & 0x08) == 0x08, + LayerType = (LayerTypeFieldMask)(response[2] & 0x07), + LinearDensity = (LinearDensityField)((response[3] & 0xF0) >> 4), + TrackDensity = (TrackDensityField)(response[3] & 0x0F), + DataAreaStartPSN = (uint)((response[4] << 24) + (response[5] << 16) + (response[6] << 8) + response[7]), + DataAreaEndPSN = (uint)((response[8] << 24) + (response[9] << 16) + (response[10] << 8) + response[11]), + Layer0EndPSN = (uint)((response[12] << 24) + (response[13] << 16) + (response[14] << 8) + response[15]), + Unknown1 = response[27], + Unknown2 = new byte[28], + Unknown3 = new byte[436], + Unknown4 = new byte[4], + Unknown5 = new byte[43], + ChallengeTableVersion = response[768], + NoChallengeEntries = response[769], + ChallengeEntries = new ChallengeEntry[23], + Unknown6 = response[1023], + Unknown7 = new byte[48], + Unknown8 = new byte[16], + Unknown9 = new byte[16], + Unknown10 = new byte[303], + Unknown11 = new byte[104], + Extents = new SecuritySectorExtent[23], + ExtentsCopy = new SecuritySectorExtent[23] + }; + + Array.Copy(response, 256, ss.Unknown2, 0, 28); + Array.Copy(response, 284, ss.Unknown3, 0, 436); + Array.Copy(response, 720, ss.Unknown4, 0, 4); + Array.Copy(response, 724, ss.Unknown5, 0, 43); + + for(int i = 0; i < 23; i++) + ss.ChallengeEntries[i] = new ChallengeEntry + { + Level = response[770 + (i * 11) + 0], + ChallengeId = response[770 + (i * 11) + 1], + ChallengeValue = (uint)((response[770 + (i * 11) + 2] << 24) + + (response[770 + (i * 11) + 3] << 16) + (response[770 + (i * 11) + 4] << 8) + + response[770 + (i * 11) + 5]), + ResponseModifier = response[770 + (i * 11) + 6], + ResponseValue = (uint)((response[770 + (i * 11) + 7] << 24) + (response[770 + (i * 11) + 8] << 16) + + (response[770 + (i * 11) + 9] << 8) + response[770 + (i * 11) + 10]) + }; + + Array.Copy(response, 1052, ss.Unknown7, 0, 48); + Array.Copy(response, 1120, ss.Unknown8, 0, 16); + Array.Copy(response, 1180, ss.Unknown9, 0, 16); + Array.Copy(response, 1208, ss.Unknown10, 0, 303); + Array.Copy(response, 1528, ss.Unknown11, 0, 104); + + for(int i = 0; i < 23; i++) + ss.Extents[i] = new SecuritySectorExtent + { + Unknown = (uint)((response[1633 + (i * 9) + 0] << 16) + (response[1633 + (i * 9) + 1] << 8) + + response[1633 + (i * 9) + 2]), + StartPSN = (uint)((response[1633 + (i * 9) + 3] << 16) + (response[1633 + (i * 9) + 4] << 8) + + response[1633 + (i * 9) + 5]), + EndPSN = (uint)((response[1633 + (i * 9) + 6] << 16) + (response[1633 + (i * 9) + 7] << 8) + + response[1633 + (i * 9) + 8]) + }; + + for(int i = 0; i < 23; i++) + ss.ExtentsCopy[i] = new SecuritySectorExtent + { + Unknown = (uint)((response[1840 + (i * 9) + 0] << 16) + (response[1840 + (i * 9) + 1] << 8) + + response[1840 + (i * 9) + 2]), + StartPSN = (uint)((response[1840 + (i * 9) + 3] << 16) + (response[1840 + (i * 9) + 4] << 8) + + response[1840 + (i * 9) + 5]), + EndPSN = (uint)((response[1840 + (i * 9) + 6] << 16) + (response[1840 + (i * 9) + 7] << 8) + + response[1840 + (i * 9) + 8]) + }; + + return ss; + } + + public static string Prettify(SecuritySector? ss) + { + if(ss == null) + return null; + + SecuritySector decoded = ss.Value; + var sb = new StringBuilder(); + + string sizeString; + + switch(decoded.DiscSize) + { + case DVDSize.Eighty: + sizeString = "80mm"; + + break; + case DVDSize.OneTwenty: + sizeString = "120mm"; + + break; + default: + sizeString = $"unknown size identifier {decoded.DiscSize}"; + + break; + } + + const string categorySentence = "Disc is a {0} {1} version {2}"; + + switch(decoded.DiskCategory) + { + case DiskCategory.DVDPRWDL: + sb.AppendFormat(categorySentence, sizeString, "Xbox Game Disc", decoded.PartVersion).AppendLine(); + + break; + case DiskCategory.DVDPRDL: + sb.AppendFormat(categorySentence, sizeString, "Xbox 360 Game Disc", decoded.PartVersion). + AppendLine(); + + break; + default: + sb.AppendFormat(categorySentence, sizeString, "unknown disc type", decoded.PartVersion). + AppendLine(); + + break; + } + + switch(decoded.MaximumRate) + { + case MaximumRateField.TwoMbps: + sb.AppendLine("Disc maximum transfer rate is 2,52 Mbit/sec."); + + break; + case MaximumRateField.FiveMbps: + sb.AppendLine("Disc maximum transfer rate is 5,04 Mbit/sec."); + + break; + case MaximumRateField.TenMbps: + sb.AppendLine("Disc maximum transfer rate is 10,08 Mbit/sec."); + + break; + case MaximumRateField.TwentyMbps: + sb.AppendLine("Disc maximum transfer rate is 20,16 Mbit/sec."); + + break; + case MaximumRateField.ThirtyMbps: + sb.AppendLine("Disc maximum transfer rate is 30,24 Mbit/sec."); + + break; + case MaximumRateField.Unspecified: + sb.AppendLine("Disc maximum transfer rate is unspecified."); + + break; + default: + sb.AppendFormat("Disc maximum transfer rate is specified by unknown key {0}", decoded.MaximumRate). + AppendLine(); + + break; + } + + sb.AppendFormat("Disc has {0} layers", decoded.Layers + 1).AppendLine(); + + if(decoded.TrackPath && + decoded.Layers == 1) + sb.AppendLine("Layers are in parallel track path"); + else if(!decoded.TrackPath && + decoded.Layers == 1) + sb.AppendLine("Layers are in opposite track path"); + + switch(decoded.LinearDensity) + { + case LinearDensityField.TwoSix: + sb.AppendLine("Pitch size is 0,267 μm/bit"); + + break; + case LinearDensityField.TwoNine: + sb.AppendLine("Pitch size is 0,147 μm/bit"); + + break; + case LinearDensityField.FourZero: + sb.AppendLine("Pitch size is between 0,409 μm/bit and 0,435 μm/bit"); + + break; + case LinearDensityField.TwoEight: + sb.AppendLine("Pitch size is between 0,140 μm/bit and 0,148 μm/bit"); + + break; + case LinearDensityField.OneFive: + sb.AppendLine("Pitch size is 0,153 μm/bit"); + + break; + case LinearDensityField.OneThree: + sb.AppendLine("Pitch size is between 0,130 μm/bit and 0,140 μm/bit"); + + break; + case LinearDensityField.ThreeFive: + sb.AppendLine("Pitch size is 0,353 μm/bit"); + + break; + default: + sb.AppendFormat("Unknown pitch size key {0}", decoded.LinearDensity).AppendLine(); + + break; + } + + switch(decoded.TrackDensity) + { + case TrackDensityField.Seven: + sb.AppendLine("Track size is 0,74 μm"); + + break; + case TrackDensityField.Eight: + sb.AppendLine("Track size is 0,80 μm"); + + break; + case TrackDensityField.Six: + sb.AppendLine("Track size is 0,615 μm"); + + break; + case TrackDensityField.Four: + sb.AppendLine("Track size is 0,40 μm"); + + break; + case TrackDensityField.Three: + sb.AppendLine("Track size is 0,34 μm"); + + break; + default: + sb.AppendFormat("Unknown track size key {0}", decoded.LinearDensity).AppendLine(); + + break; + } + + if(decoded.DataAreaStartPSN > 0) + if(decoded.DataAreaEndPSN > 0) + { + sb.AppendFormat("Data area starts at PSN {0:X}h", decoded.DataAreaStartPSN).AppendLine(); + sb.AppendFormat("Data area ends at PSN {0:X}h", decoded.DataAreaEndPSN).AppendLine(); + + if(decoded.Layers == 1 && + !decoded.TrackPath) + sb.AppendFormat("Layer 0 ends at PSN {0:X}h", decoded.Layer0EndPSN).AppendLine(); + } + else + sb.AppendLine("Disc is empty"); + else + sb.AppendLine("Disc is empty"); + + sb.AppendLine("Challenges:"); + + foreach(ChallengeEntry entry in decoded.ChallengeEntries) + { + sb.AppendFormat("\tChallenge ID: {0}", entry.ChallengeId).AppendLine(); + sb.AppendFormat("\tChallenge level: {0}", entry.Level).AppendLine(); + sb.AppendFormat("\tChallenge value: 0x{0:X8}", entry.ChallengeValue).AppendLine(); + sb.AppendFormat("\tResponse modifier: {0}", entry.ResponseModifier).AppendLine(); + sb.AppendFormat("\tResponse value: 0x{0:X8}", entry.ResponseValue).AppendLine(); + } + + for(int i = 0; i < 16; i++) + sb.AppendFormat("Extent starts at PSN {0:X6}h and ends at PSN {1:X6}h", decoded.Extents[i].StartPSN, + decoded.Extents[i].EndPSN).AppendLine(); + + return sb.ToString(); + } + + public static string Prettify(byte[] response) => Prettify(Decode(response)); + + public struct SecuritySector + { + /// Byte 0, bits 7 to 4 Disk category field + public DiskCategory DiskCategory; + /// Byte 0, bits 3 to 0 Media version + public byte PartVersion; + /// Byte 1, bits 7 to 4 120mm if 0, 80mm if 1. If UMD (60mm) 0 also. Reserved rest of values + public DVDSize DiscSize; + /// Byte 1, bits 3 to 0 Maximum data rate + public MaximumRateField MaximumRate; + /// Byte 2, bit 7 Reserved + public bool Reserved3; + /// Byte 2, bits 6 to 5 Number of layers + public byte Layers; + /// Byte 2, bit 4 Track path + public bool TrackPath; + /// Byte 2, bits 3 to 0 Layer type + public LayerTypeFieldMask LayerType; + /// Byte 3, bits 7 to 4 Linear density field + public LinearDensityField LinearDensity; + /// Byte 3, bits 3 to 0 Track density field + public TrackDensityField TrackDensity; + /// Bytes 4 to 7 PSN where Data Area starts + public uint DataAreaStartPSN; + /// Bytes 8 to 11 PSN where Data Area ends + public uint DataAreaEndPSN; + /// Bytes 12 to 15 PSN where Data Area ends in Layer 0 + public uint Layer0EndPSN; + + /// Byte 27 Always 0x06 on XGD3 + public byte Unknown1; + /// Bytes 256 to 283 Unknown, XGD2 and XGD3 + public byte[] Unknown2; + /// Bytes 284 to 719 Unknown, XGD3 + public byte[] Unknown3; + /// Bytes 720 to 723 Unknown + public byte[] Unknown4; + /// Bytes 724 to 767 Unknown, XGD3 + public byte[] Unknown5; + /// Byte 768 Version of challenge table + public byte ChallengeTableVersion; + /// Byte 769 Number of challenge entries + public byte NoChallengeEntries; + /// Bytes 770 to 1022 Unknown + public ChallengeEntry[] ChallengeEntries; + /// Byte 1023 Unknown + public byte Unknown6; + /// Bytes 1052 to 1099 Unknown, XGD1 only + public byte[] Unknown7; + /// Bytes 1120 to 1135 Unknown, XGD2 and XGD3 + public byte[] Unknown8; + /// Bytes 1180 to 1195 Unknown + public byte[] Unknown9; + /// Bytes 1208 to 1511 Unknown + public byte[] Unknown10; + /// Bytes 1528 to 1632 + public byte[] Unknown11; + /// Bytes 1633 to 1839 Security extents, 23 entries of 9 bytes + public SecuritySectorExtent[] Extents; + /// Bytes 1840 to 2047 Copy of the security extents, 23 entries of 9 bytes + public SecuritySectorExtent[] ExtentsCopy; + } + + public struct SecuritySectorExtent + { + /// Bytes 0 to 2 Unknown + public uint Unknown; + /// Bytes 3 to 5 Start PSN of this security extent + public uint StartPSN; + /// Bytes 6 to 8 End PSN of this security extent + public uint EndPSN; + } + + public struct ChallengeEntry + { + public byte Level; + public byte ChallengeId; + public uint ChallengeValue; + public byte ResponseModifier; + public uint ResponseValue; + } + } +} \ No newline at end of file diff --git a/Aaru.Decryption b/Aaru.Decryption deleted file mode 160000 index 80f19faa1..000000000 --- a/Aaru.Decryption +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 80f19faa15c29d09e936b8aa6cd27489e302b517 diff --git a/Aaru.Decryption/.editorconfig b/Aaru.Decryption/.editorconfig new file mode 100644 index 000000000..9181fe501 --- /dev/null +++ b/Aaru.Decryption/.editorconfig @@ -0,0 +1,632 @@ +root = true + +[*] +charset = utf-8 +next_line = crlf +insert_final_newline = false +indent_style = space +indent_size = 4 + +# Generic non-language specific ones for Resharper and friends +brace_style = next_line +int_align = true +keep_existing_arrangement = false +place_simple_blocks_on_single_line = true +place_simple_declaration_blocks_on_single_line = true +place_attribute_on_same_line = false +space_after_unary_operator = false +space_after_comma = true +space_around_ternary_operator = true +space_around_binary_operator = true +space_around_member_access_operator = false +space_before_open_square_brackets = false +space_after_keywords_in_control_flow_statements = true +space_before_comma = false +space_between_method_call_name_and_opening_parenthesis = false +space_between_method_declaration_name_and_open_parenthesis = false +space_between_square_brackets = false +space_between_parentheses_of_control_flow_statements = false +accessor_owner_declaration_braces = next_line +accessor_declaration_braces = next_line +case_block_braces = next_line +initializer_braces = next_line +other_braces = next_line +allow_comment_after_lbrace = false +empty_block_style = together_same_line +braces_for_ifelse = not_required +braces_for_for = not_required +braces_for_foreach = not_required +braces_for_while = not_required +braces_for_dowhile = not_required +braces_for_using = not_required +braces_for_lock = not_required +braces_for_fixed = not_required +method_or_operator_body = expression_body +local_function_body = expression_body +constructor_or_destructor_body = expression_body +accessor_owner_body = expression_body +force_attribute_style = join +function_braces = next_line +force_control_statements_braces = always_remove +space_in_singleline_accessorholder = true +type_declaration_braces = next_line +invocable_declaration_braces = next_line +anonymous_method_declaration_braces = next_line +space_between_accessors_in_singleline_property = true +indent_nested_usings_stmt = true +space_within_empty_braces = false +indent_nested_fixed_stmt = true +indent_nested_lock_stmt = true +indent_nested_for_stmt = true +indent_nested_foreach_stmt = true +indent_nested_while_stmt = true +use_continuous_indent_inside_parens = true +indent_method_decl_pars = inside +indent_invocation_pars = inside +indent_statement_pars = inside +indent_typeparam_angles = inside +indent_typearg_angles = inside +indent_pars = inside +indent_preprocessor_if = outdent +indent_preprocessor_region = usual_indent +indent_preprocessor_other = usual_indent +indent_switch_labels = true +indent_type_constraints = true +stick_comment = false +alignment_tab_fill_style = use_spaces +align_multiline_parameter = true +align_multiline_extends_list = true +align_linq_query = true +align_multiline_binary_expressions_chain = true +outdent_binary_ops = true +align_multiline_calls_chain = true +outdent_dots = true +align_multiline_array_and_object_initializer = false +indent_anonymous_method_block = false +align_first_arg_by_paren = true +align_multiline_argument = true +align_tuple_components = true +align_multiline_expression = true +align_multiline_for_stmt = true +align_multiple_declaration = true +align_multline_type_parameter_list = true +align_multline_type_parameter_constrains = true +int_align_fields = true +int_align_properties = true +int_align_methods = true +int_align_parameters = false +int_align_variables = true +int_align_assignments = true +int_align_nested_ternary = true +int_align_invocations = false +int_align_binary_expressions = true +int_align_comments = true +int_align_switch_sections = true +keep_user_linebreaks = false +keep_existing_arrangement = false +keep_existing_linebreaks = false +max_line_length = 120 +wrap_before_comma = false +special_else_if_treatment = true +place_type_attribute_on_same_line = never +place_method_attribute_on_same_line = never +place_accessorholder_attribute_on_same_line = never +place_attribute_on_same_line = never +place_accessor_attribute_on_same_line = never +place_attribute_on_same_line = never +place_field_attribute_on_same_line = never +place_attribute_on_same_line = never +wrap_parameters_style = wrap_if_long +keep_existing_declaration_parens_arrangement = false +wrap_before_declaration_lpar = false +wrap_after_declaration_lpar = false +wrap_before_declaration_rpar = false +place_constructor_initializer_on_same_line = true +keep_existing_expr_member_arrangement = false +place_expr_method_on_single_line = true +place_expr_property_on_single_line = true +place_expr_accessor_on_single_line = true +wrap_before_arrow_with_expressions = false +place_type_constraints_on_same_line = true +wrap_before_first_type_parameter_constraint = true +wrap_multiple_type_parameter_constraints_style = wrap_if_long +wrap_before_type_parameter_langle = true +wrap_before_extends_colon = false +wrap_extends_list_style = wrap_if_long +keep_existing_declaration_block_arrangement = false +place_abstract_accessorholder_on_single_line = true +place_simple_accessorholder_on_single_line = false +place_accessor_with_attrs_holder_on_single_line = false +place_simple_accessor_on_single_line = true +place_simple_method_on_single_line = false +keep_existing_enum_arrangement = false +place_simple_enum_on_single_line = false +wrap_enum_declaration = wrap_if_long +new_line_before_else = true +new_line_before_while = false +wrap_for_stmt_header_style = wrap_if_long +wrap_multiple_declaration_style = wrap_if_long +keep_existing_embedded_arrangement = false +place_simple_embedded_statement_on_same_line = false +place_simple_case_statement_on_same_line = true +keep_existing_embedded_block_arrangement = false +place_simple_embedded_block_on_same_line = false +place_simple_anonymousmethod_on_single_line = false +keep_existing_initializer_arrangement = false +place_simple_initializer_on_single_line = false +wrap_object_and_collection_initializer_style = chop_always +wrap_array_initializer_style = wrap_if_long +wrap_arguments_style = wrap_if_long +keep_existing_invocation_parens_arrangement = false +wrap_after_invocation_lpar = false +wrap_before_invocation_rpar = false +wrap_after_dot_in_method_calls = true +wrap_chained_method_calls = wrap_if_long +wrap_before_binary_opsign = false +wrap_chained_binary_expressions = wrap_if_long +force_chop_compound_if_expression = true +force_chop_compound_while_expression = true +force_chop_compound_do_expression = true +wrap_before_ternary_opsigns = true +wrap_ternary_expr_style = wrap_if_long +nested_ternary_style = expanded +wrap_linq_expressions = wrap_if_long +wrap_before_linq_expression = false +place_linq_into_on_new_line = false +wrap_verbatim_interpolated_strings = wrap_if_long +extra_spaces = remove_all +space_after_keywords_in_control_flow_statements = false +space_between_method_call_name_and_opening_parenthesis = false +space_between_method_declaration_name_and_open_parenthesis = false +space_before_typeof_parentheses = false +space_before_checked_parentheses = false +space_before_sizeof_parentheses = false +space_before_nameof_parentheses = false +space_between_keyword_and_expression = true +space_between_keyword_and_type = true +space_around_assignment_op = true +space_around_logical_op = true +space_around_binary_operator = true +space_around_equality_op = true +space_around_relational_op = true +space_around_bitwise_op = true +space_around_additive_op = true +space_around_multiplicative_op = true +space_around_shift_op = true +space_around_nullcoalescing_op = true +space_around_arrow_op = false +space_after_logical_not_op = false +space_after_unary_operator = false +space_after_cast = false +space_around_dot = false +space_around_lambda_arrow = true +space_before_pointer_asterik_declaration = false +space_before_nullable_mark = false +blank_lines_around_class_definition = 1 +namespace_indentation = all +space_within_template_argument = false +align_union_type_usage = true +space_in_singleline_method = true +space_in_singleline_anonymous_method = true +space_within_single_line_array_initializer_braces = true +space_around_arrow_op = false + +# These are for markup languages (HTML, XML, etc) +spaces_around_eq_in_pi_attribute = false +space_after_last_pi_attribute = true +pi_attributes_indent = align_by_first_attribute +blank_line_after_pi = true +spaces_around_eq_in_attribute = false +space_after_last_attribute = false +space_before_self_closing = true +attribute_style = on_single_line +attribute_indent = align_by_first_attribute +sort_attributes = true +sort_class_selectors = true +max_blank_lines_between_tags = 0 +linebreak_before_all_elements = true +linebreak_before_multiline_elements = true +quote_style = doublequoted +delete_quotes_from_solid_values = false +normalize_tag_names = true + + +[{.babelrc,.stylelintrc,jest.config,.eslintrc,.prettierrc,*.json,*.jsb3,*.jsb2,*.bowerrc}] +indent_size = 2 + +[*.js.map] +indent_size = 2 + +[*.{css,scss}] +indent_size = 2 +declarations_style = separate_lines_for_nonsingle +media_query_style = separate_lines +selector_style = same_line +properties_style = separate_lines_for_nonsingle +brace_style = next_line + +[{.analysis_options,*.yml,*.yaml}] +indent_size = 2 + +# Xml project files +[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] +indent_size = 2 + +# Xml files +[*.{xml,stylecop,resx,ruleset}] +indent_size = 2 + +# Xml config files +[*.{props,targets,config,nuspec}] +indent_size = 2 + +# .net files +[*.{cs,vb}] +# These set the this. / Me. +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning + +# These make it suggest Int32 instead of int, etc. +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# This controls implicit access modifiers +dotnet_style_require_accessibility_modifiers = never:suggestion + +# Prefer non modified fields to be marked readonly +dotnet_style_readonly_field = true:warning + +# Parenthesis settings +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_operators = always_for_clarity:warning + +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:error +dotnet_style_prefer_inferred_tuple_names = true:warning +dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning +dotnet_style_prefer_conditional_expression_over_return = true:warning +dotnet_style_coalesce_expression = true:warning +dotnet_style_null_propagation = true:error + +dotnet_sort_system_directives_first = true + +# Constants in C style, all-caps +dotnet_naming_rule.constant_fields_caps.symbols = constant_fields +dotnet_naming_rule.constant_fields_caps.severity = warning +dotnet_naming_rule.constant_fields_caps.style = caps_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.required_modifiers = const +dotnet_naming_style.caps_style.capitalization = all_upper + +# interfaces should be prefixed with I +dotnet_naming_rule.pascal_case_for_interface.severity = error +dotnet_naming_rule.pascal_case_for_interface.symbols = interfaces_fields +dotnet_naming_rule.pascal_case_for_interface.style = pascal_case_interface_style +dotnet_naming_symbols.interfaces_fields.applicable_kinds = interface +dotnet_naming_style.pascal_case_interface_style.required_prefix = I +dotnet_naming_style.pascal_case_interface_style.capitalization = pascal_case + +## internal and private fields should be _camelCase +dotnet_naming_rule.camel_case_for_private_internal_fields.severity = warning +dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields +dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style +dotnet_naming_symbols.private_internal_fields.applicable_kinds = field +dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal +dotnet_naming_style.camel_case_underscore_style.required_prefix = _ +dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case + +# 2018-12-07 NP: This is not yet working in VS2017 +# local variables should be camelCase +#dotnet_naming_rule.camel_case_for_locals.severity = suggestion +#dotnet_naming_rule.camel_case_for_locals.symbols = local_fields +#dotnet_naming_rule.camel_case_for_locals.style = camel_case_style +#dotnet_naming_symbols.local_fields.applicable_kinds = local +#dotnet_naming_style.camel_case_style.capitalization = camel_case + +[*.cs] +# var var var +csharp_style_var_for_built_in_types = false:warning +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = false:warning + +csharp_style_expression_bodied_methods = when_on_single_line:suggestion +csharp_style_expression_bodied_constructors = when_on_single_line:suggestion +csharp_style_expression_bodied_operators = when_on_single_line:suggestion +csharp_style_expression_bodied_properties = when_on_single_line:suggestion +csharp_style_expression_bodied_indexers = when_on_single_line:suggestion +csharp_style_expression_bodied_accessors = when_on_single_line:suggestion + +csharp_style_pattern_matching_over_is_with_cast_check = true:warning +csharp_style_pattern_matching_over_as_with_null_check = when_on_single_line:warning + +csharp_style_inlined_variable_declaration = true:warning + +csharp_prefer_simple_default_expression = true:warning +csharp_style_deconstructed_variable_declaration = false:warning + +csharp_style_throw_expression = true:warning +csharp_style_conditional_delegate_call = true:warning + +csharp_prefer_braces = false + +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true + +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = flush_left + +csharp_space_after_cast = false +csharp_space_after_keywords_in_control_flow_statements = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = none +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false + +csharp_preserve_single_line_statements = false +csharp_preserve_single_line_blocks = true + +csharp_blank_lines_around_region = 0 +csharp_blank_lines_inside_region = 0 +csharp_blank_lines_before_single_line_comment = 1 +csharp_keep_blank_lines_in_declarations = 1 +csharp_remove_blank_lines_near_braces_in_declarations = true +csharp_blank_lines_after_start_comment = false +csharp_blank_lines_between_using_groups = 0 +csharp_blank_lines_after_using_list = 1 +csharp_blank_lines_around_namespace = 1 +csharp_blank_lines_inside_namespace = 0 +csharp_blank_lines_around_type = 1 +csharp_blank_lines_inside_type = 0 +csharp_blank_lines_around_field = 0 +csharp_blank_lines_around_single_line_field = 0 +csharp_blank_lines_around_property = 1 +csharp_blank_lines_around_single_line_property = 0 +csharp_blank_lines_around_auto_property = 0 +csharp_blank_lines_around_single_line_auto_property = 0 +csharp_blank_lines_around_invocable = 1 +csharp_blank_lines_around_single_line_invocable = 1 +csharp_keep_blank_lines_in_code = 1 +csharp_remove_blank_lines_near_braces_in_code = true +csharp_blank_lines_around_local_method = 1 +csharp_blank_lines_around_single_line_local_method = 1 +csharp_blank_lines_before_control_transfer_statements = 1 +csharp_blank_lines_after_control_transfer_statements = 1 +csharp_blank_lines_before_block_statements = 1 +csharp_blank_lines_after_block_statements = 1 +csharp_blank_lines_before_multiline_statements = 1 +csharp_blank_lines_after_multiline_statements = 1 + +csharp_type_declaration_braces = next_line +csharp_brace_style = next_line +csharp_indent_inside_namespace = true +csharp_invocable_declaration_braces = next_line +csharp_anonymous_method_declaration_braces = next_line +csharp_accessor_owner_declaration_braces = next_line +csharp_accessor_declaration_braces = next_line +csharp_case_block_braces = next_line +csharp_initializer_braces = next_line +csharp_other_braces = next_line +csharp_allow_comment_after_lbrace = false +csharp_empty_block_style = together_same_line + +csharp_for_built_in_types = use_explicit_type +csharp_for_simple_types = use_var_when_evident +csharp_for_other_types = use_explicit_type +csharp_prefer_separate_deconstructed_variables_declaration = true +csharp_prefer_explicit_discard_declaration = false + +csharp_instance_members_qualify_members = none +csharp_builtin_type_reference_style = use_keyword +csharp_prefer_qualified_reference = false +csharp_add_imports_to_deepest_scope = false +csharp_allow_alias = true +csharp_default_private_modifier = implicit +csharp_default_internal_modifier = explicit +csharp_arguments_literal = positional +csharp_arguments_string_literal = positional +csharp_arguments_named = positional +csharp_arguments_anonymous_function = positional +csharp_arguments_other = positional +csharp_braces_for_ifelse = not_required +csharp_braces_for_for = not_required +csharp_braces_for_foreach = not_required +csharp_braces_for_while = not_required +csharp_braces_for_dowhile = not_required +csharp_braces_for_using = not_required +csharp_braces_for_lock = not_required +csharp_braces_for_fixed = not_required +csharp_method_or_operator_body = expression_body +csharp_local_function_body = expression_body +csharp_constructor_or_destructor_body = expression_body +csharp_accessor_owner_body = expression_body +csharp_force_attribute_style = join +csharp_indent_nested_usings_stmt = true + +csharp_builtin_type_reference_for_member_access_style = use_keyword +csharp_indent_nested_fixed_stmt = true +csharp_indent_nested_lock_stmt = true +csharp_indent_nested_for_stmt = true +csharp_indent_nested_foreach_stmt = true +csharp_indent_nested_while_stmt = true +csharp_use_continuous_indent_inside_parens = true +csharp_indent_method_decl_pars = inside +csharp_indent_invocation_pars = inside +csharp_indent_statement_pars = inside +csharp_indent_typeparam_angles = inside +csharp_indent_typearg_angles = inside +csharp_indent_pars = inside +csharp_indent_preprocessor_if = outdent +csharp_indent_preprocessor_region = usual_indent +csharp_indent_preprocessor_other = usual_indent +csharp_indent_switch_labels = true +csharp_indent_type_constraints = true +csharp_stick_comment = false +csharp_alignment_tab_fill_style = use_spaces +csharp_align_multiline_parameter = true +csharp_align_multiline_extends_list = true +csharp_align_linq_query = true +csharp_align_multiline_binary_expressions_chain = true +csharp_outdent_binary_ops = true +csharp_align_multiline_calls_chain = true +csharp_outdent_dots = true +csharp_align_multiline_array_and_object_initializer = false +csharp_indent_anonymous_method_block = false +csharp_align_first_arg_by_paren = true +csharp_align_multiline_argument = true +csharp_align_tuple_components = true +csharp_align_multiline_expression = true +csharp_align_multiline_for_stmt = true +csharp_align_multiple_declaration = true +csharp_align_multline_type_parameter_list = true +csharp_align_multline_type_parameter_constrains = true +csharp_int_align_fields = true +csharp_int_align_properties = true +csharp_int_align_methods = true +csharp_int_align_parameters = false +csharp_int_align_variables = true +csharp_int_align_assignments = true +csharp_int_align_nested_ternary = true +csharp_int_align_invocations = false +csharp_int_align_binary_expressions = true +csharp_int_align_comments = true +csharp_int_align_switch_sections = true +csharp_int_align = true +csharp_keep_user_linebreaks = false +csharp_keep_existing_arrangement = false +csharp_keep_existing_linebreaks = false +csharp_max_line_length = 120 +csharp_wrap_before_comma = false +csharp_special_else_if_treatment = true +csharp_insert_final_newline = false +csharp_place_type_attribute_on_same_line = never +csharp_place_method_attribute_on_same_line = never +csharp_place_accessorholder_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_place_accessor_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_place_field_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_wrap_parameters_style = wrap_if_long +csharp_keep_existing_declaration_parens_arrangement = false +csharp_wrap_before_declaration_lpar = false +csharp_wrap_after_declaration_lpar = false +csharp_wrap_before_declaration_rpar = false +csharp_place_constructor_initializer_on_same_line = true +csharp_keep_existing_expr_member_arrangement = false +csharp_place_expr_method_on_single_line = true +csharp_place_expr_property_on_single_line = true +csharp_place_expr_accessor_on_single_line = true +csharp_wrap_before_arrow_with_expressions = false +csharp_place_type_constraints_on_same_line = true +csharp_wrap_before_first_type_parameter_constraint = true +csharp_wrap_multiple_type_parameter_constraints_style = wrap_if_long +csharp_wrap_before_type_parameter_langle = true +csharp_wrap_before_extends_colon = false +csharp_wrap_extends_list_style = wrap_if_long +csharp_keep_existing_declaration_block_arrangement = false +csharp_place_abstract_accessorholder_on_single_line = true +csharp_place_simple_accessorholder_on_single_line = false +csharp_place_accessor_with_attrs_holder_on_single_line = false +csharp_place_simple_accessor_on_single_line = true +csharp_place_simple_method_on_single_line = false +csharp_keep_existing_enum_arrangement = false +csharp_place_simple_enum_on_single_line = false +csharp_wrap_enum_declaration = wrap_if_long +csharp_new_line_before_else = true +csharp_new_line_before_while = false +csharp_wrap_for_stmt_header_style = wrap_if_long +csharp_wrap_multiple_declaration_style = wrap_if_long +csharp_keep_existing_embedded_arrangement = false +csharp_place_simple_embedded_statement_on_same_line = false +csharp_place_simple_case_statement_on_same_line = true +csharp_keep_existing_embedded_block_arrangement = false +csharp_place_simple_embedded_block_on_same_line = false +csharp_place_simple_anonymousmethod_on_single_line = false +csharp_keep_existing_initializer_arrangement = false +csharp_place_simple_initializer_on_single_line = false +csharp_wrap_object_and_collection_initializer_style = chop_always +csharp_wrap_array_initializer_style = wrap_if_long +csharp_wrap_arguments_style = wrap_if_long +csharp_keep_existing_invocation_parens_arrangement = false +csharp_wrap_after_invocation_lpar = false +csharp_wrap_before_invocation_rpar = false +csharp_wrap_after_dot_in_method_calls = true +csharp_wrap_chained_method_calls = wrap_if_long +csharp_wrap_before_binary_opsign = false +csharp_wrap_chained_binary_expressions = wrap_if_long +csharp_force_chop_compound_if_expression = true +csharp_force_chop_compound_while_expression = true +csharp_force_chop_compound_do_expression = true +csharp_wrap_before_ternary_opsigns = true +csharp_wrap_ternary_expr_style = wrap_if_long +csharp_nested_ternary_style = expanded +csharp_wrap_linq_expressions = wrap_if_long +csharp_wrap_before_linq_expression = false +csharp_place_linq_into_on_new_line = false +csharp_wrap_verbatim_interpolated_strings = wrap_if_long +csharp_extra_spaces = remove_all +csharp_space_after_keywords_in_control_flow_statements = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_before_typeof_parentheses = false +csharp_space_before_checked_parentheses = false +csharp_space_before_sizeof_parentheses = false +csharp_space_before_nameof_parentheses = false +csharp_space_between_keyword_and_expression = true +csharp_space_between_keyword_and_type = true +csharp_space_around_assignment_op = true +csharp_space_around_logical_op = true +csharp_space_around_binary_operator = true +csharp_space_around_equality_op = true +csharp_space_around_relational_op = true +csharp_space_around_bitwise_op = true +csharp_space_around_additive_op = true +csharp_space_around_multiplicative_op = true +csharp_space_around_shift_op = true +csharp_space_around_nullcoalescing_op = true +csharp_space_around_arrow_op = false +csharp_space_after_logical_not_op = false +csharp_space_after_unary_operator = false +csharp_space_after_cast = false +csharp_space_around_dot = false +csharp_space_around_lambda_arrow = true +csharp_space_before_pointer_asterik_declaration = false +csharp_space_before_nullable_mark = false + +[*.cshtml] +linebreaks_around_razor_statements = true +blank_lines_around_razor_functions = true +blank_lines_around_razor_helpers = true +blank_lines_around_razor_sections = true + +# C++ +[*.{cc,cpp,cxx,h,hpp,hxx}] +cpp_indent_access_specifiers_from_class = true +cpp_indent_wrapped_function_names = false +cpp_align_multiline_type_argument = true + +# C, C++ and ObjectiveC +[*.{c,h,cc,cpp,cxx,m,hpp,hxx}] +indent_preprocessor_directives = normal +indent_type_constraints = true + +# Javascript and Typescript +[*.{js,js.map,ts}] +quote_style = doublequoted +termination_style = ensure_semicolon \ No newline at end of file diff --git a/Aaru.Decryption/.gitignore b/Aaru.Decryption/.gitignore new file mode 100644 index 000000000..47d474d72 --- /dev/null +++ b/Aaru.Decryption/.gitignore @@ -0,0 +1,608 @@ +### VisualStudio template +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ +### Linux template + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* +### Xcode template +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +### VisualStudioCode template +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +### C++ template +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o + +# Precompiled Headers +*.gch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +### MonoDevelop template +#User Specific +*.usertasks + +#Mono Project Files +*.resources +test-results/ +### GPG template +secring.* + +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### CMake template +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +### C template +# Object files +*.ko +*.elf + +# Linker output +*.map +*.exp + +*.so.* + +# Executables +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf +### Windows template +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# NuGet Packages Directory +packages/ +## TODO: If the tool you use requires repositories.config uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +# This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented) +!packages/build/ + + +# Others +sql/ +*.Cache + +# Visual Studio 2017 +.vs + +workspace.xml +cmake-build-debug +### macOS template +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +pkg/**/pkg +pkg/**/src +pkg/**/*.asc +pkg/**/*.sig +pkg/**/*.tar.xz +pkg/**/*.zip +pkg/**/aaru + +.sonarqube + +build/* \ No newline at end of file diff --git a/Aaru.Decryption/Aaru.Decryption.csproj b/Aaru.Decryption/Aaru.Decryption.csproj new file mode 100644 index 000000000..d48b3f456 --- /dev/null +++ b/Aaru.Decryption/Aaru.Decryption.csproj @@ -0,0 +1,42 @@ + + + + 2.0 + Library + Aaru.Decryption + Aaru.Decryption + $(Version) + true + 5.3.2 + Claunia.com + Copyright © 2011-2023 Natalia Portillo + Aaru Data Preservation Suite + Aaru.Decryption + $(Version) + netcoreapp3.1 + 8 + Decryption algorithms used by the Aaru Data Preservation Suite. + https://github.com/aaru-dps/ + LGPL-2.1-only + https://github.com/aaru-dps/Aaru.Decryption + true + en-US + true + true + snupkg + Rebecca Wallander <sakcheen@gmail.com> + enable + + + $(Version)+{chash:8} + true + true + + + + + + + + + diff --git a/Aaru.Decryption/DVD/CSS.cs b/Aaru.Decryption/DVD/CSS.cs new file mode 100644 index 000000000..4fae3d9d8 --- /dev/null +++ b/Aaru.Decryption/DVD/CSS.cs @@ -0,0 +1,716 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CSS.cs +// Author(s) : Rebecca Wallander +// +// --[ Description ] ---------------------------------------------------------- +// +// Handles Content Scrambling System crypto functionality. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2020-2023 Rebecca Wallander +// ****************************************************************************/ + +using System; +using System.Linq; +using Aaru.Decoders.DVD; + +// Based on information gathered from: +// ISO/IEC13818-1 Second Edition +// Mt. Fuji Commands for Multimedia Devices +// https://www.cs.cmu.edu/~dst/DeCSS/Kesden/ +// http://groups.csail.mit.edu/mac/users/hal/css/css.html +// http://www.staroceans.org/e-book/css/css_auth.html +// libdvdcpxm (https://offog.org/git/dvdaexplorer/src/libdvdcpxm/) +// libdvdcss (https://www.videolan.org/developers/libdvdcss.html) + +namespace Aaru.Decryption.DVD +{ + public class CSS + { + static readonly byte[,] _playerKeys = + { + { + 0x01, 0xaf, 0xe3, 0x12, 0x80 + }, + { + 0x12, 0x11, 0xca, 0x04, 0x3b + }, + { + 0x14, 0x0c, 0x9e, 0xd0, 0x09 + }, + { + 0x14, 0x71, 0x35, 0xba, 0xe2 + }, + { + 0x1a, 0xa4, 0x33, 0x21, 0xa6 + }, + { + 0x26, 0xec, 0xc4, 0xa7, 0x4e + }, + { + 0x2c, 0xb2, 0xc1, 0x09, 0xee + }, + { + 0x2f, 0x25, 0x9e, 0x96, 0xdd + }, + { + 0x33, 0x2f, 0x49, 0x6c, 0xe0 + }, + { + 0x35, 0x5b, 0xc1, 0x31, 0x0f + }, + { + 0x36, 0x67, 0xb2, 0xe3, 0x85 + }, + { + 0x39, 0x3d, 0xf1, 0xf1, 0xbd + }, + { + 0x3b, 0x31, 0x34, 0x0d, 0x91 + }, + { + 0x45, 0xed, 0x28, 0xeb, 0xd3 + }, + { + 0x48, 0xb7, 0x6c, 0xce, 0x69 + }, + { + 0x4b, 0x65, 0x0d, 0xc1, 0xee + }, + { + 0x4c, 0xbb, 0xf5, 0x5b, 0x23 + }, + { + 0x51, 0x67, 0x67, 0xc5, 0xe0 + }, + { + 0x53, 0x94, 0xe1, 0x75, 0xbf + }, + { + 0x57, 0x2c, 0x8b, 0x31, 0xae + }, + { + 0x63, 0xdb, 0x4c, 0x5b, 0x4a + }, + { + 0x7b, 0x1e, 0x5e, 0x2b, 0x57 + }, + { + 0x85, 0xf3, 0x85, 0xa0, 0xe0 + }, + { + 0xab, 0x1e, 0xe7, 0x7b, 0x72 + }, + { + 0xab, 0x36, 0xe3, 0xeb, 0x76 + }, + { + 0xb1, 0xb8, 0xf9, 0x38, 0x03 + }, + { + 0xb8, 0x5d, 0xd8, 0x53, 0xbd + }, + { + 0xbf, 0x92, 0xc3, 0xb0, 0xe2 + }, + { + 0xcf, 0x1a, 0xb2, 0xf8, 0x0a + }, + { + 0xec, 0xa0, 0xcf, 0xb3, 0xff + }, + { + 0xfc, 0x95, 0xa9, 0x87, 0x35 + } + }; + + static readonly byte[] _cssTable1 = + { + 0x33, 0x73, 0x3b, 0x26, 0x63, 0x23, 0x6b, 0x76, 0x3e, 0x7e, 0x36, 0x2b, 0x6e, 0x2e, 0x66, 0x7b, 0xd3, 0x93, + 0xdb, 0x06, 0x43, 0x03, 0x4b, 0x96, 0xde, 0x9e, 0xd6, 0x0b, 0x4e, 0x0e, 0x46, 0x9b, 0x57, 0x17, 0x5f, 0x82, + 0xc7, 0x87, 0xcf, 0x12, 0x5a, 0x1a, 0x52, 0x8f, 0xca, 0x8a, 0xc2, 0x1f, 0xd9, 0x99, 0xd1, 0x00, 0x49, 0x09, + 0x41, 0x90, 0xd8, 0x98, 0xd0, 0x01, 0x48, 0x08, 0x40, 0x91, 0x3d, 0x7d, 0x35, 0x24, 0x6d, 0x2d, 0x65, 0x74, + 0x3c, 0x7c, 0x34, 0x25, 0x6c, 0x2c, 0x64, 0x75, 0xdd, 0x9d, 0xd5, 0x04, 0x4d, 0x0d, 0x45, 0x94, 0xdc, 0x9c, + 0xd4, 0x05, 0x4c, 0x0c, 0x44, 0x95, 0x59, 0x19, 0x51, 0x80, 0xc9, 0x89, 0xc1, 0x10, 0x58, 0x18, 0x50, 0x81, + 0xc8, 0x88, 0xc0, 0x11, 0xd7, 0x97, 0xdf, 0x02, 0x47, 0x07, 0x4f, 0x92, 0xda, 0x9a, 0xd2, 0x0f, 0x4a, 0x0a, + 0x42, 0x9f, 0x53, 0x13, 0x5b, 0x86, 0xc3, 0x83, 0xcb, 0x16, 0x5e, 0x1e, 0x56, 0x8b, 0xce, 0x8e, 0xc6, 0x1b, + 0xb3, 0xf3, 0xbb, 0xa6, 0xe3, 0xa3, 0xeb, 0xf6, 0xbe, 0xfe, 0xb6, 0xab, 0xee, 0xae, 0xe6, 0xfb, 0x37, 0x77, + 0x3f, 0x22, 0x67, 0x27, 0x6f, 0x72, 0x3a, 0x7a, 0x32, 0x2f, 0x6a, 0x2a, 0x62, 0x7f, 0xb9, 0xf9, 0xb1, 0xa0, + 0xe9, 0xa9, 0xe1, 0xf0, 0xb8, 0xf8, 0xb0, 0xa1, 0xe8, 0xa8, 0xe0, 0xf1, 0x5d, 0x1d, 0x55, 0x84, 0xcd, 0x8d, + 0xc5, 0x14, 0x5c, 0x1c, 0x54, 0x85, 0xcc, 0x8c, 0xc4, 0x15, 0xbd, 0xfd, 0xb5, 0xa4, 0xed, 0xad, 0xe5, 0xf4, + 0xbc, 0xfc, 0xb4, 0xa5, 0xec, 0xac, 0xe4, 0xf5, 0x39, 0x79, 0x31, 0x20, 0x69, 0x29, 0x61, 0x70, 0x38, 0x78, + 0x30, 0x21, 0x68, 0x28, 0x60, 0x71, 0xb7, 0xf7, 0xbf, 0xa2, 0xe7, 0xa7, 0xef, 0xf2, 0xba, 0xfa, 0xb2, 0xaf, + 0xea, 0xaa, 0xe2, 0xff + }; + + static readonly byte[] _cssTable2 = + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x08, 0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e, 0x12, 0x13, + 0x10, 0x11, 0x16, 0x17, 0x14, 0x15, 0x1b, 0x1a, 0x19, 0x18, 0x1f, 0x1e, 0x1d, 0x1c, 0x24, 0x25, 0x26, 0x27, + 0x20, 0x21, 0x22, 0x23, 0x2d, 0x2c, 0x2f, 0x2e, 0x29, 0x28, 0x2b, 0x2a, 0x36, 0x37, 0x34, 0x35, 0x32, 0x33, + 0x30, 0x31, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x49, 0x48, 0x4b, 0x4a, 0x4d, 0x4c, 0x4f, 0x4e, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x5b, 0x5a, 0x59, 0x58, 0x5f, 0x5e, 0x5d, 0x5c, 0x52, 0x53, + 0x50, 0x51, 0x56, 0x57, 0x54, 0x55, 0x6d, 0x6c, 0x6f, 0x6e, 0x69, 0x68, 0x6b, 0x6a, 0x64, 0x65, 0x66, 0x67, + 0x60, 0x61, 0x62, 0x63, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x76, 0x77, 0x74, 0x75, 0x72, 0x73, + 0x70, 0x71, 0x92, 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95, 0x9b, 0x9a, 0x99, 0x98, 0x9f, 0x9e, 0x9d, 0x9c, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x89, 0x88, 0x8b, 0x8a, 0x8d, 0x8c, 0x8f, 0x8e, 0xb6, 0xb7, + 0xb4, 0xb5, 0xb2, 0xb3, 0xb0, 0xb1, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa0, 0xa1, 0xa2, 0xa3, 0xad, 0xac, 0xaf, 0xae, 0xa9, 0xa8, 0xab, 0xaa, 0xdb, 0xda, 0xd9, 0xd8, 0xdf, 0xde, + 0xdd, 0xdc, 0xd2, 0xd3, 0xd0, 0xd1, 0xd6, 0xd7, 0xd4, 0xd5, 0xc9, 0xc8, 0xcb, 0xca, 0xcd, 0xcc, 0xcf, 0xce, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf6, 0xf7, + 0xf4, 0xf5, 0xf2, 0xf3, 0xf0, 0xf1, 0xed, 0xec, 0xef, 0xee, 0xe9, 0xe8, 0xeb, 0xea, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe0, 0xe1, 0xe2, 0xe3 + }; + + static readonly byte[] _cssTable3 = + { + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, + 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, + 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, + 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, + 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, + 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, + 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, + 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, + 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, + 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, + 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, + 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, + 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, + 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, + 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, + 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, + 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, + 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, + 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, + 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, + 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, + 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, + 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff + }; + + static readonly byte[] _cssTable4 = + { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, + 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, + 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, + 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, + 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, + 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, + 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, + 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd, + 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, + 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, + 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, + 0x3f, 0xbf, 0x7f, 0xff + }; + + static readonly byte[] _cssTable5 = + { + 0xff, 0x7f, 0xbf, 0x3f, 0xdf, 0x5f, 0x9f, 0x1f, 0xef, 0x6f, 0xaf, 0x2f, 0xcf, 0x4f, 0x8f, 0x0f, 0xf7, 0x77, + 0xb7, 0x37, 0xd7, 0x57, 0x97, 0x17, 0xe7, 0x67, 0xa7, 0x27, 0xc7, 0x47, 0x87, 0x07, 0xfb, 0x7b, 0xbb, 0x3b, + 0xdb, 0x5b, 0x9b, 0x1b, 0xeb, 0x6b, 0xab, 0x2b, 0xcb, 0x4b, 0x8b, 0x0b, 0xf3, 0x73, 0xb3, 0x33, 0xd3, 0x53, + 0x93, 0x13, 0xe3, 0x63, 0xa3, 0x23, 0xc3, 0x43, 0x83, 0x03, 0xfd, 0x7d, 0xbd, 0x3d, 0xdd, 0x5d, 0x9d, 0x1d, + 0xed, 0x6d, 0xad, 0x2d, 0xcd, 0x4d, 0x8d, 0x0d, 0xf5, 0x75, 0xb5, 0x35, 0xd5, 0x55, 0x95, 0x15, 0xe5, 0x65, + 0xa5, 0x25, 0xc5, 0x45, 0x85, 0x05, 0xf9, 0x79, 0xb9, 0x39, 0xd9, 0x59, 0x99, 0x19, 0xe9, 0x69, 0xa9, 0x29, + 0xc9, 0x49, 0x89, 0x09, 0xf1, 0x71, 0xb1, 0x31, 0xd1, 0x51, 0x91, 0x11, 0xe1, 0x61, 0xa1, 0x21, 0xc1, 0x41, + 0x81, 0x01, 0xfe, 0x7e, 0xbe, 0x3e, 0xde, 0x5e, 0x9e, 0x1e, 0xee, 0x6e, 0xae, 0x2e, 0xce, 0x4e, 0x8e, 0x0e, + 0xf6, 0x76, 0xb6, 0x36, 0xd6, 0x56, 0x96, 0x16, 0xe6, 0x66, 0xa6, 0x26, 0xc6, 0x46, 0x86, 0x06, 0xfa, 0x7a, + 0xba, 0x3a, 0xda, 0x5a, 0x9a, 0x1a, 0xea, 0x6a, 0xaa, 0x2a, 0xca, 0x4a, 0x8a, 0x0a, 0xf2, 0x72, 0xb2, 0x32, + 0xd2, 0x52, 0x92, 0x12, 0xe2, 0x62, 0xa2, 0x22, 0xc2, 0x42, 0x82, 0x02, 0xfc, 0x7c, 0xbc, 0x3c, 0xdc, 0x5c, + 0x9c, 0x1c, 0xec, 0x6c, 0xac, 0x2c, 0xcc, 0x4c, 0x8c, 0x0c, 0xf4, 0x74, 0xb4, 0x34, 0xd4, 0x54, 0x94, 0x14, + 0xe4, 0x64, 0xa4, 0x24, 0xc4, 0x44, 0x84, 0x04, 0xf8, 0x78, 0xb8, 0x38, 0xd8, 0x58, 0x98, 0x18, 0xe8, 0x68, + 0xa8, 0x28, 0xc8, 0x48, 0x88, 0x08, 0xf0, 0x70, 0xb0, 0x30, 0xd0, 0x50, 0x90, 0x10, 0xe0, 0x60, 0xa0, 0x20, + 0xc0, 0x40, 0x80, 0x00 + }; + + static readonly byte[] _encryptTable0 = + { + 0xB7, 0xF4, 0x82, 0x57, 0xDA, 0x4D, 0xDB, 0xE2, 0x2F, 0x52, 0x1A, 0xA8, 0x68, 0x5A, 0x8A, 0xFF, 0xFB, 0x0E, + 0x6D, 0x35, 0xF7, 0x5C, 0x76, 0x12, 0xCE, 0x25, 0x79, 0x29, 0x39, 0x62, 0x08, 0x24, 0xA5, 0x85, 0x7B, 0x56, + 0x01, 0x23, 0x68, 0xCF, 0x0A, 0xE2, 0x5A, 0xED, 0x3D, 0x59, 0xB0, 0xA9, 0xB0, 0x2C, 0xF2, 0xB8, 0xEF, 0x32, + 0xA9, 0x40, 0x80, 0x71, 0xAF, 0x1E, 0xDE, 0x8F, 0x58, 0x88, 0xB8, 0x3A, 0xD0, 0xFC, 0xC4, 0x1E, 0xB5, 0xA0, + 0xBB, 0x3B, 0x0F, 0x01, 0x7E, 0x1F, 0x9F, 0xD9, 0xAA, 0xB8, 0x3D, 0x9D, 0x74, 0x1E, 0x25, 0xDB, 0x37, 0x56, + 0x8F, 0x16, 0xBA, 0x49, 0x2B, 0xAC, 0xD0, 0xBD, 0x95, 0x20, 0xBE, 0x7A, 0x28, 0xD0, 0x51, 0x64, 0x63, 0x1C, + 0x7F, 0x66, 0x10, 0xBB, 0xC4, 0x56, 0x1A, 0x04, 0x6E, 0x0A, 0xEC, 0x9C, 0xD6, 0xE8, 0x9A, 0x7A, 0xCF, 0x8C, + 0xDB, 0xB1, 0xEF, 0x71, 0xDE, 0x31, 0xFF, 0x54, 0x3E, 0x5E, 0x07, 0x69, 0x96, 0xB0, 0xCF, 0xDD, 0x9E, 0x47, + 0xC7, 0x96, 0x8F, 0xE4, 0x2B, 0x59, 0xC6, 0xEE, 0xB9, 0x86, 0x9A, 0x64, 0x84, 0x72, 0xE2, 0x5B, 0xA2, 0x96, + 0x58, 0x99, 0x50, 0x03, 0xF5, 0x38, 0x4D, 0x02, 0x7D, 0xE7, 0x7D, 0x75, 0xA7, 0xB8, 0x67, 0x87, 0x84, 0x3F, + 0x1D, 0x11, 0xE5, 0xFC, 0x1E, 0xD3, 0x83, 0x16, 0xA5, 0x29, 0xF6, 0xC7, 0x15, 0x61, 0x29, 0x1A, 0x43, 0x4F, + 0x9B, 0xAF, 0xC5, 0x87, 0x34, 0x6C, 0x0F, 0x3B, 0xA8, 0x1D, 0x45, 0x58, 0x25, 0xDC, 0xA8, 0xA3, 0x3B, 0xD1, + 0x79, 0x1B, 0x48, 0xF2, 0xE9, 0x93, 0x1F, 0xFC, 0xDB, 0x2A, 0x90, 0xA9, 0x8A, 0x3D, 0x39, 0x18, 0xA3, 0x8E, + 0x58, 0x6C, 0xE0, 0x12, 0xBB, 0x25, 0xCD, 0x71, 0x22, 0xA2, 0x64, 0xC6, 0xE7, 0xFB, 0xAD, 0x94, 0x77, 0x04, + 0x9A, 0x39, 0xCF, 0x7C + }; + + static readonly byte[] _encryptTable1 = + { + 0x8C, 0x47, 0xB0, 0xE1, 0xEB, 0xFC, 0xEB, 0x56, 0x10, 0xE5, 0x2C, 0x1A, 0x5D, 0xEF, 0xBE, 0x4F, 0x08, 0x75, + 0x97, 0x4B, 0x0E, 0x25, 0x8E, 0x6E, 0x39, 0x5A, 0x87, 0x53, 0xC4, 0x1F, 0xF4, 0x5C, 0x4E, 0xE6, 0x99, 0x30, + 0xE0, 0x42, 0x88, 0xAB, 0xE5, 0x85, 0xBC, 0x8F, 0xD8, 0x3C, 0x54, 0xC9, 0x53, 0x47, 0x18, 0xD6, 0x06, 0x5B, + 0x41, 0x2C, 0x67, 0x1E, 0x41, 0x74, 0x33, 0xE2, 0xB4, 0xE0, 0x23, 0x29, 0x42, 0xEA, 0x55, 0x0F, 0x25, 0xB4, + 0x24, 0x2C, 0x99, 0x13, 0xEB, 0x0A, 0x0B, 0xC9, 0xF9, 0x63, 0x67, 0x43, 0x2D, 0xC7, 0x7D, 0x07, 0x60, 0x89, + 0xD1, 0xCC, 0xE7, 0x94, 0x77, 0x74, 0x9B, 0x7E, 0xD7, 0xE6, 0xFF, 0xBB, 0x68, 0x14, 0x1E, 0xA3, 0x25, 0xDE, + 0x3A, 0xA3, 0x54, 0x7B, 0x87, 0x9D, 0x50, 0xCA, 0x27, 0xC3, 0xA4, 0x50, 0x91, 0x27, 0xD4, 0xB0, 0x82, 0x41, + 0x97, 0x79, 0x94, 0x82, 0xAC, 0xC7, 0x8E, 0xA5, 0x4E, 0xAA, 0x78, 0x9E, 0xE0, 0x42, 0xBA, 0x28, 0xEA, 0xB7, + 0x74, 0xAD, 0x35, 0xDA, 0x92, 0x60, 0x7E, 0xD2, 0x0E, 0xB9, 0x24, 0x5E, 0x39, 0x4F, 0x5E, 0x63, 0x09, 0xB5, + 0xFA, 0xBF, 0xF1, 0x22, 0x55, 0x1C, 0xE2, 0x25, 0xDB, 0xC5, 0xD8, 0x50, 0x03, 0x98, 0xC4, 0xAC, 0x2E, 0x11, + 0xB4, 0x38, 0x4D, 0xD0, 0xB9, 0xFC, 0x2D, 0x3C, 0x08, 0x04, 0x5A, 0xEF, 0xCE, 0x32, 0xFB, 0x4C, 0x92, 0x1E, + 0x4B, 0xFB, 0x1A, 0xD0, 0xE2, 0x3E, 0xDA, 0x6E, 0x7C, 0x4D, 0x56, 0xC3, 0x3F, 0x42, 0xB1, 0x3A, 0x23, 0x4D, + 0x6E, 0x84, 0x56, 0x68, 0xF4, 0x0E, 0x03, 0x64, 0xD0, 0xA9, 0x92, 0x2F, 0x8B, 0xBC, 0x39, 0x9C, 0xAC, 0x09, + 0x5E, 0xEE, 0xE5, 0x97, 0xBF, 0xA5, 0xCE, 0xFA, 0x28, 0x2C, 0x6D, 0x4F, 0xEF, 0x77, 0xAA, 0x1B, 0x79, 0x8E, + 0x97, 0xB4, 0xC3, 0xF4 + }; + + static readonly byte[] _encryptTable2 = + { + 0xB7, 0x75, 0x81, 0xD5, 0xDC, 0xCA, 0xDE, 0x66, 0x23, 0xDF, 0x15, 0x26, 0x62, 0xD1, 0x83, 0x77, 0xE3, 0x97, + 0x76, 0xAF, 0xE9, 0xC3, 0x6B, 0x8E, 0xDA, 0xB0, 0x6E, 0xBF, 0x2B, 0xF1, 0x19, 0xB4, 0x95, 0x34, 0x48, 0xE4, + 0x37, 0x94, 0x5D, 0x7B, 0x36, 0x5F, 0x65, 0x53, 0x07, 0xE2, 0x89, 0x11, 0x98, 0x85, 0xD9, 0x12, 0xC1, 0x9D, + 0x84, 0xEC, 0xA4, 0xD4, 0x88, 0xB8, 0xFC, 0x2C, 0x79, 0x28, 0xD8, 0xDB, 0xB3, 0x1E, 0xA2, 0xF9, 0xD0, 0x44, + 0xD7, 0xD6, 0x60, 0xEF, 0x14, 0xF4, 0xF6, 0x31, 0xD2, 0x41, 0x46, 0x67, 0x0A, 0xE1, 0x58, 0x27, 0x43, 0xA3, + 0xF8, 0xE0, 0xC8, 0xBA, 0x5A, 0x5C, 0x80, 0x6C, 0xC6, 0xF2, 0xE8, 0xAD, 0x7D, 0x04, 0x0D, 0xB9, 0x3C, 0xC2, + 0x25, 0xBD, 0x49, 0x63, 0x8C, 0x9F, 0x51, 0xCE, 0x20, 0xC5, 0xA1, 0x50, 0x92, 0x2D, 0xDD, 0xBC, 0x8D, 0x4F, + 0x9A, 0x71, 0x2F, 0x30, 0x1D, 0x73, 0x39, 0x13, 0xFB, 0x1A, 0xCB, 0x24, 0x59, 0xFE, 0x05, 0x96, 0x57, 0x0F, + 0x1F, 0xCF, 0x54, 0xBE, 0xF5, 0x06, 0x1B, 0xB2, 0x6D, 0xD3, 0x4D, 0x32, 0x56, 0x21, 0x33, 0x0B, 0x52, 0xE7, + 0xAB, 0xEB, 0xA6, 0x74, 0x00, 0x4C, 0xB1, 0x7F, 0x82, 0x99, 0x87, 0x0E, 0x5E, 0xC0, 0x8F, 0xEE, 0x6F, 0x55, + 0xF3, 0x7E, 0x08, 0x90, 0xFA, 0xB6, 0x64, 0x70, 0x47, 0x4A, 0x17, 0xA7, 0xB5, 0x40, 0x8A, 0x38, 0xE5, 0x68, + 0x3E, 0x8B, 0x69, 0xAA, 0x9B, 0x42, 0xA5, 0x10, 0x01, 0x35, 0xFD, 0x61, 0x9E, 0xE6, 0x16, 0x9C, 0x86, 0xED, + 0xCD, 0x2E, 0xFF, 0xC4, 0x5B, 0xA0, 0xAE, 0xCC, 0x4B, 0x3B, 0x03, 0xBB, 0x1C, 0x2A, 0xAC, 0x0C, 0x3F, 0x93, + 0xC7, 0x72, 0x7A, 0x09, 0x22, 0x3D, 0x45, 0x78, 0xA9, 0xA8, 0xEA, 0xC9, 0x6A, 0xF7, 0x29, 0x91, 0xF0, 0x02, + 0x18, 0x3A, 0x4E, 0x7C + }; + + static readonly byte[] _encryptTable3 = + { + 0x73, 0x51, 0x95, 0xE1, 0x12, 0xE4, 0xC0, 0x58, 0xEE, 0xF2, 0x08, 0x1B, 0xA9, 0xFA, 0x98, 0x4C, 0xA7, 0x33, + 0xE2, 0x1B, 0xA7, 0x6D, 0xF5, 0x30, 0x97, 0x1D, 0xF3, 0x02, 0x60, 0x5A, 0x82, 0x0F, 0x91, 0xD0, 0x9C, 0x10, + 0x39, 0x7A, 0x83, 0x85, 0x3B, 0xB2, 0xB8, 0xAE, 0x0C, 0x09, 0x52, 0xEA, 0x1C, 0xE1, 0x8D, 0x66, 0x4F, 0xF3, + 0xDA, 0x92, 0x29, 0xB9, 0xD5, 0xC5, 0x77, 0x47, 0x22, 0x53, 0x14, 0xF7, 0xAF, 0x22, 0x64, 0xDF, 0xC6, 0x72, + 0x12, 0xF3, 0x75, 0xDA, 0xD7, 0xD7, 0xE5, 0x02, 0x9E, 0xED, 0xDA, 0xDB, 0x4C, 0x47, 0xCE, 0x91, 0x06, 0x06, + 0x6D, 0x55, 0x8B, 0x19, 0xC9, 0xEF, 0x8C, 0x80, 0x1A, 0x0E, 0xEE, 0x4B, 0xAB, 0xF2, 0x08, 0x5C, 0xE9, 0x37, + 0x26, 0x5E, 0x9A, 0x90, 0x00, 0xF3, 0x0D, 0xB2, 0xA6, 0xA3, 0xF7, 0x26, 0x17, 0x48, 0x88, 0xC9, 0x0E, 0x2C, + 0xC9, 0x02, 0xE7, 0x18, 0x05, 0x4B, 0xF3, 0x39, 0xE1, 0x20, 0x02, 0x0D, 0x40, 0xC7, 0xCA, 0xB9, 0x48, 0x30, + 0x57, 0x67, 0xCC, 0x06, 0xBF, 0xAC, 0x81, 0x08, 0x24, 0x7A, 0xD4, 0x8B, 0x19, 0x8E, 0xAC, 0xB4, 0x5A, 0x0F, + 0x73, 0x13, 0xAC, 0x9E, 0xDA, 0xB6, 0xB8, 0x96, 0x5B, 0x60, 0x88, 0xE1, 0x81, 0x3F, 0x07, 0x86, 0x37, 0x2D, + 0x79, 0x14, 0x52, 0xEA, 0x73, 0xDF, 0x3D, 0x09, 0xC8, 0x25, 0x48, 0xD8, 0x75, 0x60, 0x9A, 0x08, 0x27, 0x4A, + 0x2C, 0xB9, 0xA8, 0x8B, 0x8A, 0x73, 0x62, 0x37, 0x16, 0x02, 0xBD, 0xC1, 0x0E, 0x56, 0x54, 0x3E, 0x14, 0x5F, + 0x8C, 0x8F, 0x6E, 0x75, 0x1C, 0x07, 0x39, 0x7B, 0x4B, 0xDB, 0xD3, 0x4B, 0x1E, 0xC8, 0x7E, 0xFE, 0x3E, 0x72, + 0x16, 0x83, 0x7D, 0xEE, 0xF5, 0xCA, 0xC5, 0x18, 0xF9, 0xD8, 0x68, 0xAB, 0x38, 0x85, 0xA8, 0xF0, 0xA1, 0x73, + 0x9F, 0x5D, 0x19, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x72, 0x39, 0x25, 0x67, 0x26, + 0x6D, 0x71, 0x36, 0x77, 0x3C, 0x20, 0x62, 0x23, 0x68, 0x74, 0xC3, 0x82, 0xC9, 0x15, 0x57, 0x16, 0x5D, 0x81 + }; + + static readonly byte[,] _permutationChallenge = + { + { + 1, 3, 0, 7, 5, 2, 9, 6, 4, 8 + }, + { + 6, 1, 9, 3, 8, 5, 7, 4, 0, 2 + }, + { + 4, 0, 3, 5, 7, 2, 8, 6, 1, 9 + } + }; + + static readonly byte[,] _permutationVariant = + { + { + 0x0a, 0x08, 0x0e, 0x0c, 0x0b, 0x09, 0x0f, 0x0d, 0x1a, 0x18, 0x1e, 0x1c, 0x1b, 0x19, 0x1f, 0x1d, 0x02, + 0x00, 0x06, 0x04, 0x03, 0x01, 0x07, 0x05, 0x12, 0x10, 0x16, 0x14, 0x13, 0x11, 0x17, 0x15 + }, + { + 0x12, 0x1a, 0x16, 0x1e, 0x02, 0x0a, 0x06, 0x0e, 0x10, 0x18, 0x14, 0x1c, 0x00, 0x08, 0x04, 0x0c, 0x13, + 0x1b, 0x17, 0x1f, 0x03, 0x0b, 0x07, 0x0f, 0x11, 0x19, 0x15, 0x1d, 0x01, 0x09, 0x05, 0x0d + } + }; + + static readonly byte[] _variants = + { + 0xB7, 0x74, 0x85, 0xD0, 0xCC, 0xDB, 0xCA, 0x73, 0x03, 0xFE, 0x31, 0x03, 0x52, 0xE0, 0xB7, 0x42, 0x63, 0x16, + 0xF2, 0x2A, 0x79, 0x52, 0xFF, 0x1B, 0x7A, 0x11, 0xCA, 0x1A, 0x9B, 0x40, 0xAD, 0x01 + }; + + static readonly byte[] _secret = + { + 0x55, 0xD6, 0xC4, 0xC5, 0x28 + }; + + /// + /// The disc key returned by the logical unit is encoded with the bus key to prevent man-in-the-middle attacks. + /// This method returns a structure with the decoded key included. + /// + /// The encoded key from the logical unit. + /// The bus key from the logical unit. + /// A DiscKey struct with the decoded key. + public static CSS_CPRM.DiscKey? DecodeDiscKey(byte[] response, byte[] busKey) + { + if(response.Length != 2052 || + busKey.Length != 5) + return null; + + byte[] key = response.Skip(4).Take(2048).ToArray(); + + for(uint i = 0; i < key.Length; i++) + key[i] ^= busKey[4 - (i % busKey.Length)]; + + return new CSS_CPRM.DiscKey + { + DataLength = (ushort)((response[0] << 8) + response[1]), + Reserved1 = response[2], + Reserved2 = response[3], + Key = key + }; + } + + /// + /// The title key returned by the logical unit is encoded with the bus key to prevent man-in-the-middle attacks. + /// This method returns a structure with the decoded key included. + /// + /// The encoded key from the logical unit. + /// The bus key from the logical unit. + /// A TitleKey struct with the decoded key. + public static CSS_CPRM.TitleKey? DecodeTitleKey(byte[] response, byte[] busKey) + { + if(response.Length != 12 || + busKey.Length != 5) + return null; + + byte[] key = response.Skip(5).Take(5).ToArray(); + + for(uint i = 0; i < key.Length; i++) + key[i] ^= busKey[4 - (i % busKey.Length)]; + + return new CSS_CPRM.TitleKey + { + DataLength = (ushort)((response[0] << 8) + response[1]), + Reserved1 = response[2], + Reserved2 = response[3], + CMI = response[4], + Key = key, + Reserved3 = response[10], + Reserved4 = response[11] + }; + } + + /// Takes a challenge and a variant and encrypts it according to the key type. + /// The type of key to encrypt. + /// + /// The challenge sent to the logical unit. + /// The encrypted key. + /// The encrypted key. + public static void EncryptKey(DvdCssKeyType keyType, uint variant, byte[] challenge, out byte[] key) + { + byte[] bits = new byte[30]; + byte[] scratch = new byte[10]; + byte index = sizeof(byte) * 30; + byte[] temp1 = new byte[5]; + byte[] temp2 = new byte[5]; + byte carry = 0; + key = new byte[5]; + + for(int i = 9; i >= 0; --i) + scratch[i] = challenge[_permutationChallenge[(uint)keyType, i]]; + + byte cssVariant = (byte)(keyType == 0 ? variant : _permutationVariant[(uint)keyType - 1, variant]); + + for(int i = 5; --i >= 0;) + temp1[i] = (byte)(scratch[5 + i] ^ _secret[i] ^ _encryptTable2[i]); + + uint lfsr0 = (uint)((temp1[0] << 17) | (temp1[1] << 9) | ((temp1[2] & ~7) << 1) | 8 | (temp1[2] & 7)); + uint lfsr1 = (uint)((temp1[3] << 9) | 0x100 | temp1[4]); + + do + { + byte val = 0; + + for(int bit = 0; bit < 8; ++bit) + { + byte oLfsr0 = (byte)(((lfsr0 >> 24) ^ (lfsr0 >> 21) ^ (lfsr0 >> 20) ^ (lfsr0 >> 12)) & 1); + lfsr0 = (lfsr0 << 1) | oLfsr0; + + byte oLfsr1 = (byte)(((lfsr1 >> 16) ^ (lfsr1 >> 2)) & 1); + lfsr1 = (lfsr1 << 1) | oLfsr1; + + byte combined = (byte)(Convert.ToByte(oLfsr1 == 0) + carry + Convert.ToByte(oLfsr0 == 0)); + carry = (byte)((combined >> 1) & 1); + val |= (byte)((combined & 1) << bit); + } + + bits[--index] = val; + } while(index > 0); + + byte cse = (byte)(_variants[cssVariant] ^ _encryptTable2[cssVariant]); + int term = 0; + + for(int i = 5; --i >= 0; term = scratch[i]) + { + index = (byte)(bits[25 + i] ^ scratch[i]); + index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse); + + temp1[i] = (byte)(_encryptTable2[index] ^ _encryptTable3[index] ^ term); + } + + temp1[4] ^= temp1[0]; + term = 0; + + for(int i = 5; --i >= 0; term = temp1[i]) + { + index = (byte)(bits[20 + i] ^ temp1[i]); + index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse); + + temp2[i] = (byte)(_encryptTable2[index] ^ _encryptTable3[index] ^ term); + } + + temp2[4] ^= temp2[0]; + term = 0; + + for(int i = 5; --i >= 0; term = temp2[i]) + { + index = (byte)(bits[15 + i] ^ temp2[i]); + index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse); + index = (byte)(_encryptTable2[index] ^ _encryptTable3[index] ^ term); + + temp1[i] = (byte)(_encryptTable0[index] ^ _encryptTable2[index]); + } + + temp1[4] ^= temp1[0]; + term = 0; + + for(int i = 5; --i >= 0; term = temp1[i]) + { + index = (byte)(bits[10 + i] ^ temp1[i]); + index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse); + index = (byte)(_encryptTable2[index] ^ _encryptTable3[index] ^ term); + + temp2[i] = (byte)(_encryptTable0[index] ^ _encryptTable2[index]); + } + + temp2[4] ^= temp2[0]; + term = 0; + + for(int i = 5; --i >= 0; term = temp2[i]) + { + index = (byte)(bits[5 + i] ^ temp2[i]); + index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse); + + temp1[i] = (byte)(_encryptTable2[index] ^ _encryptTable3[index] ^ term); + } + + temp1[4] ^= temp1[0]; + term = 0; + + for(int i = 5; --i >= 0; term = temp1[i]) + { + index = (byte)(bits[i] ^ temp1[i]); + index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse); + + key[i] = (byte)(_encryptTable2[index] ^ _encryptTable3[index] ^ term); + } + } + + /// Takes an encrypted key and its crypto and returns the key decrypted. + /// + /// The key used to encrypt the data. + /// The encrypted data. + /// The decrypted data. + public static void DecryptKey(byte invert, byte[] cryptoKey, byte[] encryptedKey, out byte[] decryptedKey) + { + decryptedKey = new byte[5]; + byte[] k = new byte[5]; + + uint lfsr1Lo = (uint)(cryptoKey[0] | 0x100); + uint lfsr1Hi = cryptoKey[1]; + + uint lfsr0 = (uint)(((cryptoKey[4] << 17) | (cryptoKey[3] << 9) | (cryptoKey[2] << 1)) + 8 - + (cryptoKey[2] & 7)); + + lfsr0 = (uint)((_cssTable4[lfsr0 & 0xff] << 24) | (_cssTable4[(lfsr0 >> 8) & 0xff] << 16) | + (_cssTable4[(lfsr0 >> 16) & 0xff] << 8) | _cssTable4[(lfsr0 >> 24) & 0xff]); + + uint combined = 0; + + for(uint i = 0; i < 5; i++) + { + byte oLfsr1 = (byte)(_cssTable2[lfsr1Hi] ^ _cssTable3[lfsr1Lo]); + lfsr1Hi = lfsr1Lo >> 1; + lfsr1Lo = ((lfsr1Lo & 1) << 8) ^ oLfsr1; + oLfsr1 = _cssTable4[oLfsr1]; + byte oLfsr0 = (byte)(((((((lfsr0 >> 8) ^ lfsr0) >> 1) ^ lfsr0) >> 3) ^ lfsr0) >> 7); + lfsr0 = (lfsr0 >> 8) | ((uint)oLfsr0 << 24); + combined += (uint)((oLfsr0 ^ invert) + oLfsr1); + k[i] = (byte)(combined & 0xff); + combined >>= 8; + } + + decryptedKey[4] = (byte)(k[4] ^ _cssTable1[encryptedKey[4]] ^ encryptedKey[3]); + decryptedKey[3] = (byte)(k[3] ^ _cssTable1[encryptedKey[3]] ^ encryptedKey[2]); + decryptedKey[2] = (byte)(k[2] ^ _cssTable1[encryptedKey[2]] ^ encryptedKey[1]); + decryptedKey[1] = (byte)(k[1] ^ _cssTable1[encryptedKey[1]] ^ encryptedKey[0]); + decryptedKey[0] = (byte)(k[0] ^ _cssTable1[encryptedKey[0]] ^ decryptedKey[4]); + + decryptedKey[4] = (byte)(k[4] ^ _cssTable1[decryptedKey[4]] ^ decryptedKey[3]); + decryptedKey[3] = (byte)(k[3] ^ _cssTable1[decryptedKey[3]] ^ decryptedKey[2]); + decryptedKey[2] = (byte)(k[2] ^ _cssTable1[decryptedKey[2]] ^ decryptedKey[1]); + decryptedKey[1] = (byte)(k[1] ^ _cssTable1[decryptedKey[1]] ^ decryptedKey[0]); + decryptedKey[0] = (byte)(k[0] ^ _cssTable1[decryptedKey[0]]); + } + + public static void + DecryptTitleKey(byte invert, byte[] cryptoKey, byte[] encryptedKey, out byte[] decryptedKey) => + DecryptKey(invert, cryptoKey, encryptedKey, out decryptedKey); + + /// Takes an bytearray of encrypted keys, decrypts them and returns the correctly decrypted key. + /// Encrypted keys to try to decrypt. + /// The decrypted key if found. + public static void DecryptDiscKey(byte[] encryptedKeys, out byte[]? decryptedKey) + { + decryptedKey = new byte[5]; + byte[] verificationKey = encryptedKeys.Take(5).ToArray(); + + for(uint n = 0; n < _playerKeys.GetLength(0); n++) + { + byte[] currentPlayerKey = Enumerable.Range(0, _playerKeys.GetLength(1)).Select(x => _playerKeys[n, x]). + ToArray(); + + for(uint i = 1; i < 409; i++) + { + DecryptKey(0, currentPlayerKey, encryptedKeys.Skip(5 * (int)i).Take(5).ToArray(), out decryptedKey); + + // The first key in the structure is the key encrypted with itself, so we can use it to verify + // we found the correct key. + DecryptKey(0, decryptedKey, verificationKey, out byte[] verify); + + if(decryptedKey.SequenceEqual(verify)) + { + return; + } + } + } + + // No correct key was found. + decryptedKey = null; + } + + /// Takes a sector and a decrypted title key and returns the decrypted sector. + /// Encrypted sector data. + /// The Copyright Management Information. + /// The encryption keys. + /// Number of sectors in sectorData. + /// Size of one sector. + /// The decrypted sector. + public static byte[] DecryptSector(byte[] sectorData, byte[] cmiData, byte[] keyData, uint blocks = 1, + uint blockSize = 2048) + { + if(cmiData.All(cmi => (cmi & 0x80) >> 7 == 0) || + keyData.All(k => k == 0)) + return sectorData; + + byte[] decryptedBuffer = new byte[sectorData.Length]; + + for(uint j = 0; j < blocks; j++) + { + byte[] currentKey = keyData.Skip((int)(j * 5)).Take(5).ToArray(); + byte[] currentSector = sectorData.Skip((int)(j * blockSize)).Take((int)blockSize).ToArray(); + + // If the CMI tells use the sector isn't encrypted or + // if the key is all zeroes or + // if the MPEG Packetized Elementary Stream scrambling control value tells us the packet is not scrambled + if((cmiData[j] & 0x80) >> 7 == 0 || + currentKey.All(k => k == 0) || + (currentSector[20] & 0x30) >> 4 == 0) + { + // Sector is not encrypted + Array.Copy(currentSector, 0, decryptedBuffer, (int)(j * blockSize), blockSize); + + continue; + } + + uint lfsr1Lo = (uint)(currentKey[0] ^ currentSector[0x54]) | 0x100; + uint lfsr1Hi = (uint)currentKey[1] ^ currentSector[0x55]; + + uint lfsr0 = (uint)((currentKey[2] | (currentKey[3] << 8) | (currentKey[4] << 16)) ^ + (sectorData[0x56] | (sectorData[0x57] << 8) | (sectorData[0x58] << 16))); + + uint oLfsr1 = lfsr0 & 7; + lfsr0 = (lfsr0 * 2) + 8 - oLfsr1; + + uint combined = 0; + + for(uint i = 128; i < blockSize; i++) + { + oLfsr1 = (uint)(_cssTable2[lfsr1Hi] ^ _cssTable3[lfsr1Lo]); + lfsr1Hi = lfsr1Lo >> 1; + lfsr1Lo = ((lfsr1Lo & 1) << 8) ^ oLfsr1; + oLfsr1 = _cssTable5[oLfsr1]; + uint oLfsr0 = (((((((lfsr0 >> 3) ^ lfsr0) >> 1) ^ lfsr0) >> 8) ^ lfsr0) >> 5) & 0xff; + lfsr0 = (lfsr0 >> 8) | (oLfsr0 << 24); + lfsr0 = (lfsr0 << 8) | oLfsr0; + oLfsr0 = _cssTable4[oLfsr0]; + combined += oLfsr0 + oLfsr1; + currentSector[i] = (byte)(_cssTable1[currentSector[i]] ^ (combined & 0xff)); + combined >>= 8; + } + + Array.Copy(currentSector, 0, decryptedBuffer, (int)(j * blockSize), blockSize); + } + + return decryptedBuffer; + } + + /// Takes an RPC state from the drive and a CMI from a disc and checks if the regions are compatible. + /// The RegionalPlaybackControlState from drive. + /// The LeadInCopyright from disc. + /// true if the regions are compatible, else false + public static bool CheckRegion(CSS_CPRM.RegionalPlaybackControlState rpc, CSS_CPRM.LeadInCopyright cmi) + { + // if disc region is all or none, we cannot do anything but try to read it as is + if(cmi.RegionInformation == 0xFF || + cmi.RegionInformation == 0x00) + return true; + + return ((rpc.RegionMask & 0x01) == (cmi.RegionInformation & 0x01) && (rpc.RegionMask & 0x01) != 0x01) || + ((rpc.RegionMask & 0x02) == (cmi.RegionInformation & 0x02) && (rpc.RegionMask & 0x02) != 0x02) || + ((rpc.RegionMask & 0x04) == (cmi.RegionInformation & 0x04) && (rpc.RegionMask & 0x04) != 0x04) || + ((rpc.RegionMask & 0x08) == (cmi.RegionInformation & 0x08) && (rpc.RegionMask & 0x08) != 0x08) || + ((rpc.RegionMask & 0x10) == (cmi.RegionInformation & 0x10) && (rpc.RegionMask & 0x10) != 0x10) || + ((rpc.RegionMask & 0x20) == (cmi.RegionInformation & 0x20) && (rpc.RegionMask & 0x20) != 0x20) || + ((rpc.RegionMask & 0x40) == (cmi.RegionInformation & 0x40) && (rpc.RegionMask & 0x40) != 0x40) || + ((rpc.RegionMask & 0x80) == (cmi.RegionInformation & 0x80) && (rpc.RegionMask & 0x80) != 0x80); + } + } +} \ No newline at end of file diff --git a/Aaru.Decryption/DVD/Dump.cs b/Aaru.Decryption/DVD/Dump.cs new file mode 100644 index 000000000..59ab07b99 --- /dev/null +++ b/Aaru.Decryption/DVD/Dump.cs @@ -0,0 +1,508 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Dump.cs +// Author(s) : Rebecca Wallander +// +// --[ Description ] ---------------------------------------------------------- +// +// SCSI read commands related to Content Scrambling System. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2020-2023 Rebecca Wallander +// ****************************************************************************/ + +using System; +using System.Linq; +using Aaru.Console; +using Aaru.Decoders.DVD; +using Aaru.Devices; + +namespace Aaru.Decryption.DVD +{ + public sealed class Dump + { + const byte KEY_SIZE = 5; + const byte CHALLENGE_SIZE = 2 * KEY_SIZE; + readonly Device _dev; + + public Dump(Device dev) + { + _dev = dev; + BusKey = Array.Empty(); + Agid = 0; + } + + public byte Agid { get; private set; } + public byte[] BusKey { get; private set; } + + /// Returns the Authentication Success Flag of the logical unit. + /// true if the command failed and contains the sense buffer. + /// Buffer where the Authentication Success Flag will be stored. + /// Sense buffer. + /// Key class. + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + public bool ReadAsf(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, uint timeout, + out double duration) + { + senseBuffer = new byte[64]; + byte[] cdb = new byte[12]; + buffer = new byte[8]; + + cdb[0] = (byte)ScsiCommands.ReportKey; + cdb[7] = (byte)keyClass; + cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); + cdb[9] = (byte)(buffer.Length & 0xFF); + cdb[10] = (byte)((byte)CssReportKeyFormat.Asf ^ ((Agid & 0x03) << 6)); + + _dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, + out bool sense); + + AaruConsole.DebugWriteLine("SCSI Device", + "REPORT ASF (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.", duration, + Agid, sense, _dev.LastError); + + return sense; + } + + /// Returns the Regional Playback Control State of the logical unit. + /// true if the command failed and contains the sense buffer. + /// Buffer where the Regional Playback Control State will be stored. + /// Sense buffer. + /// Key class. + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + public bool ReadRpc(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, uint timeout, + out double duration) + { + senseBuffer = new byte[64]; + byte[] cdb = new byte[12]; + buffer = new byte[8]; + + cdb[0] = (byte)ScsiCommands.ReportKey; + cdb[7] = (byte)keyClass; + cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); + cdb[9] = (byte)(buffer.Length & 0xFF); + cdb[10] = (byte)((byte)CssReportKeyFormat.RpcState ^ ((Agid & 0x03) << 6)); + + _dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, + out bool sense); + + AaruConsole.DebugWriteLine("SCSI Device", + "REPORT ASF (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.", duration, + Agid, sense, _dev.LastError); + + return sense; + } + + /// Invalidates an Authentication Grant ID. + /// Buffer where the Regional Playback Control State will be stored. + /// Sense buffer. + /// Key class. + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + /// true if the command failed and contains the sense buffer. + public bool InvalidateAgid(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, uint timeout, + out double duration) + { + senseBuffer = new byte[64]; + byte[] cdb = new byte[12]; + buffer = Array.Empty(); + + cdb[0] = (byte)ScsiCommands.ReportKey; + cdb[7] = (byte)keyClass; + cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); + cdb[9] = (byte)(buffer.Length & 0xFF); + cdb[10] = (byte)((byte)CssReportKeyFormat.InvalidateAgid ^ ((Agid & 0x03) << 6)); + + _dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, + out bool sense); + + AaruConsole.DebugWriteLine("SCSI Device", + "INVALIDATE AGID (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.", + duration, Agid, sense, _dev.LastError); + + return sense; + } + + /// Returns a valid Authentication Grant ID for CSS/CPPM. + /// Buffer where the Regional Playback Control State will be stored. + /// Sense buffer. + /// Key class. + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + /// true if the command failed and contains the sense buffer. + public bool ReportAgidCssCppm(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, uint timeout, + out double duration) + { + senseBuffer = new byte[64]; + byte[] cdb = new byte[12]; + buffer = new byte[8]; + + cdb[0] = (byte)ScsiCommands.ReportKey; + cdb[7] = (byte)keyClass; + cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); + cdb[9] = (byte)(buffer.Length & 0xFF); + cdb[10] = (byte)((byte)CssReportKeyFormat.AgidForCssCppm ^ ((Agid & 0x03) << 6)); + + _dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, + out bool sense); + + AaruConsole.DebugWriteLine("SCSI Device", + "REPORT AGID CSS/CPPM (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.", + duration, Agid, sense, _dev.LastError); + + return sense; + } + + /// Returns KEY1 from the logical unit. + /// Buffer where the Regional Playback Control State will be stored. + /// Sense buffer. + /// Key class. + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + /// true if the command failed and contains the sense buffer. + public bool ReportKey1(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, uint timeout, + out double duration) + { + senseBuffer = new byte[64]; + byte[] cdb = new byte[12]; + buffer = new byte[12]; + + cdb[0] = (byte)ScsiCommands.ReportKey; + cdb[7] = (byte)keyClass; + cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); + cdb[9] = (byte)(buffer.Length & 0xFF); + cdb[10] = (byte)((byte)CssReportKeyFormat.Key1 ^ ((Agid & 0x03) << 6)); + + _dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, + out bool sense); + + AaruConsole.DebugWriteLine("SCSI Device", + "REPORT KEY1 (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.", duration, + Agid, sense, _dev.LastError); + + return sense; + } + + /// Returns the challenge from the logical unit. + /// Buffer where the Regional Playback Control State will be stored. + /// Sense buffer. + /// Key class. + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + /// true if the command failed and contains the sense buffer. + public bool ReportChallenge(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, uint timeout, + out double duration) + { + senseBuffer = new byte[64]; + byte[] cdb = new byte[12]; + buffer = new byte[16]; + + cdb[0] = (byte)ScsiCommands.ReportKey; + cdb[7] = (byte)keyClass; + cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); + cdb[9] = (byte)(buffer.Length & 0xFF); + cdb[10] = (byte)((byte)CssReportKeyFormat.ChallengeKey ^ ((Agid & 0x03) << 6)); + + _dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, + out bool sense); + + AaruConsole.DebugWriteLine("SCSI Device", + "REPORT CHALLENGE (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.", + duration, Agid, sense, _dev.LastError); + + return sense; + } + + /// Send a challenge to the logical unit. + /// Buffer where the Regional Playback Control State will be stored. + /// Sense buffer. + /// Key class. + /// The challenge; can be any 10 bytes. + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + /// true if the command failed and contains the sense buffer. + public bool SendChallenge(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, + byte[] challengeKey, uint timeout, out double duration) + { + senseBuffer = new byte[64]; + byte[] cdb = new byte[12]; + buffer = new byte[16]; + + cdb[0] = (byte)ScsiCommands.SendKey; + cdb[7] = (byte)keyClass; + cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); + cdb[9] = (byte)(buffer.Length & 0xFF); + cdb[10] = (byte)((byte)CssSendKeyFormat.ChallengeKey ^ ((Agid & 0x03) << 6)); + buffer[0] = (byte)(((buffer.Length - 2) & 0xFF00) >> 8); + buffer[1] = (byte)((buffer.Length - 2) & 0xFF); + buffer[4] = challengeKey[9]; + buffer[5] = challengeKey[8]; + buffer[6] = challengeKey[7]; + buffer[7] = challengeKey[6]; + buffer[8] = challengeKey[5]; + buffer[9] = challengeKey[4]; + buffer[10] = challengeKey[3]; + buffer[11] = challengeKey[2]; + buffer[12] = challengeKey[1]; + buffer[13] = challengeKey[0]; + + _dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.Out, out duration, + out bool sense); + + AaruConsole.DebugWriteLine("SCSI Device", + "SEND CHALLENGE (AGID: {1}, Challenge {2}, Sense: {3}, Last Error: {4}) took {0} ms.", + duration, Agid, challengeKey, sense, _dev.LastError); + + return sense; + } + + /// Send KEY2 to the logical unit. + /// Buffer where the Regional Playback Control State will be stored. + /// Sense buffer. + /// Key class. + /// The KEY2 message. + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + /// true if the command failed and contains the sense buffer. + public bool SendKey2(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, byte[] key2, + uint timeout, out double duration) + { + senseBuffer = new byte[64]; + byte[] cdb = new byte[12]; + buffer = new byte[12]; + + cdb[0] = (byte)ScsiCommands.SendKey; + cdb[7] = (byte)keyClass; + cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); + cdb[9] = (byte)(buffer.Length & 0xFF); + cdb[10] = (byte)((byte)CssSendKeyFormat.Key2 ^ ((Agid & 0x03) << 6)); + buffer[0] = (byte)(((buffer.Length - 2) & 0xFF00) >> 8); + buffer[1] = (byte)((buffer.Length - 2) & 0xFF); + buffer[4] = key2[4]; + buffer[5] = key2[3]; + buffer[6] = key2[2]; + buffer[7] = key2[1]; + buffer[8] = key2[0]; + + _dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.Out, out duration, + out bool sense); + + AaruConsole.DebugWriteLine("SCSI Device", + "SEND CHALLENGE (AGID: {1}, KEY2 {2}, Sense: {3}, Last Error: {4}) took {0} ms.", + duration, Agid, key2, sense, _dev.LastError); + + return sense; + } + + /// Returns the encrypted disc key of the MMC logical unit + /// true if the command failed and contains the sense buffer. + /// Buffer where the bus key will be stored + /// Sense buffer. + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + public bool ReadDiscKey(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration) + { + senseBuffer = new byte[64]; + byte[] cdb = new byte[12]; + buffer = new byte[2052]; + + cdb[0] = (byte)ScsiCommands.ReadDiscStructure; + cdb[1] = (byte)MmcDiscStructureMediaType.Dvd & 0x0F; + cdb[6] = 0; + cdb[7] = (byte)MmcDiscStructureFormat.DiscKey; + cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); + cdb[9] = (byte)(buffer.Length & 0xFF); + cdb[10] = (byte)((Agid & 0x03) << 6); + + _dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, + out bool sense); + + return sense; + } + + /// Returns the bus key of the MMC logical unit + /// true if the command failed and contains the sense buffer. + /// Buffer where the bus key will be stored + /// Sense buffer. + /// The type of protection the logical unit reports + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + public bool ReadBusKey(out byte[] buffer, out byte[] senseBuffer, CopyrightType protectionType, uint timeout, + out double duration) + { + duration = 0; + buffer = Array.Empty(); + senseBuffer = new byte[64]; + + bool sense = false; + byte[] challenge = new byte[CHALLENGE_SIZE]; + byte[] key1 = new byte[KEY_SIZE]; + byte variant = 0; + + for(byte i = 0; i < 4; i++) + { + // Invalidate AGID to reset any previous drive communications + Agid = i; + + sense = InvalidateAgid(out buffer, out senseBuffer, DvdCssKeyClass.DvdCssCppmOrCprm, timeout, + out duration); + + // Get AGID + if(protectionType == CopyrightType.CSS) + { + sense = ReportAgidCssCppm(out buffer, out senseBuffer, DvdCssKeyClass.DvdCssCppmOrCprm, timeout, + out duration); + } + + if(protectionType == CopyrightType.CPRM) + { + throw new NotImplementedException(); + } + + if(!sense) + { + Agid = (byte)(buffer[7] >> 6); + + break; + } + } + + if(sense) + { + return true; + } + + for(byte i = 0; i < CHALLENGE_SIZE; i++) + challenge[i] = i; + + sense = SendChallenge(out buffer, out senseBuffer, DvdCssKeyClass.DvdCssCppmOrCprm, challenge, timeout, + out duration); + + if(sense) + { + return true; + } + + sense = ReportKey1(out buffer, out senseBuffer, DvdCssKeyClass.DvdCssCppmOrCprm, timeout, out duration); + + if(sense) + { + return true; + } + + for(byte i = 0; i < KEY_SIZE; i++) + key1[i] = buffer[8 - i]; + + for(byte i = 0; i < 32; i++) + { + CSS.EncryptKey(DvdCssKeyType.Key1, i, challenge, out byte[] keyCheck); + + if(key1.SequenceEqual(keyCheck)) + { + variant = i; + + break; + } + + if(i >= 31) + { + senseBuffer = Array.Empty(); + + return true; + } + } + + sense = ReportChallenge(out buffer, out senseBuffer, DvdCssKeyClass.DvdCssCppmOrCprm, timeout, + out duration); + + if(sense) + { + return true; + } + + for(byte i = 0; i < CHALLENGE_SIZE; i++) + challenge[i] = buffer[13 - i]; + + CSS.EncryptKey(DvdCssKeyType.Key2, variant, challenge, out byte[] key2); + + sense = SendKey2(out buffer, out senseBuffer, DvdCssKeyClass.DvdCssCppmOrCprm, key2, timeout, out duration); + + if(sense) + { + return true; + } + + key1.CopyTo(challenge, 0); + key2.CopyTo(challenge, key1.Length); + CSS.EncryptKey(DvdCssKeyType.BusKey, variant, challenge, out buffer); + + BusKey = buffer; + + return false; + } + + /// Reads a title key for a sector on the disc. + /// Buffer where the bus key will be stored + /// Sense buffer. + /// Key class. + /// The sector address to get the key for. + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + /// true if the command failed and contains the sense buffer. + public bool ReadTitleKey(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, ulong address, + uint timeout, out double duration) + { + // We need to be in a bus key state to read title keys. Only CSS has title keys. + ReadBusKey(out buffer, out senseBuffer, CopyrightType.CSS, timeout, out duration); + + BusKey = buffer; + + senseBuffer = new byte[64]; + byte[] cdb = new byte[12]; + buffer = new byte[12]; + + cdb[0] = (byte)ScsiCommands.ReportKey; + cdb[2] = (byte)((address & 0xFF000000) >> 24); + cdb[3] = (byte)((address & 0xFF0000) >> 16); + cdb[4] = (byte)((address & 0xFF00) >> 8); + cdb[5] = (byte)(address & 0xFF); + cdb[7] = (byte)keyClass; + cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8); + cdb[9] = (byte)(buffer.Length & 0xFF); + cdb[10] = (byte)((byte)CssReportKeyFormat.TitleKey ^ ((Agid & 0x03) << 6)); + + _dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, + out bool sense); + + AaruConsole.DebugWriteLine("SCSI Device", "GET TITLE KEY (AGID: {1}, LBA: {2}, Sense: {3}) took {0} ms.", + duration, Agid, address, sense); + + return sense; + } + } +} \ No newline at end of file diff --git a/Aaru.Decryption/Enums.cs b/Aaru.Decryption/Enums.cs new file mode 100644 index 000000000..947a5e238 --- /dev/null +++ b/Aaru.Decryption/Enums.cs @@ -0,0 +1,12 @@ +namespace Aaru.Decryption +{ + public enum DvdCssKeyClass : byte + { + DvdCssCppmOrCprm = 0, RewritableSecurityServicesA = 1 + } + + public enum DvdCssKeyType + { + Key1 = 0, Key2 = 1, BusKey = 2 + } +} \ No newline at end of file diff --git a/Aaru.Decryption/LICENSE b/Aaru.Decryption/LICENSE new file mode 100644 index 000000000..b4f38daad --- /dev/null +++ b/Aaru.Decryption/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-2023 Natalia Portillo + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Aaru.Dto b/Aaru.Dto deleted file mode 160000 index f3fddee41..000000000 --- a/Aaru.Dto +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f3fddee4195e00dd083818b9bf76ae08d1b72d65 diff --git a/Aaru.Dto/.editorconfig b/Aaru.Dto/.editorconfig new file mode 100644 index 000000000..8b506dabe --- /dev/null +++ b/Aaru.Dto/.editorconfig @@ -0,0 +1,632 @@ +root = true + +[*] +charset=utf-8 +next_line=crlf +insert_final_newline=false +indent_style=space +indent_size=4 + +# Generic non-language specific ones for Resharper and friends +brace_style=next_line +int_align=true +keep_existing_arrangement=false +place_simple_blocks_on_single_line=true +place_simple_declaration_blocks_on_single_line=true +place_attribute_on_same_line=false +space_after_unary_operator=false +space_after_comma=true +space_around_ternary_operator=true +space_around_binary_operator=true +space_around_member_access_operator=false +space_before_open_square_brackets=false +space_after_keywords_in_control_flow_statements=true +space_before_comma=false +space_between_method_call_name_and_opening_parenthesis=false +space_between_method_declaration_name_and_open_parenthesis=false +space_between_square_brackets=false +space_between_parentheses_of_control_flow_statements=false +accessor_owner_declaration_braces=next_line +accessor_declaration_braces=next_line +case_block_braces=next_line +initializer_braces=next_line +other_braces=next_line +allow_comment_after_lbrace=false +empty_block_style=together_same_line +braces_for_ifelse=not_required +braces_for_for=not_required +braces_for_foreach=not_required +braces_for_while=not_required +braces_for_dowhile=not_required +braces_for_using=not_required +braces_for_lock=not_required +braces_for_fixed=not_required +method_or_operator_body=expression_body +local_function_body=expression_body +constructor_or_destructor_body=expression_body +accessor_owner_body=expression_body +force_attribute_style=join +function_braces=next_line +force_control_statements_braces=always_remove +space_in_singleline_accessorholder=true +type_declaration_braces=next_line +invocable_declaration_braces=next_line +anonymous_method_declaration_braces=next_line +space_between_accessors_in_singleline_property=true +indent_nested_usings_stmt=true +space_within_empty_braces=false +indent_nested_fixed_stmt=true +indent_nested_lock_stmt=true +indent_nested_for_stmt=true +indent_nested_foreach_stmt=true +indent_nested_while_stmt=true +use_continuous_indent_inside_parens=true +indent_method_decl_pars=inside +indent_invocation_pars=inside +indent_statement_pars=inside +indent_typeparam_angles=inside +indent_typearg_angles=inside +indent_pars=inside +indent_preprocessor_if=outdent +indent_preprocessor_region=usual_indent +indent_preprocessor_other=usual_indent +indent_switch_labels=true +indent_type_constraints=true +stick_comment=false +alignment_tab_fill_style=use_spaces +align_multiline_parameter=true +align_multiline_extends_list=true +align_linq_query=true +align_multiline_binary_expressions_chain=true +outdent_binary_ops=true +align_multiline_calls_chain=true +outdent_dots=true +align_multiline_array_and_object_initializer=false +indent_anonymous_method_block=false +align_first_arg_by_paren=true +align_multiline_argument=true +align_tuple_components=true +align_multiline_expression=true +align_multiline_for_stmt=true +align_multiple_declaration=true +align_multline_type_parameter_list=true +align_multline_type_parameter_constrains=true +int_align_fields=true +int_align_properties=true +int_align_methods=true +int_align_parameters=false +int_align_variables=true +int_align_assignments=true +int_align_nested_ternary=true +int_align_invocations=false +int_align_binary_expressions=true +int_align_comments=true +int_align_switch_sections=true +keep_user_linebreaks=false +keep_existing_arrangement=false +keep_existing_linebreaks=false +max_line_length=120 +wrap_before_comma=false +special_else_if_treatment=true +place_type_attribute_on_same_line=never +place_method_attribute_on_same_line=never +place_accessorholder_attribute_on_same_line=never +place_attribute_on_same_line=never +place_accessor_attribute_on_same_line=never +place_attribute_on_same_line=never +place_field_attribute_on_same_line=never +place_attribute_on_same_line=never +wrap_parameters_style=wrap_if_long +keep_existing_declaration_parens_arrangement=false +wrap_before_declaration_lpar=false +wrap_after_declaration_lpar=false +wrap_before_declaration_rpar=false +place_constructor_initializer_on_same_line=true +keep_existing_expr_member_arrangement=false +place_expr_method_on_single_line=true +place_expr_property_on_single_line=true +place_expr_accessor_on_single_line=true +wrap_before_arrow_with_expressions=false +place_type_constraints_on_same_line=true +wrap_before_first_type_parameter_constraint=true +wrap_multiple_type_parameter_constraints_style=wrap_if_long +wrap_before_type_parameter_langle=true +wrap_before_extends_colon=false +wrap_extends_list_style=wrap_if_long +keep_existing_declaration_block_arrangement=false +place_abstract_accessorholder_on_single_line=true +place_simple_accessorholder_on_single_line=false +place_accessor_with_attrs_holder_on_single_line=false +place_simple_accessor_on_single_line=true +place_simple_method_on_single_line=false +keep_existing_enum_arrangement=false +place_simple_enum_on_single_line=false +wrap_enum_declaration=wrap_if_long +new_line_before_else=true +new_line_before_while=false +wrap_for_stmt_header_style=wrap_if_long +wrap_multiple_declaration_style=wrap_if_long +keep_existing_embedded_arrangement=false +place_simple_embedded_statement_on_same_line=false +place_simple_case_statement_on_same_line=true +keep_existing_embedded_block_arrangement=false +place_simple_embedded_block_on_same_line=false +place_simple_anonymousmethod_on_single_line=false +keep_existing_initializer_arrangement=false +place_simple_initializer_on_single_line=false +wrap_object_and_collection_initializer_style=chop_always +wrap_array_initializer_style=wrap_if_long +wrap_arguments_style=wrap_if_long +keep_existing_invocation_parens_arrangement=false +wrap_after_invocation_lpar=false +wrap_before_invocation_rpar=false +wrap_after_dot_in_method_calls=true +wrap_chained_method_calls=wrap_if_long +wrap_before_binary_opsign=false +wrap_chained_binary_expressions=wrap_if_long +force_chop_compound_if_expression=true +force_chop_compound_while_expression=true +force_chop_compound_do_expression=true +wrap_before_ternary_opsigns=true +wrap_ternary_expr_style=wrap_if_long +nested_ternary_style=expanded +wrap_linq_expressions=wrap_if_long +wrap_before_linq_expression=false +place_linq_into_on_new_line=false +wrap_verbatim_interpolated_strings=wrap_if_long +extra_spaces=remove_all +space_after_keywords_in_control_flow_statements=false +space_between_method_call_name_and_opening_parenthesis=false +space_between_method_declaration_name_and_open_parenthesis=false +space_before_typeof_parentheses=false +space_before_checked_parentheses=false +space_before_sizeof_parentheses=false +space_before_nameof_parentheses=false +space_between_keyword_and_expression=true +space_between_keyword_and_type=true +space_around_assignment_op=true +space_around_logical_op=true +space_around_binary_operator=true +space_around_equality_op=true +space_around_relational_op=true +space_around_bitwise_op=true +space_around_additive_op=true +space_around_multiplicative_op=true +space_around_shift_op=true +space_around_nullcoalescing_op=true +space_around_arrow_op=false +space_after_logical_not_op=false +space_after_unary_operator=false +space_after_cast=false +space_around_dot=false +space_around_lambda_arrow=true +space_before_pointer_asterik_declaration=false +space_before_nullable_mark=false +blank_lines_around_class_definition=1 +namespace_indentation=all +space_within_template_argument=false +align_union_type_usage=true +space_in_singleline_method=true +space_in_singleline_anonymous_method=true +space_within_single_line_array_initializer_braces=true +space_around_arrow_op=false + +# These are for markup languages (HTML, XML, etc) +spaces_around_eq_in_pi_attribute=false +space_after_last_pi_attribute=true +pi_attributes_indent=align_by_first_attribute +blank_line_after_pi=true +spaces_around_eq_in_attribute=false +space_after_last_attribute=false +space_before_self_closing=true +attribute_style=on_single_line +attribute_indent=align_by_first_attribute +sort_attributes=true +sort_class_selectors=true +max_blank_lines_between_tags=0 +linebreak_before_all_elements=true +linebreak_before_multiline_elements=true +quote_style=doublequoted +delete_quotes_from_solid_values=false +normalize_tag_names=true + + +[{.babelrc,.stylelintrc,jest.config,.eslintrc,.prettierrc,*.json,*.jsb3,*.jsb2,*.bowerrc}] +indent_size=2 + +[*.js.map] +indent_size=2 + +[*.{css,scss}] +indent_size=2 +declarations_style=separate_lines_for_nonsingle +media_query_style=separate_lines +selector_style=same_line +properties_style=separate_lines_for_nonsingle +brace_style=next_line + +[{.analysis_options,*.yml,*.yaml}] +indent_size=2 + +# Xml project files +[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] +indent_size = 2 + +# Xml files +[*.{xml,stylecop,resx,ruleset}] +indent_size = 2 + +# Xml config files +[*.{props,targets,config,nuspec}] +indent_size = 2 + +# .net files +[*.{cs,vb}] +# These set the this. / Me. +dotnet_style_qualification_for_field=false:warning +dotnet_style_qualification_for_property=false:warning +dotnet_style_qualification_for_method=false:warning +dotnet_style_qualification_for_event=false:warning + +# These make it suggest Int32 instead of int, etc. +dotnet_style_predefined_type_for_locals_parameters_members=true:suggestion +dotnet_style_predefined_type_for_member_access=true:suggestion + +# This controls implicit access modifiers +dotnet_style_require_accessibility_modifiers=never:suggestion + +# Prefer non modified fields to be marked readonly +dotnet_style_readonly_field=true:warning + +# Parenthesis settings +dotnet_style_parentheses_in_arithmetic_binary_operators=always_for_clarity:warning +dotnet_style_parentheses_in_relational_binary_operators=always_for_clarity:warning +dotnet_style_parentheses_in_other_binary_operators=always_for_clarity:warning +dotnet_style_parentheses_in_other_operators=always_for_clarity:warning + +dotnet_style_object_initializer=true:suggestion +dotnet_style_collection_initializer=true:suggestion +dotnet_style_explicit_tuple_names=true:error +dotnet_style_prefer_inferred_tuple_names=true:warning +dotnet_style_prefer_inferred_anonymous_type_member_names=true:warning +dotnet_style_prefer_is_null_check_over_reference_equality_method=true:warning +dotnet_style_prefer_conditional_expression_over_return=true:warning +dotnet_style_coalesce_expression=true:warning +dotnet_style_null_propagation=true:error + +dotnet_sort_system_directives_first=true + +# Constants in C style, all-caps +dotnet_naming_rule.constant_fields_caps.symbols = constant_fields +dotnet_naming_rule.constant_fields_caps.severity = warning +dotnet_naming_rule.constant_fields_caps.style = caps_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.required_modifiers = const +dotnet_naming_style.caps_style.capitalization = all_upper + +# interfaces should be prefixed with I +dotnet_naming_rule.pascal_case_for_interface.severity = error +dotnet_naming_rule.pascal_case_for_interface.symbols = interfaces_fields +dotnet_naming_rule.pascal_case_for_interface.style = pascal_case_interface_style +dotnet_naming_symbols.interfaces_fields.applicable_kinds = interface +dotnet_naming_style.pascal_case_interface_style.required_prefix = I +dotnet_naming_style.pascal_case_interface_style.capitalization = pascal_case + +## internal and private fields should be _camelCase +dotnet_naming_rule.camel_case_for_private_internal_fields.severity = warning +dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields +dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style +dotnet_naming_symbols.private_internal_fields.applicable_kinds = field +dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal +dotnet_naming_style.camel_case_underscore_style.required_prefix = _ +dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case + +# 2018-12-07 NP: This is not yet working in VS2017 +# local variables should be camelCase +#dotnet_naming_rule.camel_case_for_locals.severity = suggestion +#dotnet_naming_rule.camel_case_for_locals.symbols = local_fields +#dotnet_naming_rule.camel_case_for_locals.style = camel_case_style +#dotnet_naming_symbols.local_fields.applicable_kinds = local +#dotnet_naming_style.camel_case_style.capitalization = camel_case + +[*.cs] +# var var var +csharp_style_var_for_built_in_types=false:warning +csharp_style_var_when_type_is_apparent=true:suggestion +csharp_style_var_elsewhere=false:warning + +csharp_style_expression_bodied_methods=when_on_single_line:suggestion +csharp_style_expression_bodied_constructors=when_on_single_line:suggestion +csharp_style_expression_bodied_operators=when_on_single_line:suggestion +csharp_style_expression_bodied_properties=when_on_single_line:suggestion +csharp_style_expression_bodied_indexers=when_on_single_line:suggestion +csharp_style_expression_bodied_accessors=when_on_single_line:suggestion + +csharp_style_pattern_matching_over_is_with_cast_check=true:warning +csharp_style_pattern_matching_over_as_with_null_check=when_on_single_line:warning + +csharp_style_inlined_variable_declaration=true:warning + +csharp_prefer_simple_default_expression=true:warning +csharp_style_deconstructed_variable_declaration=false:warning + +csharp_style_throw_expression=true:warning +csharp_style_conditional_delegate_call=true:warning + +csharp_prefer_braces=false + +csharp_new_line_before_open_brace=all +csharp_new_line_before_else=true +csharp_new_line_before_catch=true +csharp_new_line_before_finally=true +csharp_new_line_before_members_in_object_initializers=true +csharp_new_line_before_members_in_anonymous_types=true +csharp_new_line_between_query_expression_clauses=true + +csharp_indent_case_contents=true +csharp_indent_switch_labels=true +csharp_indent_labels=flush_left + +csharp_space_after_cast=false +csharp_space_after_keywords_in_control_flow_statements=false +csharp_space_between_method_declaration_parameter_list_parentheses=false +csharp_space_between_parentheses=none +csharp_space_before_colon_in_inheritance_clause=true +csharp_space_after_colon_in_inheritance_clause=true +csharp_space_around_binary_operators=before_and_after +csharp_space_between_method_declaration_empty_parameter_list_parentheses=false +csharp_space_between_method_call_name_and_opening_parenthesis=false +csharp_space_between_method_call_empty_parameter_list_parentheses=false + +csharp_preserve_single_line_statements=false +csharp_preserve_single_line_blocks=true + +csharp_blank_lines_around_region=0 +csharp_blank_lines_inside_region=0 +csharp_blank_lines_before_single_line_comment=1 +csharp_keep_blank_lines_in_declarations=1 +csharp_remove_blank_lines_near_braces_in_declarations=true +csharp_blank_lines_after_start_comment=false +csharp_blank_lines_between_using_groups=0 +csharp_blank_lines_after_using_list=1 +csharp_blank_lines_around_namespace=1 +csharp_blank_lines_inside_namespace=0 +csharp_blank_lines_around_type=1 +csharp_blank_lines_inside_type=0 +csharp_blank_lines_around_field=0 +csharp_blank_lines_around_single_line_field=0 +csharp_blank_lines_around_property=1 +csharp_blank_lines_around_single_line_property=0 +csharp_blank_lines_around_auto_property=0 +csharp_blank_lines_around_single_line_auto_property=0 +csharp_blank_lines_around_invocable=1 +csharp_blank_lines_around_single_line_invocable=1 +csharp_keep_blank_lines_in_code=1 +csharp_remove_blank_lines_near_braces_in_code=true +csharp_blank_lines_around_local_method=1 +csharp_blank_lines_around_single_line_local_method=1 +csharp_blank_lines_before_control_transfer_statements=1 +csharp_blank_lines_after_control_transfer_statements=1 +csharp_blank_lines_before_block_statements=1 +csharp_blank_lines_after_block_statements=1 +csharp_blank_lines_before_multiline_statements=1 +csharp_blank_lines_after_multiline_statements=1 + +csharp_type_declaration_braces=next_line +csharp_brace_style=next_line +csharp_indent_inside_namespace=true +csharp_invocable_declaration_braces=next_line +csharp_anonymous_method_declaration_braces=next_line +csharp_accessor_owner_declaration_braces=next_line +csharp_accessor_declaration_braces=next_line +csharp_case_block_braces=next_line +csharp_initializer_braces=next_line +csharp_other_braces=next_line +csharp_allow_comment_after_lbrace=false +csharp_empty_block_style=together_same_line + +csharp_for_built_in_types=use_explicit_type +csharp_for_simple_types=use_var_when_evident +csharp_for_other_types=use_explicit_type +csharp_prefer_separate_deconstructed_variables_declaration=true +csharp_prefer_explicit_discard_declaration=false + +csharp_instance_members_qualify_members=none +csharp_builtin_type_reference_style=use_keyword +csharp_prefer_qualified_reference=false +csharp_add_imports_to_deepest_scope=false +csharp_allow_alias=true +csharp_default_private_modifier=implicit +csharp_default_internal_modifier=explicit +csharp_arguments_literal=positional +csharp_arguments_string_literal=positional +csharp_arguments_named=positional +csharp_arguments_anonymous_function=positional +csharp_arguments_other=positional +csharp_braces_for_ifelse=not_required +csharp_braces_for_for=not_required +csharp_braces_for_foreach=not_required +csharp_braces_for_while=not_required +csharp_braces_for_dowhile=not_required +csharp_braces_for_using=not_required +csharp_braces_for_lock=not_required +csharp_braces_for_fixed=not_required +csharp_method_or_operator_body=expression_body +csharp_local_function_body=expression_body +csharp_constructor_or_destructor_body=expression_body +csharp_accessor_owner_body=expression_body +csharp_force_attribute_style=join +csharp_indent_nested_usings_stmt=true + +csharp_builtin_type_reference_for_member_access_style=use_keyword +csharp_indent_nested_fixed_stmt=true +csharp_indent_nested_lock_stmt=true +csharp_indent_nested_for_stmt=true +csharp_indent_nested_foreach_stmt=true +csharp_indent_nested_while_stmt=true +csharp_use_continuous_indent_inside_parens=true +csharp_indent_method_decl_pars=inside +csharp_indent_invocation_pars=inside +csharp_indent_statement_pars=inside +csharp_indent_typeparam_angles=inside +csharp_indent_typearg_angles=inside +csharp_indent_pars=inside +csharp_indent_preprocessor_if=outdent +csharp_indent_preprocessor_region=usual_indent +csharp_indent_preprocessor_other=usual_indent +csharp_indent_switch_labels=true +csharp_indent_type_constraints=true +csharp_stick_comment=false +csharp_alignment_tab_fill_style=use_spaces +csharp_align_multiline_parameter=true +csharp_align_multiline_extends_list=true +csharp_align_linq_query=true +csharp_align_multiline_binary_expressions_chain=true +csharp_outdent_binary_ops=true +csharp_align_multiline_calls_chain=true +csharp_outdent_dots=true +csharp_align_multiline_array_and_object_initializer=false +csharp_indent_anonymous_method_block=false +csharp_align_first_arg_by_paren=true +csharp_align_multiline_argument=true +csharp_align_tuple_components=true +csharp_align_multiline_expression=true +csharp_align_multiline_for_stmt=true +csharp_align_multiple_declaration=true +csharp_align_multline_type_parameter_list=true +csharp_align_multline_type_parameter_constrains=true +csharp_int_align_fields=true +csharp_int_align_properties=true +csharp_int_align_methods=true +csharp_int_align_parameters=false +csharp_int_align_variables=true +csharp_int_align_assignments=true +csharp_int_align_nested_ternary=true +csharp_int_align_invocations=false +csharp_int_align_binary_expressions=true +csharp_int_align_comments=true +csharp_int_align_switch_sections=true +csharp_int_align=true +csharp_keep_user_linebreaks=false +csharp_keep_existing_arrangement=false +csharp_keep_existing_linebreaks=false +csharp_max_line_length=120 +csharp_wrap_before_comma=false +csharp_special_else_if_treatment=true +csharp_insert_final_newline=false +csharp_place_type_attribute_on_same_line=never +csharp_place_method_attribute_on_same_line=never +csharp_place_accessorholder_attribute_on_same_line=never +csharp_place_attribute_on_same_line=never +csharp_place_accessor_attribute_on_same_line=never +csharp_place_attribute_on_same_line=never +csharp_place_field_attribute_on_same_line=never +csharp_place_attribute_on_same_line=never +csharp_wrap_parameters_style=wrap_if_long +csharp_keep_existing_declaration_parens_arrangement=false +csharp_wrap_before_declaration_lpar=false +csharp_wrap_after_declaration_lpar=false +csharp_wrap_before_declaration_rpar=false +csharp_place_constructor_initializer_on_same_line=true +csharp_keep_existing_expr_member_arrangement=false +csharp_place_expr_method_on_single_line=true +csharp_place_expr_property_on_single_line=true +csharp_place_expr_accessor_on_single_line=true +csharp_wrap_before_arrow_with_expressions=false +csharp_place_type_constraints_on_same_line=true +csharp_wrap_before_first_type_parameter_constraint=true +csharp_wrap_multiple_type_parameter_constraints_style=wrap_if_long +csharp_wrap_before_type_parameter_langle=true +csharp_wrap_before_extends_colon=false +csharp_wrap_extends_list_style=wrap_if_long +csharp_keep_existing_declaration_block_arrangement=false +csharp_place_abstract_accessorholder_on_single_line=true +csharp_place_simple_accessorholder_on_single_line=false +csharp_place_accessor_with_attrs_holder_on_single_line=false +csharp_place_simple_accessor_on_single_line=true +csharp_place_simple_method_on_single_line=false +csharp_keep_existing_enum_arrangement=false +csharp_place_simple_enum_on_single_line=false +csharp_wrap_enum_declaration=wrap_if_long +csharp_new_line_before_else=true +csharp_new_line_before_while=false +csharp_wrap_for_stmt_header_style=wrap_if_long +csharp_wrap_multiple_declaration_style=wrap_if_long +csharp_keep_existing_embedded_arrangement=false +csharp_place_simple_embedded_statement_on_same_line=false +csharp_place_simple_case_statement_on_same_line=true +csharp_keep_existing_embedded_block_arrangement=false +csharp_place_simple_embedded_block_on_same_line=false +csharp_place_simple_anonymousmethod_on_single_line=false +csharp_keep_existing_initializer_arrangement=false +csharp_place_simple_initializer_on_single_line=false +csharp_wrap_object_and_collection_initializer_style=chop_always +csharp_wrap_array_initializer_style=wrap_if_long +csharp_wrap_arguments_style=wrap_if_long +csharp_keep_existing_invocation_parens_arrangement=false +csharp_wrap_after_invocation_lpar=false +csharp_wrap_before_invocation_rpar=false +csharp_wrap_after_dot_in_method_calls=true +csharp_wrap_chained_method_calls=wrap_if_long +csharp_wrap_before_binary_opsign=false +csharp_wrap_chained_binary_expressions=wrap_if_long +csharp_force_chop_compound_if_expression=true +csharp_force_chop_compound_while_expression=true +csharp_force_chop_compound_do_expression=true +csharp_wrap_before_ternary_opsigns=true +csharp_wrap_ternary_expr_style=wrap_if_long +csharp_nested_ternary_style=expanded +csharp_wrap_linq_expressions=wrap_if_long +csharp_wrap_before_linq_expression=false +csharp_place_linq_into_on_new_line=false +csharp_wrap_verbatim_interpolated_strings=wrap_if_long +csharp_extra_spaces=remove_all +csharp_space_after_keywords_in_control_flow_statements=false +csharp_space_between_method_call_name_and_opening_parenthesis=false +csharp_space_between_method_declaration_name_and_open_parenthesis=false +csharp_space_before_typeof_parentheses=false +csharp_space_before_checked_parentheses=false +csharp_space_before_sizeof_parentheses=false +csharp_space_before_nameof_parentheses=false +csharp_space_between_keyword_and_expression=true +csharp_space_between_keyword_and_type=true +csharp_space_around_assignment_op=true +csharp_space_around_logical_op=true +csharp_space_around_binary_operator=true +csharp_space_around_equality_op=true +csharp_space_around_relational_op=true +csharp_space_around_bitwise_op=true +csharp_space_around_additive_op=true +csharp_space_around_multiplicative_op=true +csharp_space_around_shift_op=true +csharp_space_around_nullcoalescing_op=true +csharp_space_around_arrow_op=false +csharp_space_after_logical_not_op=false +csharp_space_after_unary_operator=false +csharp_space_after_cast=false +csharp_space_around_dot=false +csharp_space_around_lambda_arrow=true +csharp_space_before_pointer_asterik_declaration=false +csharp_space_before_nullable_mark=false + +[*.cshtml] +linebreaks_around_razor_statements=true +blank_lines_around_razor_functions=true +blank_lines_around_razor_helpers=true +blank_lines_around_razor_sections=true + +# C++ +[*.{cc,cpp,cxx,h,hpp,hxx}] +cpp_indent_access_specifiers_from_class=true +cpp_indent_wrapped_function_names=false +cpp_align_multiline_type_argument=true + +# C, C++ and ObjectiveC +[*.{c,h,cc,cpp,cxx,m,hpp,hxx}] +indent_preprocessor_directives=normal +indent_type_constraints=true + +# Javascript and Typescript +[*.{js,js.map,ts}] +quote_style=doublequoted +termination_style=ensure_semicolon \ No newline at end of file diff --git a/Aaru.Dto/.gitignore b/Aaru.Dto/.gitignore new file mode 100644 index 000000000..05c540d38 --- /dev/null +++ b/Aaru.Dto/.gitignore @@ -0,0 +1,595 @@ +### VisualStudio template +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ +### Linux template + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* +### Xcode template +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +### VisualStudioCode template +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +### C++ template +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o + +# Precompiled Headers +*.gch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +### MonoDevelop template +#User Specific +*.usertasks + +#Mono Project Files +*.resources +test-results/ +### GPG template +secring.* + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests +### CMake template +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +### C template +# Object files +*.ko +*.elf + +# Linker output +*.map +*.exp + +*.so.* + +# Executables +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf +### Windows template +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# NuGet Packages Directory +packages/ +## TODO: If the tool you use requires repositories.config uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +# This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented) +!packages/build/ + + +# Others +sql/ +*.Cache + +# Visual Studio 2017 +.vs + +workspace.xml +cmake-build-debug +### macOS template +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +pkg/**/pkg +pkg/**/src +pkg/**/*.asc +pkg/**/*.sig +pkg/**/*.tar.xz +pkg/**/*.zip +pkg/**/aaru + +.sonarqube \ No newline at end of file diff --git a/Aaru.Dto/Aaru.Dto.csproj b/Aaru.Dto/Aaru.Dto.csproj new file mode 100644 index 000000000..d34985085 --- /dev/null +++ b/Aaru.Dto/Aaru.Dto.csproj @@ -0,0 +1,59 @@ + + + + Debug + AnyCPU + 2.0 + {F4399FF5-9BD0-475A-9EA7-3DAE45291FE2} + Library + Aaru.Dto + Aaru.Dto + $(Version) + false + true + 5.3.2 + Claunia.com + Copyright © 2011-2023 Natalia Portillo + Aaru Data Preservation Suite + Aaru.Dto + $(Version) + netcoreapp3.1 + 8 + Data transfer objects used to interchange data between Aaru and Aaru.Server. + https://github.com/aaru-dps/ + LGPL-2.1-only + https://github.com/aaru-dps/Aaru + true + en-US + true + true + snupkg + Natalia Portillo <claunia@claunia.com> + + + $(Version)+{chash:8} + true + true + + + + + + + LICENSE.LGPL + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Aaru.Dto/CdOffsetDto.cs b/Aaru.Dto/CdOffsetDto.cs new file mode 100644 index 000000000..c90cf5e5b --- /dev/null +++ b/Aaru.Dto/CdOffsetDto.cs @@ -0,0 +1,68 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CdOffsetDto.cs +// Author(s) : Natalia Portillo +// +// Component : DTOs. +// +// --[ Description ] ---------------------------------------------------------- +// +// DTO for syncing Compact Disc read offsets. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using Aaru.CommonTypes.Metadata; + +namespace Aaru.Dto +{ + /// + /// + /// DTO from a CD drive read offset + /// + public class CdOffsetDto : CdOffset + { + /// + /// Build an empty DTO + /// + public CdOffsetDto() {} + + /// + /// Build a DTO using the specified offset and database ID + /// + /// CD reading offset + /// Database ID + public CdOffsetDto(CdOffset offset, int id) + { + Manufacturer = offset.Manufacturer; + Model = offset.Model; + Offset = offset.Offset; + Submissions = offset.Submissions; + Agreement = offset.Agreement; + Id = id; + } + + /// + /// Database ID + /// + public int Id { get; set; } + } +} \ No newline at end of file diff --git a/Aaru.Dto/DeviceDto.cs b/Aaru.Dto/DeviceDto.cs new file mode 100644 index 000000000..60c1871ac --- /dev/null +++ b/Aaru.Dto/DeviceDto.cs @@ -0,0 +1,278 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : DeviceDto.cs +// Author(s) : Natalia Portillo +// +// Component : Aaru Server. +// +// --[ Description ] ---------------------------------------------------------- +// +// DTO for syncing processed device reports in database. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Collections.Generic; +using Aaru.CommonTypes.Metadata; + +// ReSharper disable VirtualMemberCallInConstructor + +namespace Aaru.Dto +{ + /// + /// DTO for known device + /// + public class DeviceDto : DeviceReportV2 + { + /// + /// Build an empty DTO + /// + public DeviceDto() {} + + /// + /// Build a DTO from a device report + /// + /// Device report + public DeviceDto(DeviceReportV2 report) + { + ATA = report.ATA; + ATAPI = report.ATAPI; + CompactFlash = report.CompactFlash; + FireWire = report.FireWire; + MultiMediaCard = report.MultiMediaCard; + PCMCIA = report.PCMCIA; + SCSI = report.SCSI; + SecureDigital = report.SecureDigital; + USB = report.USB; + Manufacturer = report.Manufacturer; + Model = report.Model; + Revision = report.Revision; + Type = report.Type; + GdRomSwapDiscCapabilities = report.GdRomSwapDiscCapabilities; + } + + /// + /// Build a DTO from a device report with the specified parameters + /// + /// Device report + /// Database ID + /// Optimal number of blocks for read + /// Can read GD-ROM using swap trick? + public DeviceDto(DeviceReportV2 report, int id, int optimalMultipleSectorsRead, bool? canReadGdRomUsingSwapDisc) + { + ATA = report.ATA; + ATAPI = report.ATAPI; + CompactFlash = report.CompactFlash; + FireWire = report.FireWire; + MultiMediaCard = report.MultiMediaCard; + PCMCIA = report.PCMCIA; + SCSI = report.SCSI; + SecureDigital = report.SecureDigital; + USB = report.USB; + Manufacturer = report.Manufacturer; + Model = report.Model; + Revision = report.Revision; + Type = report.Type; + GdRomSwapDiscCapabilities = report.GdRomSwapDiscCapabilities; + + if(ATA != null) + { + ATA.Identify = null; + ATA.ReadCapabilities = ClearBinaries(ATA.ReadCapabilities); + + if(ATA.RemovableMedias != null) + { + TestedMedia[] medias = ATA.RemovableMedias.ToArray(); + ATA.RemovableMedias = new List(); + + foreach(TestedMedia media in medias) + ATA.RemovableMedias.Add(ClearBinaries(media)); + } + } + + if(ATAPI != null) + { + ATAPI.Identify = null; + ATAPI.ReadCapabilities = ClearBinaries(ATAPI.ReadCapabilities); + + if(ATAPI.RemovableMedias != null) + { + TestedMedia[] medias = ATAPI.RemovableMedias.ToArray(); + ATAPI.RemovableMedias = new List(); + + foreach(TestedMedia media in medias) + ATAPI.RemovableMedias.Add(ClearBinaries(media)); + } + } + + if(PCMCIA != null) + { + PCMCIA.AdditionalInformation = null; + PCMCIA.CIS = null; + } + + MultiMediaCard = null; + SecureDigital = null; + + if(SCSI != null) + { + SCSI.EVPDPages = null; + SCSI.InquiryData = null; + SCSI.ModeSense6Data = null; + SCSI.ModeSense10Data = null; + SCSI.ModeSense6CurrentData = null; + SCSI.ModeSense10CurrentData = null; + SCSI.ModeSense6ChangeableData = null; + SCSI.ModeSense10ChangeableData = null; + SCSI.ReadCapabilities = ClearBinaries(SCSI.ReadCapabilities); + + if(SCSI.ModeSense != null) + { + SCSI.ModeSense.BlockDescriptors = null; + SCSI.ModeSense.ModePages = null; + } + + if(SCSI.RemovableMedias != null) + { + TestedMedia[] medias = SCSI.RemovableMedias.ToArray(); + SCSI.RemovableMedias = new List(); + + foreach(TestedMedia media in medias) + SCSI.RemovableMedias.Add(ClearBinaries(media)); + } + + if(SCSI.MultiMediaDevice != null) + { + SCSI.MultiMediaDevice.ModeSense2AData = null; + + if(SCSI.MultiMediaDevice.Features != null) + SCSI.MultiMediaDevice.Features.BinaryData = null; + + if(SCSI.MultiMediaDevice.TestedMedia != null) + { + TestedMedia[] medias = SCSI.MultiMediaDevice.TestedMedia.ToArray(); + SCSI.MultiMediaDevice.TestedMedia = new List(); + + foreach(TestedMedia media in medias) + SCSI.MultiMediaDevice.TestedMedia.Add(ClearBinaries(media)); + } + } + + SCSI.SequentialDevice = null; + } + + if(USB != null) + USB.Descriptors = null; + + Id = id; + OptimalMultipleSectorsRead = optimalMultipleSectorsRead; + CanReadGdRomUsingSwapDisc = canReadGdRomUsingSwapDisc; + } + + /// + /// Optimal maximum number of transfer blocks to read + /// + public int OptimalMultipleSectorsRead { get; set; } + + /// + /// Can read GD-ROM using disc swap trick? + /// + public bool? CanReadGdRomUsingSwapDisc { get; set; } + + /// + /// Database ID + /// + public new int Id { get; set; } + + static TestedMedia ClearBinaries(TestedMedia media) + { + if(media is null) + return null; + + media.AdipData = null; + media.AtipData = null; + media.BluBcaData = null; + media.BluDdsData = null; + media.BluDiData = null; + media.BluPacData = null; + media.BluSaiData = null; + media.C2PointersData = null; + media.CmiData = null; + media.CorrectedSubchannelData = null; + media.CorrectedSubchannelWithC2Data = null; + media.DcbData = null; + media.DmiData = null; + media.DvdAacsData = null; + media.DvdBcaData = null; + media.DvdDdsData = null; + media.DvdLayerData = null; + media.DvdSaiData = null; + media.EmbossedPfiData = null; + media.FullTocData = null; + media.HdCmiData = null; + media.HLDTSTReadRawDVDData = null; + media.IdentifyData = null; + media.LeadInData = null; + media.LeadOutData = null; + media.ModeSense6Data = null; + media.ModeSense10Data = null; + media.NecReadCddaData = null; + media.PfiData = null; + media.PioneerReadCddaData = null; + media.PioneerReadCddaMsfData = null; + media.PlextorReadCddaData = null; + media.PlextorReadRawDVDData = null; + media.PmaData = null; + media.PQSubchannelData = null; + media.PQSubchannelWithC2Data = null; + media.PriData = null; + media.Read6Data = null; + media.Read10Data = null; + media.Read12Data = null; + media.Read16Data = null; + media.ReadCdData = null; + media.ReadCdFullData = null; + media.ReadCdMsfData = null; + media.ReadCdMsfFullData = null; + media.ReadDmaData = null; + media.ReadDmaLba48Data = null; + media.ReadDmaLbaData = null; + media.ReadDmaRetryData = null; + media.ReadLba48Data = null; + media.ReadLbaData = null; + media.ReadLong10Data = null; + media.ReadLong16Data = null; + media.ReadLongData = null; + media.ReadLongLbaData = null; + media.ReadLongRetryData = null; + media.ReadLongRetryLbaData = null; + media.ReadRetryLbaData = null; + media.ReadSectorsData = null; + media.ReadSectorsRetryData = null; + media.RWSubchannelData = null; + media.RWSubchannelWithC2Data = null; + media.TocData = null; + media.Track1PregapData = null; + + return media; + } + } +} \ No newline at end of file diff --git a/Aaru.Dto/SyncDto.cs b/Aaru.Dto/SyncDto.cs new file mode 100644 index 000000000..a60fdc84d --- /dev/null +++ b/Aaru.Dto/SyncDto.cs @@ -0,0 +1,59 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : SyncDto.cs +// Author(s) : Natalia Portillo +// +// Component : Aaru Server. +// +// --[ Description ] ---------------------------------------------------------- +// +// DTO for syncing server and client databases. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Collections.Generic; + +namespace Aaru.Dto +{ + /// + /// DTO for database synchronization. + /// + public class SyncDto + { + /// + /// List of USB vendors + /// + public List UsbVendors { get; set; } + /// + /// List of USB products + /// + public List UsbProducts { get; set; } + /// + /// List of CD read offsets + /// + public List Offsets { get; set; } + /// + /// List of known devices + /// + public List Devices { get; set; } + } +} \ No newline at end of file diff --git a/Aaru.Dto/UsbProductDto.cs b/Aaru.Dto/UsbProductDto.cs new file mode 100644 index 000000000..aa8c61750 --- /dev/null +++ b/Aaru.Dto/UsbProductDto.cs @@ -0,0 +1,57 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : UsbProductDto.cs +// Author(s) : Natalia Portillo +// +// Component : Aaru Server. +// +// --[ Description ] ---------------------------------------------------------- +// +// DTO for syncing USB product identifiers in database. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.Dto +{ + /// + /// DTO for USB product field + /// + public class UsbProductDto + { + /// + /// Database ID + /// + public int Id { get; set; } + /// + /// Product ID + /// + public ushort ProductId { get; set; } + /// + /// Product name + /// + public string Product { get; set; } + /// + /// Vendor ID + /// + public ushort VendorId { get; set; } + } +} \ No newline at end of file diff --git a/Aaru.Dto/UsbVendorDto.cs b/Aaru.Dto/UsbVendorDto.cs new file mode 100644 index 000000000..9a637fd6b --- /dev/null +++ b/Aaru.Dto/UsbVendorDto.cs @@ -0,0 +1,49 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : UsbVendorDto.cs +// Author(s) : Natalia Portillo +// +// Component : Aaru Server. +// +// --[ Description ] ---------------------------------------------------------- +// +// DTO for syncing USB vendor identifiers in database. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.Dto +{ + /// + /// DTO for USB vendor field + /// + public class UsbVendorDto + { + /// + /// Vendor ID + /// + public ushort VendorId { get; set; } + /// + /// Vendor + /// + public string Vendor { get; set; } + } +} \ No newline at end of file diff --git a/Aaru.Helpers b/Aaru.Helpers deleted file mode 160000 index 633f5713f..000000000 --- a/Aaru.Helpers +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 633f5713f760710421578c583c8621dc7ce9915c diff --git a/Aaru.Helpers/.editorconfig b/Aaru.Helpers/.editorconfig new file mode 100644 index 000000000..9181fe501 --- /dev/null +++ b/Aaru.Helpers/.editorconfig @@ -0,0 +1,632 @@ +root = true + +[*] +charset = utf-8 +next_line = crlf +insert_final_newline = false +indent_style = space +indent_size = 4 + +# Generic non-language specific ones for Resharper and friends +brace_style = next_line +int_align = true +keep_existing_arrangement = false +place_simple_blocks_on_single_line = true +place_simple_declaration_blocks_on_single_line = true +place_attribute_on_same_line = false +space_after_unary_operator = false +space_after_comma = true +space_around_ternary_operator = true +space_around_binary_operator = true +space_around_member_access_operator = false +space_before_open_square_brackets = false +space_after_keywords_in_control_flow_statements = true +space_before_comma = false +space_between_method_call_name_and_opening_parenthesis = false +space_between_method_declaration_name_and_open_parenthesis = false +space_between_square_brackets = false +space_between_parentheses_of_control_flow_statements = false +accessor_owner_declaration_braces = next_line +accessor_declaration_braces = next_line +case_block_braces = next_line +initializer_braces = next_line +other_braces = next_line +allow_comment_after_lbrace = false +empty_block_style = together_same_line +braces_for_ifelse = not_required +braces_for_for = not_required +braces_for_foreach = not_required +braces_for_while = not_required +braces_for_dowhile = not_required +braces_for_using = not_required +braces_for_lock = not_required +braces_for_fixed = not_required +method_or_operator_body = expression_body +local_function_body = expression_body +constructor_or_destructor_body = expression_body +accessor_owner_body = expression_body +force_attribute_style = join +function_braces = next_line +force_control_statements_braces = always_remove +space_in_singleline_accessorholder = true +type_declaration_braces = next_line +invocable_declaration_braces = next_line +anonymous_method_declaration_braces = next_line +space_between_accessors_in_singleline_property = true +indent_nested_usings_stmt = true +space_within_empty_braces = false +indent_nested_fixed_stmt = true +indent_nested_lock_stmt = true +indent_nested_for_stmt = true +indent_nested_foreach_stmt = true +indent_nested_while_stmt = true +use_continuous_indent_inside_parens = true +indent_method_decl_pars = inside +indent_invocation_pars = inside +indent_statement_pars = inside +indent_typeparam_angles = inside +indent_typearg_angles = inside +indent_pars = inside +indent_preprocessor_if = outdent +indent_preprocessor_region = usual_indent +indent_preprocessor_other = usual_indent +indent_switch_labels = true +indent_type_constraints = true +stick_comment = false +alignment_tab_fill_style = use_spaces +align_multiline_parameter = true +align_multiline_extends_list = true +align_linq_query = true +align_multiline_binary_expressions_chain = true +outdent_binary_ops = true +align_multiline_calls_chain = true +outdent_dots = true +align_multiline_array_and_object_initializer = false +indent_anonymous_method_block = false +align_first_arg_by_paren = true +align_multiline_argument = true +align_tuple_components = true +align_multiline_expression = true +align_multiline_for_stmt = true +align_multiple_declaration = true +align_multline_type_parameter_list = true +align_multline_type_parameter_constrains = true +int_align_fields = true +int_align_properties = true +int_align_methods = true +int_align_parameters = false +int_align_variables = true +int_align_assignments = true +int_align_nested_ternary = true +int_align_invocations = false +int_align_binary_expressions = true +int_align_comments = true +int_align_switch_sections = true +keep_user_linebreaks = false +keep_existing_arrangement = false +keep_existing_linebreaks = false +max_line_length = 120 +wrap_before_comma = false +special_else_if_treatment = true +place_type_attribute_on_same_line = never +place_method_attribute_on_same_line = never +place_accessorholder_attribute_on_same_line = never +place_attribute_on_same_line = never +place_accessor_attribute_on_same_line = never +place_attribute_on_same_line = never +place_field_attribute_on_same_line = never +place_attribute_on_same_line = never +wrap_parameters_style = wrap_if_long +keep_existing_declaration_parens_arrangement = false +wrap_before_declaration_lpar = false +wrap_after_declaration_lpar = false +wrap_before_declaration_rpar = false +place_constructor_initializer_on_same_line = true +keep_existing_expr_member_arrangement = false +place_expr_method_on_single_line = true +place_expr_property_on_single_line = true +place_expr_accessor_on_single_line = true +wrap_before_arrow_with_expressions = false +place_type_constraints_on_same_line = true +wrap_before_first_type_parameter_constraint = true +wrap_multiple_type_parameter_constraints_style = wrap_if_long +wrap_before_type_parameter_langle = true +wrap_before_extends_colon = false +wrap_extends_list_style = wrap_if_long +keep_existing_declaration_block_arrangement = false +place_abstract_accessorholder_on_single_line = true +place_simple_accessorholder_on_single_line = false +place_accessor_with_attrs_holder_on_single_line = false +place_simple_accessor_on_single_line = true +place_simple_method_on_single_line = false +keep_existing_enum_arrangement = false +place_simple_enum_on_single_line = false +wrap_enum_declaration = wrap_if_long +new_line_before_else = true +new_line_before_while = false +wrap_for_stmt_header_style = wrap_if_long +wrap_multiple_declaration_style = wrap_if_long +keep_existing_embedded_arrangement = false +place_simple_embedded_statement_on_same_line = false +place_simple_case_statement_on_same_line = true +keep_existing_embedded_block_arrangement = false +place_simple_embedded_block_on_same_line = false +place_simple_anonymousmethod_on_single_line = false +keep_existing_initializer_arrangement = false +place_simple_initializer_on_single_line = false +wrap_object_and_collection_initializer_style = chop_always +wrap_array_initializer_style = wrap_if_long +wrap_arguments_style = wrap_if_long +keep_existing_invocation_parens_arrangement = false +wrap_after_invocation_lpar = false +wrap_before_invocation_rpar = false +wrap_after_dot_in_method_calls = true +wrap_chained_method_calls = wrap_if_long +wrap_before_binary_opsign = false +wrap_chained_binary_expressions = wrap_if_long +force_chop_compound_if_expression = true +force_chop_compound_while_expression = true +force_chop_compound_do_expression = true +wrap_before_ternary_opsigns = true +wrap_ternary_expr_style = wrap_if_long +nested_ternary_style = expanded +wrap_linq_expressions = wrap_if_long +wrap_before_linq_expression = false +place_linq_into_on_new_line = false +wrap_verbatim_interpolated_strings = wrap_if_long +extra_spaces = remove_all +space_after_keywords_in_control_flow_statements = false +space_between_method_call_name_and_opening_parenthesis = false +space_between_method_declaration_name_and_open_parenthesis = false +space_before_typeof_parentheses = false +space_before_checked_parentheses = false +space_before_sizeof_parentheses = false +space_before_nameof_parentheses = false +space_between_keyword_and_expression = true +space_between_keyword_and_type = true +space_around_assignment_op = true +space_around_logical_op = true +space_around_binary_operator = true +space_around_equality_op = true +space_around_relational_op = true +space_around_bitwise_op = true +space_around_additive_op = true +space_around_multiplicative_op = true +space_around_shift_op = true +space_around_nullcoalescing_op = true +space_around_arrow_op = false +space_after_logical_not_op = false +space_after_unary_operator = false +space_after_cast = false +space_around_dot = false +space_around_lambda_arrow = true +space_before_pointer_asterik_declaration = false +space_before_nullable_mark = false +blank_lines_around_class_definition = 1 +namespace_indentation = all +space_within_template_argument = false +align_union_type_usage = true +space_in_singleline_method = true +space_in_singleline_anonymous_method = true +space_within_single_line_array_initializer_braces = true +space_around_arrow_op = false + +# These are for markup languages (HTML, XML, etc) +spaces_around_eq_in_pi_attribute = false +space_after_last_pi_attribute = true +pi_attributes_indent = align_by_first_attribute +blank_line_after_pi = true +spaces_around_eq_in_attribute = false +space_after_last_attribute = false +space_before_self_closing = true +attribute_style = on_single_line +attribute_indent = align_by_first_attribute +sort_attributes = true +sort_class_selectors = true +max_blank_lines_between_tags = 0 +linebreak_before_all_elements = true +linebreak_before_multiline_elements = true +quote_style = doublequoted +delete_quotes_from_solid_values = false +normalize_tag_names = true + + +[{.babelrc,.stylelintrc,jest.config,.eslintrc,.prettierrc,*.json,*.jsb3,*.jsb2,*.bowerrc}] +indent_size = 2 + +[*.js.map] +indent_size = 2 + +[*.{css,scss}] +indent_size = 2 +declarations_style = separate_lines_for_nonsingle +media_query_style = separate_lines +selector_style = same_line +properties_style = separate_lines_for_nonsingle +brace_style = next_line + +[{.analysis_options,*.yml,*.yaml}] +indent_size = 2 + +# Xml project files +[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] +indent_size = 2 + +# Xml files +[*.{xml,stylecop,resx,ruleset}] +indent_size = 2 + +# Xml config files +[*.{props,targets,config,nuspec}] +indent_size = 2 + +# .net files +[*.{cs,vb}] +# These set the this. / Me. +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning + +# These make it suggest Int32 instead of int, etc. +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# This controls implicit access modifiers +dotnet_style_require_accessibility_modifiers = never:suggestion + +# Prefer non modified fields to be marked readonly +dotnet_style_readonly_field = true:warning + +# Parenthesis settings +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_operators = always_for_clarity:warning + +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:error +dotnet_style_prefer_inferred_tuple_names = true:warning +dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning +dotnet_style_prefer_conditional_expression_over_return = true:warning +dotnet_style_coalesce_expression = true:warning +dotnet_style_null_propagation = true:error + +dotnet_sort_system_directives_first = true + +# Constants in C style, all-caps +dotnet_naming_rule.constant_fields_caps.symbols = constant_fields +dotnet_naming_rule.constant_fields_caps.severity = warning +dotnet_naming_rule.constant_fields_caps.style = caps_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.required_modifiers = const +dotnet_naming_style.caps_style.capitalization = all_upper + +# interfaces should be prefixed with I +dotnet_naming_rule.pascal_case_for_interface.severity = error +dotnet_naming_rule.pascal_case_for_interface.symbols = interfaces_fields +dotnet_naming_rule.pascal_case_for_interface.style = pascal_case_interface_style +dotnet_naming_symbols.interfaces_fields.applicable_kinds = interface +dotnet_naming_style.pascal_case_interface_style.required_prefix = I +dotnet_naming_style.pascal_case_interface_style.capitalization = pascal_case + +## internal and private fields should be _camelCase +dotnet_naming_rule.camel_case_for_private_internal_fields.severity = warning +dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields +dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style +dotnet_naming_symbols.private_internal_fields.applicable_kinds = field +dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal +dotnet_naming_style.camel_case_underscore_style.required_prefix = _ +dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case + +# 2018-12-07 NP: This is not yet working in VS2017 +# local variables should be camelCase +#dotnet_naming_rule.camel_case_for_locals.severity = suggestion +#dotnet_naming_rule.camel_case_for_locals.symbols = local_fields +#dotnet_naming_rule.camel_case_for_locals.style = camel_case_style +#dotnet_naming_symbols.local_fields.applicable_kinds = local +#dotnet_naming_style.camel_case_style.capitalization = camel_case + +[*.cs] +# var var var +csharp_style_var_for_built_in_types = false:warning +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = false:warning + +csharp_style_expression_bodied_methods = when_on_single_line:suggestion +csharp_style_expression_bodied_constructors = when_on_single_line:suggestion +csharp_style_expression_bodied_operators = when_on_single_line:suggestion +csharp_style_expression_bodied_properties = when_on_single_line:suggestion +csharp_style_expression_bodied_indexers = when_on_single_line:suggestion +csharp_style_expression_bodied_accessors = when_on_single_line:suggestion + +csharp_style_pattern_matching_over_is_with_cast_check = true:warning +csharp_style_pattern_matching_over_as_with_null_check = when_on_single_line:warning + +csharp_style_inlined_variable_declaration = true:warning + +csharp_prefer_simple_default_expression = true:warning +csharp_style_deconstructed_variable_declaration = false:warning + +csharp_style_throw_expression = true:warning +csharp_style_conditional_delegate_call = true:warning + +csharp_prefer_braces = false + +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true + +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = flush_left + +csharp_space_after_cast = false +csharp_space_after_keywords_in_control_flow_statements = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = none +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false + +csharp_preserve_single_line_statements = false +csharp_preserve_single_line_blocks = true + +csharp_blank_lines_around_region = 0 +csharp_blank_lines_inside_region = 0 +csharp_blank_lines_before_single_line_comment = 1 +csharp_keep_blank_lines_in_declarations = 1 +csharp_remove_blank_lines_near_braces_in_declarations = true +csharp_blank_lines_after_start_comment = false +csharp_blank_lines_between_using_groups = 0 +csharp_blank_lines_after_using_list = 1 +csharp_blank_lines_around_namespace = 1 +csharp_blank_lines_inside_namespace = 0 +csharp_blank_lines_around_type = 1 +csharp_blank_lines_inside_type = 0 +csharp_blank_lines_around_field = 0 +csharp_blank_lines_around_single_line_field = 0 +csharp_blank_lines_around_property = 1 +csharp_blank_lines_around_single_line_property = 0 +csharp_blank_lines_around_auto_property = 0 +csharp_blank_lines_around_single_line_auto_property = 0 +csharp_blank_lines_around_invocable = 1 +csharp_blank_lines_around_single_line_invocable = 1 +csharp_keep_blank_lines_in_code = 1 +csharp_remove_blank_lines_near_braces_in_code = true +csharp_blank_lines_around_local_method = 1 +csharp_blank_lines_around_single_line_local_method = 1 +csharp_blank_lines_before_control_transfer_statements = 1 +csharp_blank_lines_after_control_transfer_statements = 1 +csharp_blank_lines_before_block_statements = 1 +csharp_blank_lines_after_block_statements = 1 +csharp_blank_lines_before_multiline_statements = 1 +csharp_blank_lines_after_multiline_statements = 1 + +csharp_type_declaration_braces = next_line +csharp_brace_style = next_line +csharp_indent_inside_namespace = true +csharp_invocable_declaration_braces = next_line +csharp_anonymous_method_declaration_braces = next_line +csharp_accessor_owner_declaration_braces = next_line +csharp_accessor_declaration_braces = next_line +csharp_case_block_braces = next_line +csharp_initializer_braces = next_line +csharp_other_braces = next_line +csharp_allow_comment_after_lbrace = false +csharp_empty_block_style = together_same_line + +csharp_for_built_in_types = use_explicit_type +csharp_for_simple_types = use_var_when_evident +csharp_for_other_types = use_explicit_type +csharp_prefer_separate_deconstructed_variables_declaration = true +csharp_prefer_explicit_discard_declaration = false + +csharp_instance_members_qualify_members = none +csharp_builtin_type_reference_style = use_keyword +csharp_prefer_qualified_reference = false +csharp_add_imports_to_deepest_scope = false +csharp_allow_alias = true +csharp_default_private_modifier = implicit +csharp_default_internal_modifier = explicit +csharp_arguments_literal = positional +csharp_arguments_string_literal = positional +csharp_arguments_named = positional +csharp_arguments_anonymous_function = positional +csharp_arguments_other = positional +csharp_braces_for_ifelse = not_required +csharp_braces_for_for = not_required +csharp_braces_for_foreach = not_required +csharp_braces_for_while = not_required +csharp_braces_for_dowhile = not_required +csharp_braces_for_using = not_required +csharp_braces_for_lock = not_required +csharp_braces_for_fixed = not_required +csharp_method_or_operator_body = expression_body +csharp_local_function_body = expression_body +csharp_constructor_or_destructor_body = expression_body +csharp_accessor_owner_body = expression_body +csharp_force_attribute_style = join +csharp_indent_nested_usings_stmt = true + +csharp_builtin_type_reference_for_member_access_style = use_keyword +csharp_indent_nested_fixed_stmt = true +csharp_indent_nested_lock_stmt = true +csharp_indent_nested_for_stmt = true +csharp_indent_nested_foreach_stmt = true +csharp_indent_nested_while_stmt = true +csharp_use_continuous_indent_inside_parens = true +csharp_indent_method_decl_pars = inside +csharp_indent_invocation_pars = inside +csharp_indent_statement_pars = inside +csharp_indent_typeparam_angles = inside +csharp_indent_typearg_angles = inside +csharp_indent_pars = inside +csharp_indent_preprocessor_if = outdent +csharp_indent_preprocessor_region = usual_indent +csharp_indent_preprocessor_other = usual_indent +csharp_indent_switch_labels = true +csharp_indent_type_constraints = true +csharp_stick_comment = false +csharp_alignment_tab_fill_style = use_spaces +csharp_align_multiline_parameter = true +csharp_align_multiline_extends_list = true +csharp_align_linq_query = true +csharp_align_multiline_binary_expressions_chain = true +csharp_outdent_binary_ops = true +csharp_align_multiline_calls_chain = true +csharp_outdent_dots = true +csharp_align_multiline_array_and_object_initializer = false +csharp_indent_anonymous_method_block = false +csharp_align_first_arg_by_paren = true +csharp_align_multiline_argument = true +csharp_align_tuple_components = true +csharp_align_multiline_expression = true +csharp_align_multiline_for_stmt = true +csharp_align_multiple_declaration = true +csharp_align_multline_type_parameter_list = true +csharp_align_multline_type_parameter_constrains = true +csharp_int_align_fields = true +csharp_int_align_properties = true +csharp_int_align_methods = true +csharp_int_align_parameters = false +csharp_int_align_variables = true +csharp_int_align_assignments = true +csharp_int_align_nested_ternary = true +csharp_int_align_invocations = false +csharp_int_align_binary_expressions = true +csharp_int_align_comments = true +csharp_int_align_switch_sections = true +csharp_int_align = true +csharp_keep_user_linebreaks = false +csharp_keep_existing_arrangement = false +csharp_keep_existing_linebreaks = false +csharp_max_line_length = 120 +csharp_wrap_before_comma = false +csharp_special_else_if_treatment = true +csharp_insert_final_newline = false +csharp_place_type_attribute_on_same_line = never +csharp_place_method_attribute_on_same_line = never +csharp_place_accessorholder_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_place_accessor_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_place_field_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_wrap_parameters_style = wrap_if_long +csharp_keep_existing_declaration_parens_arrangement = false +csharp_wrap_before_declaration_lpar = false +csharp_wrap_after_declaration_lpar = false +csharp_wrap_before_declaration_rpar = false +csharp_place_constructor_initializer_on_same_line = true +csharp_keep_existing_expr_member_arrangement = false +csharp_place_expr_method_on_single_line = true +csharp_place_expr_property_on_single_line = true +csharp_place_expr_accessor_on_single_line = true +csharp_wrap_before_arrow_with_expressions = false +csharp_place_type_constraints_on_same_line = true +csharp_wrap_before_first_type_parameter_constraint = true +csharp_wrap_multiple_type_parameter_constraints_style = wrap_if_long +csharp_wrap_before_type_parameter_langle = true +csharp_wrap_before_extends_colon = false +csharp_wrap_extends_list_style = wrap_if_long +csharp_keep_existing_declaration_block_arrangement = false +csharp_place_abstract_accessorholder_on_single_line = true +csharp_place_simple_accessorholder_on_single_line = false +csharp_place_accessor_with_attrs_holder_on_single_line = false +csharp_place_simple_accessor_on_single_line = true +csharp_place_simple_method_on_single_line = false +csharp_keep_existing_enum_arrangement = false +csharp_place_simple_enum_on_single_line = false +csharp_wrap_enum_declaration = wrap_if_long +csharp_new_line_before_else = true +csharp_new_line_before_while = false +csharp_wrap_for_stmt_header_style = wrap_if_long +csharp_wrap_multiple_declaration_style = wrap_if_long +csharp_keep_existing_embedded_arrangement = false +csharp_place_simple_embedded_statement_on_same_line = false +csharp_place_simple_case_statement_on_same_line = true +csharp_keep_existing_embedded_block_arrangement = false +csharp_place_simple_embedded_block_on_same_line = false +csharp_place_simple_anonymousmethod_on_single_line = false +csharp_keep_existing_initializer_arrangement = false +csharp_place_simple_initializer_on_single_line = false +csharp_wrap_object_and_collection_initializer_style = chop_always +csharp_wrap_array_initializer_style = wrap_if_long +csharp_wrap_arguments_style = wrap_if_long +csharp_keep_existing_invocation_parens_arrangement = false +csharp_wrap_after_invocation_lpar = false +csharp_wrap_before_invocation_rpar = false +csharp_wrap_after_dot_in_method_calls = true +csharp_wrap_chained_method_calls = wrap_if_long +csharp_wrap_before_binary_opsign = false +csharp_wrap_chained_binary_expressions = wrap_if_long +csharp_force_chop_compound_if_expression = true +csharp_force_chop_compound_while_expression = true +csharp_force_chop_compound_do_expression = true +csharp_wrap_before_ternary_opsigns = true +csharp_wrap_ternary_expr_style = wrap_if_long +csharp_nested_ternary_style = expanded +csharp_wrap_linq_expressions = wrap_if_long +csharp_wrap_before_linq_expression = false +csharp_place_linq_into_on_new_line = false +csharp_wrap_verbatim_interpolated_strings = wrap_if_long +csharp_extra_spaces = remove_all +csharp_space_after_keywords_in_control_flow_statements = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_before_typeof_parentheses = false +csharp_space_before_checked_parentheses = false +csharp_space_before_sizeof_parentheses = false +csharp_space_before_nameof_parentheses = false +csharp_space_between_keyword_and_expression = true +csharp_space_between_keyword_and_type = true +csharp_space_around_assignment_op = true +csharp_space_around_logical_op = true +csharp_space_around_binary_operator = true +csharp_space_around_equality_op = true +csharp_space_around_relational_op = true +csharp_space_around_bitwise_op = true +csharp_space_around_additive_op = true +csharp_space_around_multiplicative_op = true +csharp_space_around_shift_op = true +csharp_space_around_nullcoalescing_op = true +csharp_space_around_arrow_op = false +csharp_space_after_logical_not_op = false +csharp_space_after_unary_operator = false +csharp_space_after_cast = false +csharp_space_around_dot = false +csharp_space_around_lambda_arrow = true +csharp_space_before_pointer_asterik_declaration = false +csharp_space_before_nullable_mark = false + +[*.cshtml] +linebreaks_around_razor_statements = true +blank_lines_around_razor_functions = true +blank_lines_around_razor_helpers = true +blank_lines_around_razor_sections = true + +# C++ +[*.{cc,cpp,cxx,h,hpp,hxx}] +cpp_indent_access_specifiers_from_class = true +cpp_indent_wrapped_function_names = false +cpp_align_multiline_type_argument = true + +# C, C++ and ObjectiveC +[*.{c,h,cc,cpp,cxx,m,hpp,hxx}] +indent_preprocessor_directives = normal +indent_type_constraints = true + +# Javascript and Typescript +[*.{js,js.map,ts}] +quote_style = doublequoted +termination_style = ensure_semicolon \ No newline at end of file diff --git a/Aaru.Helpers/.gitignore b/Aaru.Helpers/.gitignore new file mode 100644 index 000000000..05c540d38 --- /dev/null +++ b/Aaru.Helpers/.gitignore @@ -0,0 +1,595 @@ +### VisualStudio template +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ +### Linux template + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* +### Xcode template +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +### VisualStudioCode template +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +### C++ template +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o + +# Precompiled Headers +*.gch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +### MonoDevelop template +#User Specific +*.usertasks + +#Mono Project Files +*.resources +test-results/ +### GPG template +secring.* + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests +### CMake template +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +### C template +# Object files +*.ko +*.elf + +# Linker output +*.map +*.exp + +*.so.* + +# Executables +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf +### Windows template +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# NuGet Packages Directory +packages/ +## TODO: If the tool you use requires repositories.config uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +# This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented) +!packages/build/ + + +# Others +sql/ +*.Cache + +# Visual Studio 2017 +.vs + +workspace.xml +cmake-build-debug +### macOS template +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +pkg/**/pkg +pkg/**/src +pkg/**/*.asc +pkg/**/*.sig +pkg/**/*.tar.xz +pkg/**/*.zip +pkg/**/aaru + +.sonarqube \ No newline at end of file diff --git a/Aaru.Helpers/Aaru.Helpers.csproj b/Aaru.Helpers/Aaru.Helpers.csproj new file mode 100644 index 000000000..44cf4caa4 --- /dev/null +++ b/Aaru.Helpers/Aaru.Helpers.csproj @@ -0,0 +1,69 @@ + + + + 2.0 + {F8BDF57B-1571-4CD0-84B3-B422088D359A} + Library + Aaru.Helpers + Aaru.Helpers + $(Version) + false + true + 5.3.2 + Claunia.com + Copyright © 2011-2023 Natalia Portillo + Aaru Data Preservation Suite + Aaru.Helpers + $(Version) + netcoreapp3.1 + 8 + Contains helpers used by the Aaru Data Preservation Suite. + https://github.com/aaru-dps/ + LGPL-2.1-only + https://github.com/aaru-dps/Aaru.Helpers + true + en-US + true + true + snupkg + Natalia Portillo <claunia@claunia.com> + + + $(Version)+{chash:8} + true + true + + + + + + + + + + + + + + + + + + + + + + {CCAA7AFE-C094-4D82-A66D-630DE8A3F545} + Aaru.Console + + + + + LICENSE.LGPL + + + + + + + \ No newline at end of file diff --git a/Aaru.Helpers/ArrayFill.cs b/Aaru.Helpers/ArrayFill.cs new file mode 100644 index 000000000..7b45352a3 --- /dev/null +++ b/Aaru.Helpers/ArrayFill.cs @@ -0,0 +1,81 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ArrayFill.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Fills an array with a specified value. +// +// --[ License ] -------------------------------------------------------------- +// +// No license specified by creator. +// +// Published on https://github.com/mykohsu/Extensions/blob/master/ArrayExtensions.cs +// +// Assuming open source. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// Copyright(C) 2014 mykohsu +// ****************************************************************************/ + +using System; +using System.Text; + +namespace Aaru.Helpers +{ + public static partial class ArrayHelpers + { + /// Fills an array with the specified value + /// Array + /// Value + /// Array type + public static void ArrayFill(T[] destinationArray, T value) => ArrayFill(destinationArray, new[] + { + value + }); + + /// Fills an array with the contents of the specified array + /// Array + /// Value + /// Array type + public static void ArrayFill(T[] destinationArray, T[] value) + { + if(destinationArray == null) + throw new ArgumentNullException(nameof(destinationArray)); + + if(value.Length > destinationArray.Length) + throw new ArgumentException("Length of value array must not be more than length of destination"); + + // set the initial array value + Array.Copy(value, destinationArray, value.Length); + + int arrayToFillHalfLength = destinationArray.Length / 2; + int copyLength; + + for(copyLength = value.Length; copyLength < arrayToFillHalfLength; copyLength <<= 1) + Array.Copy(destinationArray, 0, destinationArray, copyLength, copyLength); + + Array.Copy(destinationArray, 0, destinationArray, copyLength, destinationArray.Length - copyLength); + } + + /// Converts a byte array to its hexadecimal representation + /// Byte array + /// true to use uppercase + /// + public static string ByteArrayToHex(byte[] array, bool upper = false) + { + var sb = new StringBuilder(); + + for(long i = 0; i < array.LongLength; i++) + sb.AppendFormat("{0:x2}", array[i]); + + return upper ? sb.ToString().ToUpper() : sb.ToString(); + } + } +} \ No newline at end of file diff --git a/Aaru.Helpers/ArrayIsEmpty.cs b/Aaru.Helpers/ArrayIsEmpty.cs new file mode 100644 index 000000000..2ad87b760 --- /dev/null +++ b/Aaru.Helpers/ArrayIsEmpty.cs @@ -0,0 +1,50 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : ArrayIsEmpty.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Methods for detecting an empty array. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Linq; + +namespace Aaru.Helpers +{ + /// Helper operations to work with arrays + public static partial class ArrayHelpers + { + /// Checks if an array is null, filled with the NULL byte (0x00) or ASCII whitespace (0x20) + /// Array + /// True if null or whitespace + public static bool ArrayIsNullOrWhiteSpace(byte[] array) => array?.All(b => b == 0x00 || b == 0x20) != false; + + /// Checks if an array is null or filled with the NULL byte (0x00) + /// Array + /// True if null + public static bool ArrayIsNullOrEmpty(byte[] array) => array?.All(b => b == 0x00) != false; + } +} \ No newline at end of file diff --git a/Aaru.Helpers/BigEndianBitConverter.cs b/Aaru.Helpers/BigEndianBitConverter.cs new file mode 100644 index 000000000..fcbe3bcaf --- /dev/null +++ b/Aaru.Helpers/BigEndianBitConverter.cs @@ -0,0 +1,324 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : BigEndianBitConverter.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Override of System.BitConverter that knows how to handle big-endian. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Linq; + +namespace Aaru.Helpers +{ + /// + /// Converts base data types to an array of bytes, and an array of bytes to base data types. All info taken from + /// the meta data of System.BitConverter. This implementation allows for Endianness consideration. + /// + public static class BigEndianBitConverter + { + /// Converts the specified double-precision floating point number to a 64-bit signed integer. + /// The number to convert. + /// A 64-bit signed integer whose value is equivalent to value. + /// It is not currently implemented + public static long DoubleToInt64Bits(double value) => throw new NotImplementedException(); + + /// Returns the specified Boolean value as an array of bytes. + /// A Boolean value. + /// An array of bytes with length 1. + public static byte[] GetBytes(bool value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Returns the specified Unicode character value as an array of bytes. + /// A character to convert. + /// An array of bytes with length 2. + public static byte[] GetBytes(char value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Returns the specified double-precision floating point value as an array of bytes. + /// The number to convert. + /// An array of bytes with length 8. + public static byte[] GetBytes(double value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Returns the specified single-precision floating point value as an array of bytes. + /// The number to convert. + /// An array of bytes with length 4. + public static byte[] GetBytes(float value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Returns the specified 32-bit signed integer value as an array of bytes. + /// The number to convert. + /// An array of bytes with length 4. + public static byte[] GetBytes(int value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Returns the specified 64-bit signed integer value as an array of bytes. + /// The number to convert. + /// An array of bytes with length 8. + public static byte[] GetBytes(long value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Returns the specified 16-bit signed integer value as an array of bytes. + /// The number to convert. + /// An array of bytes with length 2. + public static byte[] GetBytes(short value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Returns the specified 32-bit unsigned integer value as an array of bytes. + /// The number to convert. + /// An array of bytes with length 4. + public static byte[] GetBytes(uint value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Returns the specified 64-bit unsigned integer value as an array of bytes. + /// The number to convert. + /// An array of bytes with length 8. + public static byte[] GetBytes(ulong value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Returns the specified 16-bit unsigned integer value as an array of bytes. + /// The number to convert. + /// An array of bytes with length 2. + public static byte[] GetBytes(ushort value) => BitConverter.GetBytes(value).Reverse().ToArray(); + + /// Converts the specified 64-bit signed integer to a double-precision floating point number. + /// The number to convert. + /// A double-precision floating point number whose value is equivalent to value. + public static double Int64BitsToDouble(long value) => throw new NotImplementedException(); + + /// Returns a Boolean value converted from one byte at a specified position in a byte array. + /// An array of bytes. + /// The starting position within value. + /// true if the byte at in value is nonzero; otherwise, false. + /// value is null. + /// + /// is less than zero or greater than the + /// length of value minus 1. + /// + public static bool ToBoolean(byte[] value, int startIndex) => throw new NotImplementedException(); + + /// Returns a Unicode character converted from two bytes at a specified position in a byte array. + /// An array. + /// The starting position within value. + /// A character formed by two bytes beginning at . + /// equals the length of value minus 1. + /// value is null. + /// + /// is less than zero or greater than the + /// length of value minus 1. + /// + public static char ToChar(byte[] value, int startIndex) => throw new NotImplementedException(); + + /// + /// Returns a double-precision floating point number converted from eight bytes at a specified position in a byte + /// array. + /// + /// An array of bytes. + /// The starting position within value. + /// A double precision floating point number formed by eight bytes beginning at . + /// + /// is greater than or equal to the length of value + /// minus 7, and is less than or equal to the length of value minus 1. + /// + /// value is null. + /// + /// is less than zero or greater than the + /// length of value minus 1. + /// + public static double ToDouble(byte[] value, int startIndex) => throw new NotImplementedException(); + + /// Returns a 16-bit signed integer converted from two bytes at a specified position in a byte array. + /// An array of bytes. + /// The starting position within value. + /// A 16-bit signed integer formed by two bytes beginning at . + /// equals the length of value minus 1. + /// value is null. + /// + /// startIndex is less than zero or greater than the length of value + /// minus 1. + /// + public static short ToInt16(byte[] value, int startIndex) => + BitConverter.ToInt16(value.Reverse().ToArray(), value.Length - sizeof(short) - startIndex); + + /// Returns a 32-bit signed integer converted from four bytes at a specified position in a byte array. + /// An array of bytes. + /// The starting position within value. + /// A 32-bit signed integer formed by four bytes beginning at . + /// + /// is greater than or equal to the length of value + /// minus 3, and is less than or equal to the length of value minus 1. + /// + /// value is null. + /// + /// startIndex is less than zero or greater than the length of value + /// minus 1. + /// + public static int ToInt32(byte[] value, int startIndex) => + BitConverter.ToInt32(value.Reverse().ToArray(), value.Length - sizeof(int) - startIndex); + + /// Returns a 64-bit signed integer converted from eight bytes at a specified position in a byte array. + /// An array of bytes. + /// The starting position within value. + /// A 64-bit signed integer formed by eight bytes beginning at . + /// + /// is greater than or equal to the length of value + /// minus 7, and is less than or equal to the length of value minus 1. + /// + /// value is null. + /// + /// is less than zero or greater than the + /// length of value minus 1. + /// + public static long ToInt64(byte[] value, int startIndex) => + BitConverter.ToInt64(value.Reverse().ToArray(), value.Length - sizeof(long) - startIndex); + + /// + /// Returns a single-precision floating point number converted from four bytes at a specified position in a byte + /// array. + /// + /// An array of bytes. + /// The starting position within value. + /// A single-precision floating point number formed by four bytes beginning at . + /// + /// is greater than or equal to the length of value + /// minus 3, and is less than or equal to the length of value minus 1. + /// + /// value is null. + /// + /// is less than zero or greater than the + /// length of value minus 1. + /// + public static float ToSingle(byte[] value, int startIndex) => + BitConverter.ToSingle(value.Reverse().ToArray(), value.Length - sizeof(float) - startIndex); + + /// + /// Converts the numeric value of each element of a specified array of bytes to its equivalent hexadecimal string + /// representation. + /// + /// An array of bytes. + /// + /// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding + /// element in value; for example, "7F-2C-4A". + /// + /// value is null. + public static string ToString(byte[] value) => BitConverter.ToString(value.Reverse().ToArray()); + + /// + /// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal + /// string representation. + /// + /// An array of bytes. + /// The starting position within value. + /// + /// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding + /// element in a subarray of value; for example, "7F-2C-4A". + /// + /// value is null. + /// + /// startIndex is less than zero or greater than the length of value + /// minus 1. + /// + public static string ToString(byte[] value, int startIndex) => + BitConverter.ToString(value.Reverse().ToArray(), startIndex); + + /// + /// Converts the numeric value of each element of a specified subarray of bytes to its equivalent hexadecimal + /// string representation. + /// + /// An array of bytes. + /// The starting position within value. + /// The number of array elements in value to convert. + /// + /// A System.String of hexadecimal pairs separated by hyphens, where each pair represents the corresponding + /// element in a subarray of value; for example, "7F-2C-4A". + /// + /// value is null. + /// + /// startIndex or length is less than zero. -or- startIndex is greater + /// than zero and is greater than or equal to the length of value. + /// + /// + /// The combination of startIndex and length does not specify a position within + /// value; that is, the startIndex parameter is greater than the length of value minus the length parameter. + /// + public static string ToString(byte[] value, int startIndex, int length) => + BitConverter.ToString(value.Reverse().ToArray(), startIndex, length); + + /// Returns a 16-bit unsigned integer converted from two bytes at a specified position in a byte array. + /// The array of bytes. + /// The starting position within value. + /// A 16-bit unsigned integer formed by two bytes beginning at startIndex. + /// startIndex equals the length of value minus 1. + /// value is null. + /// + /// startIndex is less than zero or greater than the length of value + /// minus 1. + /// + public static ushort ToUInt16(byte[] value, int startIndex) => + BitConverter.ToUInt16(value.Reverse().ToArray(), value.Length - sizeof(ushort) - startIndex); + + /// Returns a 32-bit unsigned integer converted from four bytes at a specified position in a byte array. + /// An array of bytes. + /// The starting position within value. + /// A 32-bit unsigned integer formed by four bytes beginning at startIndex. + /// + /// startIndex is greater than or equal to the length of value minus 3, and is + /// less than or equal to the length of value minus 1. + /// + /// value is null. + /// + /// startIndex is less than zero or greater than the length of value + /// minus 1. + /// + public static uint ToUInt32(byte[] value, int startIndex) => + BitConverter.ToUInt32(value.Reverse().ToArray(), value.Length - sizeof(uint) - startIndex); + + /// Returns a 64-bit unsigned integer converted from eight bytes at a specified position in a byte array. + /// An array of bytes. + /// The starting position within value. + /// A 64-bit unsigned integer formed by the eight bytes beginning at startIndex. + /// + /// startIndex is greater than or equal to the length of value minus 7, and is + /// less than or equal to the length of value minus 1. + /// + /// value is null. + /// + /// startIndex is less than zero or greater than the length of value + /// minus 1. + /// + public static ulong ToUInt64(byte[] value, int startIndex) => + BitConverter.ToUInt64(value.Reverse().ToArray(), value.Length - sizeof(ulong) - startIndex); + + /// Converts a big endian byte array representation of a GUID into the .NET Guid structure + /// Byte array containing a GUID in big endian + /// Start of the byte array to process + /// Processed Guid + public static Guid ToGuid(byte[] value, int startIndex) => new Guid(ToUInt32(value, 0 + startIndex), + ToUInt16(value, 4 + startIndex), + ToUInt16(value, 6 + startIndex), + value[8 + startIndex + 0], + value[8 + startIndex + 1], + value[8 + startIndex + 2], + value[8 + startIndex + 3], + value[8 + startIndex + 5], + value[8 + startIndex + 5], + value[8 + startIndex + 6], + value[8 + startIndex + 7]); + } +} \ No newline at end of file diff --git a/Aaru.Helpers/BitEndian.cs b/Aaru.Helpers/BitEndian.cs new file mode 100644 index 000000000..8a67f85f7 --- /dev/null +++ b/Aaru.Helpers/BitEndian.cs @@ -0,0 +1,51 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : BitEndian.cs +// Author(s) : Natalia Portillo +// +// Component : Common types. +// +// --[ Description ] ---------------------------------------------------------- +// +// Defines enumerations of bit endianness. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.Helpers +{ + /// Describes the endianness of bits on a data structure + public enum BitEndian + { + /// Little-endian, or least significant bit + Little, + /// Big-endian, or most significant bit + Big, + /// PDP-11 endian, little endian except for 32-bit integers where the 16 halves are swapped between them + Pdp + } +} \ No newline at end of file diff --git a/Aaru.Helpers/CHS.cs b/Aaru.Helpers/CHS.cs new file mode 100644 index 000000000..725c960cb --- /dev/null +++ b/Aaru.Helpers/CHS.cs @@ -0,0 +1,49 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CHS.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Helpers for CHS<->LBA conversions +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.Helpers +{ + /// Helper operations to work with CHS values + public static class CHS + { + /// Converts a CHS position to a LBA one + /// Cylinder + /// Head + /// Sector + /// Number of heads + /// Number of sectors per track + /// + public static uint ToLBA(uint cyl, uint head, uint sector, uint maxHead, uint maxSector) => + maxHead == 0 || maxSector == 0 ? (((cyl * 16) + head) * 63) + sector - 1 + : (((cyl * maxHead) + head) * maxSector) + sector - 1; + } +} \ No newline at end of file diff --git a/Aaru.Helpers/CompareBytes.cs b/Aaru.Helpers/CompareBytes.cs new file mode 100644 index 000000000..cf8f2c6f8 --- /dev/null +++ b/Aaru.Helpers/CompareBytes.cs @@ -0,0 +1,72 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CompareBytes.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Compares two byte arrays. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.Helpers +{ + public static partial class ArrayHelpers + { + /// Compares two byte arrays + /// true if they are different in any way + /// true if they have the same size + /// Left array + /// Right array + public static void CompareBytes(out bool different, out bool sameSize, byte[] compareArray1, + byte[] compareArray2) + { + different = false; + sameSize = true; + + long leastBytes; + + if(compareArray1.LongLength < compareArray2.LongLength) + { + sameSize = false; + leastBytes = compareArray1.LongLength; + } + else if(compareArray1.LongLength > compareArray2.LongLength) + { + sameSize = false; + leastBytes = compareArray2.LongLength; + } + else + leastBytes = compareArray1.LongLength; + + for(long i = 0; i < leastBytes; i++) + if(compareArray1[i] != compareArray2[i]) + { + different = true; + + return; + } + } + } +} \ No newline at end of file diff --git a/Aaru.Helpers/CountBits.cs b/Aaru.Helpers/CountBits.cs new file mode 100644 index 000000000..d2d7eac00 --- /dev/null +++ b/Aaru.Helpers/CountBits.cs @@ -0,0 +1,49 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : CountBits.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Counts bits in a number. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +namespace Aaru.Helpers +{ + /// Helper operations to count bits + public static class CountBits + { + /// Counts the number of bits set to true in a number + /// Number + /// Bits set to true + public static int Count(uint number) + { + number -= (number >> 1) & 0x55555555; + number = (number & 0x33333333) + ((number >> 2) & 0x33333333); + + return (int)((((number + (number >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24); + } + } +} \ No newline at end of file diff --git a/Aaru.Helpers/DateHandlers.cs b/Aaru.Helpers/DateHandlers.cs new file mode 100644 index 000000000..cb6b70c7c --- /dev/null +++ b/Aaru.Helpers/DateHandlers.cs @@ -0,0 +1,389 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : DateHandlers.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Convert several timestamp formats to C# DateTime. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Text; +using Aaru.Console; + +namespace Aaru.Helpers +{ + /// Helper operations for timestamp management (date and time) + public static class DateHandlers + { + static readonly DateTime _lisaEpoch = new DateTime(1901, 1, 1, 0, 0, 0); + static readonly DateTime _macEpoch = new DateTime(1904, 1, 1, 0, 0, 0); + static readonly DateTime _unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0); + /// Day 0 of Julian Date system + static readonly DateTime _julianEpoch = new DateTime(1858, 11, 17, 0, 0, 0); + static readonly DateTime _amigaEpoch = new DateTime(1978, 1, 1, 0, 0, 0); + + /// Converts a Macintosh timestamp to a .NET DateTime + /// Macintosh timestamp (seconds since 1st Jan. 1904) + /// .NET DateTime + public static DateTime MacToDateTime(ulong macTimeStamp) => _macEpoch.AddTicks((long)(macTimeStamp * 10000000)); + + /// Converts a Lisa timestamp to a .NET DateTime + /// Lisa timestamp (seconds since 1st Jan. 1901) + /// .NET DateTime + public static DateTime LisaToDateTime(uint lisaTimeStamp) => _lisaEpoch.AddSeconds(lisaTimeStamp); + + /// Converts a UNIX timestamp to a .NET DateTime + /// UNIX timestamp (seconds since 1st Jan. 1970) + /// .NET DateTime + public static DateTime UnixToDateTime(int unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp); + + /// Converts a UNIX timestamp to a .NET DateTime + /// UNIX timestamp (seconds since 1st Jan. 1970) + /// .NET DateTime + public static DateTime UnixToDateTime(long unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp); + + /// Converts a UNIX timestamp to a .NET DateTime + /// UNIX timestamp (seconds since 1st Jan. 1970) + /// .NET DateTime + public static DateTime UnixUnsignedToDateTime(uint unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp); + + /// Converts a UNIX timestamp to a .NET DateTime + /// Seconds since 1st Jan. 1970) + /// Nanoseconds + /// .NET DateTime + public static DateTime UnixUnsignedToDateTime(uint seconds, uint nanoseconds) => + _unixEpoch.AddSeconds(seconds).AddTicks((long)nanoseconds / 100); + + /// Converts a UNIX timestamp to a .NET DateTime + /// UNIX timestamp (seconds since 1st Jan. 1970) + /// .NET DateTime + public static DateTime UnixUnsignedToDateTime(ulong unixTimeStamp) => _unixEpoch.AddSeconds(unixTimeStamp); + + /// Converts a High Sierra Format timestamp to a .NET DateTime + /// High Sierra Format timestamp + /// .NET DateTime + public static DateTime HighSierraToDateTime(byte[] vdDateTime) + { + byte[] isoTime = new byte[17]; + Array.Copy(vdDateTime, 0, isoTime, 0, 16); + + return Iso9660ToDateTime(isoTime); + } + + // TODO: Timezone + /// Converts an ISO9660 timestamp to a .NET DateTime + /// ISO9660 timestamp + /// .NET DateTime + public static DateTime Iso9660ToDateTime(byte[] vdDateTime) + { + byte[] twoCharValue = new byte[2]; + byte[] fourCharValue = new byte[4]; + + fourCharValue[0] = vdDateTime[0]; + fourCharValue[1] = vdDateTime[1]; + fourCharValue[2] = vdDateTime[2]; + fourCharValue[3] = vdDateTime[3]; + + AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "year = \"{0}\"", + StringHandlers.CToString(fourCharValue, Encoding.ASCII)); + + if(!int.TryParse(StringHandlers.CToString(fourCharValue, Encoding.ASCII), out int year)) + year = 0; + + twoCharValue[0] = vdDateTime[4]; + twoCharValue[1] = vdDateTime[5]; + + AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "month = \"{0}\"", + StringHandlers.CToString(twoCharValue, Encoding.ASCII)); + + if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int month)) + month = 0; + + twoCharValue[0] = vdDateTime[6]; + twoCharValue[1] = vdDateTime[7]; + + AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "day = \"{0}\"", + StringHandlers.CToString(twoCharValue, Encoding.ASCII)); + + if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int day)) + day = 0; + + twoCharValue[0] = vdDateTime[8]; + twoCharValue[1] = vdDateTime[9]; + + AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "hour = \"{0}\"", + StringHandlers.CToString(twoCharValue, Encoding.ASCII)); + + if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int hour)) + hour = 0; + + twoCharValue[0] = vdDateTime[10]; + twoCharValue[1] = vdDateTime[11]; + + AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "minute = \"{0}\"", + StringHandlers.CToString(twoCharValue, Encoding.ASCII)); + + if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int minute)) + minute = 0; + + twoCharValue[0] = vdDateTime[12]; + twoCharValue[1] = vdDateTime[13]; + + AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "second = \"{0}\"", + StringHandlers.CToString(twoCharValue, Encoding.ASCII)); + + if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int second)) + second = 0; + + twoCharValue[0] = vdDateTime[14]; + twoCharValue[1] = vdDateTime[15]; + + AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", "hundredths = \"{0}\"", + StringHandlers.CToString(twoCharValue, Encoding.ASCII)); + + if(!int.TryParse(StringHandlers.CToString(twoCharValue, Encoding.ASCII), out int hundredths)) + hundredths = 0; + + AaruConsole.DebugWriteLine("ISO9600ToDateTime handler", + "decodedDT = new DateTime({0}, {1}, {2}, {3}, {4}, {5}, {6}, DateTimeKind.Unspecified);", + year, month, day, hour, minute, second, hundredths * 10); + + sbyte difference = (sbyte)vdDateTime[16]; + + var decodedDt = new DateTime(year, month, day, hour, minute, second, hundredths * 10, DateTimeKind.Utc); + + return decodedDt.AddMinutes(difference * -15); + } + + /// Converts a VMS timestamp to a .NET DateTime + /// VMS timestamp (tenths of microseconds since day 0 of the Julian Date) + /// .NET DateTime + /// C# works in UTC, VMS on Julian Date, some displacement may occur on disks created outside UTC + public static DateTime VmsToDateTime(ulong vmsDate) + { + double delta = vmsDate * 0.0001; // Tenths of microseconds to milliseconds, will lose some detail + + return _julianEpoch.AddMilliseconds(delta); + } + + /// Converts an Amiga timestamp to a .NET DateTime + /// Days since the 1st Jan. 1978 + /// Minutes since o'clock + /// Ticks + /// .NET DateTime + public static DateTime AmigaToDateTime(uint days, uint minutes, uint ticks) + { + DateTime temp = _amigaEpoch.AddDays(days); + temp = temp.AddMinutes(minutes); + + return temp.AddMilliseconds(ticks * 20); + } + + /// Converts an UCSD Pascal timestamp to a .NET DateTime + /// UCSD Pascal timestamp + /// .NET DateTime + public static DateTime UcsdPascalToDateTime(short dateRecord) + { + int year = ((dateRecord & 0xFE00) >> 9) + 1900; + int day = (dateRecord & 0x01F0) >> 4; + int month = dateRecord & 0x000F; + + AaruConsole.DebugWriteLine("UCSDPascalToDateTime handler", + "dateRecord = 0x{0:X4}, year = {1}, month = {2}, day = {3}", dateRecord, year, + month, day); + + return new DateTime(year, month, day); + } + + /// Converts a DOS timestamp to a .NET DateTime + /// Date + /// Time + /// .NET DateTime + public static DateTime DosToDateTime(ushort date, ushort time) + { + int year = ((date & 0xFE00) >> 9) + 1980; + int month = (date & 0x1E0) >> 5; + int day = date & 0x1F; + int hour = (time & 0xF800) >> 11; + int minute = (time & 0x7E0) >> 5; + int second = (time & 0x1F) * 2; + + AaruConsole.DebugWriteLine("DOSToDateTime handler", "date = 0x{0:X4}, year = {1}, month = {2}, day = {3}", + date, year, month, day); + + AaruConsole.DebugWriteLine("DOSToDateTime handler", + "time = 0x{0:X4}, hour = {1}, minute = {2}, second = {3}", time, hour, minute, + second); + + DateTime dosDate; + + try + { + dosDate = new DateTime(year, month, day, hour, minute, second); + } + catch(ArgumentOutOfRangeException) + { + dosDate = new DateTime(1980, 1, 1, 0, 0, 0); + } + + return dosDate; + } + + /// Converts a CP/M timestamp to .NET DateTime + /// CP/M timestamp + /// .NET DateTime + public static DateTime CpmToDateTime(byte[] timestamp) + { + ushort days = BitConverter.ToUInt16(timestamp, 0); + int hours = timestamp[2]; + int minutes = timestamp[3]; + + DateTime temp = _amigaEpoch.AddDays(days); + temp = temp.AddHours(hours); + temp = temp.AddMinutes(minutes); + + return temp; + } + + /// Converts an ECMA timestamp to a .NET DateTime + /// Timezone + /// Year + /// Month + /// Day + /// Hour + /// Minute + /// Second + /// Centiseconds + /// Hundreds of microseconds + /// Microseconds + /// + public static DateTime EcmaToDateTime(ushort typeAndTimeZone, short year, byte month, byte day, byte hour, + byte minute, byte second, byte centiseconds, byte hundredsOfMicroseconds, + byte microseconds) + { + byte specification = (byte)((typeAndTimeZone & 0xF000) >> 12); + + long ticks = ((long)centiseconds * 100000) + ((long)hundredsOfMicroseconds * 1000) + + ((long)microseconds * 10); + + if(specification == 0) + return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Utc).AddTicks(ticks); + + ushort preOffset = (ushort)(typeAndTimeZone & 0xFFF); + short offset; + + if((preOffset & 0x800) == 0x800) + offset = (short)(preOffset | 0xF000); + else + offset = (short)(preOffset & 0x7FF); + + if(offset == -2047) + return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Unspecified).AddTicks(ticks); + + if(offset < -1440 || + offset > 1440) + offset = 0; + + return new DateTimeOffset(year, month, day, hour, minute, second, new TimeSpan(0, offset, 0)). + AddTicks(ticks).DateTime; + } + + /// Converts a Solaris high resolution timestamp to .NET DateTime + /// Solaris high resolution timestamp + /// .NET DateTime + public static DateTime UnixHrTimeToDateTime(ulong hrTimeStamp) => + _unixEpoch.AddTicks((long)(hrTimeStamp / 100)); + + /// Converts an OS-9 timestamp to .NET DateTime + /// OS-9 timestamp + /// .NET DateTime + public static DateTime Os9ToDateTime(byte[] date) + { + if(date == null || + (date.Length != 3 && date.Length != 5)) + return DateTime.MinValue; + + DateTime os9Date; + + try + { + os9Date = date.Length == 5 ? new DateTime(1900 + date[0], date[1], date[2], date[3], date[4], 0) + : new DateTime(1900 + date[0], date[1], date[2], 0, 0, 0); + } + catch(ArgumentOutOfRangeException) + { + os9Date = new DateTime(1900, 0, 0, 0, 0, 0); + } + + return os9Date; + } + + /// Converts a LIF timestamp to .NET DateTime + /// LIF timestamp + /// .NET DateTime + public static DateTime LifToDateTime(byte[] date) + { + if(date == null || + date.Length != 6) + return new DateTime(1970, 1, 1, 0, 0, 0); + + return LifToDateTime(date[0], date[1], date[2], date[3], date[4], date[5]); + } + + /// Converts a LIF timestamp to .NET DateTime + /// Yer + /// Month + /// Day + /// Hour + /// Minute + /// Second + /// .NET DateTime + public static DateTime LifToDateTime(byte year, byte month, byte day, byte hour, byte minute, byte second) + { + try + { + int iyear = ((year >> 4) * 10) + (year & 0xF); + int imonth = ((month >> 4) * 10) + (month & 0xF); + int iday = ((day >> 4) * 10) + (day & 0xF); + int iminute = ((minute >> 4) * 10) + (minute & 0xF); + int ihour = ((hour >> 4) * 10) + (hour & 0xF); + int isecond = ((second >> 4) * 10) + (second & 0xF); + + if(iyear >= 70) + iyear += 1900; + else + iyear += 2000; + + return new DateTime(iyear, imonth, iday, ihour, iminute, isecond); + } + catch(ArgumentOutOfRangeException) + { + return new DateTime(1970, 1, 1, 0, 0, 0); + } + } + } +} \ No newline at end of file diff --git a/Aaru.Helpers/Marshal.cs b/Aaru.Helpers/Marshal.cs new file mode 100644 index 000000000..b0529c4c5 --- /dev/null +++ b/Aaru.Helpers/Marshal.cs @@ -0,0 +1,498 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Marshal.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Provides marshalling for binary data. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Aaru.Helpers +{ + /// Provides methods to marshal binary data into C# structs + public static class Marshal + { + /// Returns the size of an unmanaged type in bytes. + /// The type whose size is to be returned. + /// The size, in bytes, of the type that is specified by the generic type parameter. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int SizeOf() => System.Runtime.InteropServices.Marshal.SizeOf(); + + /// Marshal little-endian binary data to a structure + /// Byte array containing the binary data + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T ByteArrayToStructureLittleEndian(byte[] bytes) where T : struct + { + var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned); + + var str = (T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T)); + + ptr.Free(); + + return str; + } + + /// Marshal little-endian binary data to a structure + /// Byte array containing the binary data + /// Start on the array where the structure begins + /// Length of the structure in bytes + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T ByteArrayToStructureLittleEndian(byte[] bytes, int start, int length) where T : struct + { + Span span = bytes; + + return ByteArrayToStructureLittleEndian(span.Slice(start, length).ToArray()); + } + + /// Marshal big-endian binary data to a structure + /// Byte array containing the binary data + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T ByteArrayToStructureBigEndian(byte[] bytes) where T : struct + { + var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned); + + object str = (T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T)); + + ptr.Free(); + + return (T)SwapStructureMembersEndian(str); + } + + /// Marshal big-endian binary data to a structure + /// Byte array containing the binary data + /// Start on the array where the structure begins + /// Length of the structure in bytes + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T ByteArrayToStructureBigEndian(byte[] bytes, int start, int length) where T : struct + { + Span span = bytes; + + return ByteArrayToStructureBigEndian(span.Slice(start, length).ToArray()); + } + + /// Marshal PDP-11 binary data to a structure + /// Byte array containing the binary data + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T ByteArrayToStructurePdpEndian(byte[] bytes) where T : struct + { + { + var ptr = GCHandle.Alloc(bytes, GCHandleType.Pinned); + + object str = + (T)System.Runtime.InteropServices.Marshal.PtrToStructure(ptr.AddrOfPinnedObject(), typeof(T)); + + ptr.Free(); + + return (T)SwapStructureMembersEndianPdp(str); + } + } + + /// Marshal PDP-11 binary data to a structure + /// Byte array containing the binary data + /// Start on the array where the structure begins + /// Length of the structure in bytes + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T ByteArrayToStructurePdpEndian(byte[] bytes, int start, int length) where T : struct + { + Span span = bytes; + + return ByteArrayToStructurePdpEndian(span.Slice(start, length).ToArray()); + } + + /// + /// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this + /// method will crash. + /// + /// Byte array containing the binary data + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T SpanToStructureLittleEndian(ReadOnlySpan bytes) where T : struct => + MemoryMarshal.Read(bytes); + + /// + /// Marshal little-endian binary data to a structure. If the structure type contains any non value type, this + /// method will crash. + /// + /// Byte span containing the binary data + /// Start on the span where the structure begins + /// Length of the structure in bytes + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T SpanToStructureLittleEndian(ReadOnlySpan bytes, int start, int length) + where T : struct => MemoryMarshal.Read(bytes.Slice(start, length)); + + /// + /// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method + /// will crash. + /// + /// Byte array containing the binary data + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T SpanToStructureBigEndian(ReadOnlySpan bytes) where T : struct + { + T str = SpanToStructureLittleEndian(bytes); + + return (T)SwapStructureMembersEndian(str); + } + + /// + /// Marshal big-endian binary data to a structure. If the structure type contains any non value type, this method + /// will crash. + /// + /// Byte span containing the binary data + /// Start on the span where the structure begins + /// Length of the structure in bytes + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T SpanToStructureBigEndian(ReadOnlySpan bytes, int start, int length) where T : struct + { + T str = SpanToStructureLittleEndian(bytes.Slice(start, length)); + + return (T)SwapStructureMembersEndian(str); + } + + /// + /// Marshal PDP-11 binary data to a structure. If the structure type contains any non value type, this method will + /// crash. + /// + /// Byte array containing the binary data + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T SpanToStructurePdpEndian(ReadOnlySpan bytes) where T : struct + { + object str = SpanToStructureLittleEndian(bytes); + + return (T)SwapStructureMembersEndianPdp(str); + } + + /// + /// Marshal PDP-11 binary data to a structure. If the structure type contains any non value type, this method will + /// crash. + /// + /// Byte array containing the binary data + /// Start on the span where the structure begins + /// Length of the structure in bytes + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T SpanToStructurePdpEndian(ReadOnlySpan bytes, int start, int length) where T : struct + { + object str = SpanToStructureLittleEndian(bytes.Slice(start, length)); + + return (T)SwapStructureMembersEndianPdp(str); + } + + /// + /// Marshal a structure depending on the decoration of . If the + /// decoration is not present it will marshal as a reference type containing little endian structure. + /// + /// Byte array containing the binary data + /// Type of the structure to marshal + /// The binary data marshalled in a structure with the specified type + /// + /// The contains an unsupported + /// endian + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MarshalStructure(byte[] bytes) where T : struct + { + if(!(typeof(T).GetCustomAttribute(typeof(MarshallingPropertiesAttribute)) is MarshallingPropertiesAttribute + properties)) + return ByteArrayToStructureLittleEndian(bytes); + + switch(properties.Endian) + { + case BitEndian.Little: + return properties.HasReferences ? ByteArrayToStructureLittleEndian(bytes) + : SpanToStructureLittleEndian(bytes); + + case BitEndian.Big: + return properties.HasReferences ? ByteArrayToStructureBigEndian(bytes) + : SpanToStructureBigEndian(bytes); + + case BitEndian.Pdp: + return properties.HasReferences ? ByteArrayToStructurePdpEndian(bytes) + : SpanToStructurePdpEndian(bytes); + default: throw new ArgumentOutOfRangeException(); + } + } + + /// Swaps all members of a structure + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining), SuppressMessage("ReSharper", "InconsistentNaming")] + public static object SwapStructureMembersEndian(object str) + { + Type t = str.GetType(); + FieldInfo[] fieldInfo = t.GetFields(); + + foreach(FieldInfo fi in fieldInfo) + if(fi.FieldType == typeof(short) || + (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(short))) + { + short x = (short)fi.GetValue(str); + fi.SetValue(str, (short)((x << 8) | ((x >> 8) & 0xFF))); + } + else if(fi.FieldType == typeof(int) || + (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(int))) + { + int x = (int)fi.GetValue(str); + x = (int)(((x << 8) & 0xFF00FF00) | (((uint)x >> 8) & 0xFF00FF)); + fi.SetValue(str, (int)(((uint)x << 16) | (((uint)x >> 16) & 0xFFFF))); + } + else if(fi.FieldType == typeof(long) || + (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(long))) + { + long x = (long)fi.GetValue(str); + x = ((x & 0x00000000FFFFFFFF) << 32) | (long)(((ulong)x & 0xFFFFFFFF00000000) >> 32); + x = ((x & 0x0000FFFF0000FFFF) << 16) | (long)(((ulong)x & 0xFFFF0000FFFF0000) >> 16); + x = ((x & 0x00FF00FF00FF00FF) << 8) | (long)(((ulong)x & 0xFF00FF00FF00FF00) >> 8); + + fi.SetValue(str, x); + } + else if(fi.FieldType == typeof(ushort) || + (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(ushort))) + { + ushort x = (ushort)fi.GetValue(str); + fi.SetValue(str, (ushort)((x << 8) | (x >> 8))); + } + else if(fi.FieldType == typeof(uint) || + (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(uint))) + { + uint x = (uint)fi.GetValue(str); + x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF); + fi.SetValue(str, (x << 16) | (x >> 16)); + } + else if(fi.FieldType == typeof(ulong) || + (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(ulong))) + { + ulong x = (ulong)fi.GetValue(str); + x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32); + x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16); + x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8); + fi.SetValue(str, x); + } + else if(fi.FieldType == typeof(float)) + { + float flt = (float)fi.GetValue(str); + byte[] flt_b = BitConverter.GetBytes(flt); + + fi.SetValue(str, BitConverter.ToSingle(new[] + { + flt_b[3], flt_b[2], flt_b[1], flt_b[0] + }, 0)); + } + else if(fi.FieldType == typeof(double)) + { + double dbl = (double)fi.GetValue(str); + byte[] dbl_b = BitConverter.GetBytes(dbl); + + fi.SetValue(str, BitConverter.ToDouble(new[] + { + dbl_b[7], dbl_b[6], dbl_b[5], dbl_b[4], dbl_b[3], dbl_b[2], dbl_b[1], dbl_b[0] + }, 0)); + } + else if(fi.FieldType == typeof(byte) || + fi.FieldType == typeof(sbyte)) + { + // Do nothing, can't byteswap them! + } + else if(fi.FieldType == typeof(Guid)) + { + // TODO: Swap GUID + } + + // TODO: Swap arrays + else if(fi.FieldType.IsValueType && + !fi.FieldType.IsEnum && + !fi.FieldType.IsArray) + { + object obj = fi.GetValue(str); + object strc = SwapStructureMembersEndian(obj); + fi.SetValue(str, strc); + } + + return str; + } + + /// Swaps all fields in an structure considering them to follow PDP endian conventions + /// Source structure + /// Resulting structure + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static object SwapStructureMembersEndianPdp(object str) + { + Type t = str.GetType(); + FieldInfo[] fieldInfo = t.GetFields(); + + foreach(FieldInfo fi in fieldInfo) + if(fi.FieldType == typeof(short) || + fi.FieldType == typeof(long) || + fi.FieldType == typeof(ushort) || + fi.FieldType == typeof(ulong) || + fi.FieldType == typeof(float) || + fi.FieldType == typeof(double) || + fi.FieldType == typeof(byte) || + fi.FieldType == typeof(sbyte) || + fi.FieldType == typeof(Guid)) + { + // Do nothing + } + else if(fi.FieldType == typeof(int) || + (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(int))) + { + int x = (int)fi.GetValue(str); + fi.SetValue(str, ((x & 0xffffu) << 16) | ((x & 0xffff0000u) >> 16)); + } + else if(fi.FieldType == typeof(uint) || + (fi.FieldType.IsEnum && fi.FieldType.GetEnumUnderlyingType() == typeof(uint))) + { + uint x = (uint)fi.GetValue(str); + fi.SetValue(str, ((x & 0xffffu) << 16) | ((x & 0xffff0000u) >> 16)); + } + + // TODO: Swap arrays + else if(fi.FieldType.IsValueType && + !fi.FieldType.IsEnum && + !fi.FieldType.IsArray) + { + object obj = fi.GetValue(str); + object strc = SwapStructureMembersEndianPdp(obj); + fi.SetValue(str, strc); + } + + return str; + } + + /// Marshal a structure to little-endian binary data + /// The structure you want to marshal to binary + /// Type of the structure to marshal + /// The byte array representing the given structure + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte[] StructureToByteArrayLittleEndian(T str) where T : struct + { + byte[] buf = new byte[SizeOf()]; + var ptr = GCHandle.Alloc(buf, GCHandleType.Pinned); + System.Runtime.InteropServices.Marshal.StructureToPtr(str, ptr.AddrOfPinnedObject(), false); + ptr.Free(); + + return buf; + } + + /// Marshal a structure to little-endian binary data + /// The structure you want to marshal to binary + /// Type of the structure to marshal + /// The byte array representing the given structure + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte[] StructureToByteArrayBigEndian(T str) where T : struct => + StructureToByteArrayLittleEndian((T)SwapStructureMembersEndian(str)); + + /// Converts a hexadecimal string into a byte array + /// Hexadecimal string + /// Resulting byte array + /// Number of output bytes processed + public static int ConvertFromHexAscii(string hex, out byte[] outBuf) + { + outBuf = null; + + if(hex is null || + hex == "") + return -1; + + int off = 0; + + if(hex[0] == '0' && + (hex[1] == 'x' || hex[1] == 'X')) + { + off = 2; + } + + outBuf = new byte[(hex.Length - off) / 2]; + int count = 0; + + for(int i = off; i < hex.Length; i += 2) + { + char c = hex[i]; + + if(c < '0' || + (c > '9' && c < 'A') || + (c > 'F' && c < 'a') || + c > 'f') + break; + + c -= c >= 'a' && c <= 'f' + ? '\u0057' + : c >= 'A' && c <= 'F' + ? '\u0037' + : '\u0030'; + + outBuf[(i - off) / 2] = (byte)(c << 4); + + c = hex[i + 1]; + + if(c < '0' || + (c > '9' && c < 'A') || + (c > 'F' && c < 'a') || + c > 'f') + break; + + c -= c >= 'a' && c <= 'f' + ? '\u0057' + : c >= 'A' && c <= 'F' + ? '\u0037' + : '\u0030'; + + outBuf[(i - off) / 2] += (byte)c; + + count++; + } + + return count; + } + } +} \ No newline at end of file diff --git a/Aaru.Helpers/MarshallingPropertiesAttribute.cs b/Aaru.Helpers/MarshallingPropertiesAttribute.cs new file mode 100644 index 000000000..2283337b1 --- /dev/null +++ b/Aaru.Helpers/MarshallingPropertiesAttribute.cs @@ -0,0 +1,62 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : MarshallingPropertiesAttribute.cs +// Author(s) : Natalia Portillo +// +// Component : Common types. +// +// --[ Description ] ---------------------------------------------------------- +// +// Declares properties of structs for marshalling. +// +// --[ License ] -------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; + +namespace Aaru.Helpers +{ + /// + /// Defines properties to help marshalling structs from binary data + [AttributeUsage(AttributeTargets.Struct)] + public sealed class MarshallingPropertiesAttribute : Attribute + { + /// + /// Defines properties to help marshalling structs from binary data + /// Defines properties to help marshalling structs from binary data + public MarshallingPropertiesAttribute(BitEndian endian) + { + Endian = endian; + HasReferences = true; + } + + /// c + public BitEndian Endian { get; } + /// Tells if the structure, or any nested structure, has any non-value type (e.g. arrays, strings, etc). + public bool HasReferences { get; set; } + } +} \ No newline at end of file diff --git a/Aaru.Helpers/PrintHex.cs b/Aaru.Helpers/PrintHex.cs new file mode 100644 index 000000000..ea634eb00 --- /dev/null +++ b/Aaru.Helpers/PrintHex.cs @@ -0,0 +1,136 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : PrintHex.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Prints a byte array as hexadecimal. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Text; +using Aaru.Console; + +namespace Aaru.Helpers +{ + /// Helper operations to get hexadecimal representations of byte arrays + public static class PrintHex + { + /// Prints a byte array as hexadecimal values to the console + /// Array + /// Width of line + public static void PrintHexArray(byte[] array, int width = 16) => + AaruConsole.WriteLine(ByteArrayToHexArrayString(array, width)); + + /// Prints a byte array as hexadecimal values to a string + /// Array + /// Width of line + /// Use ANSI escape colors for sections + /// String containing hexadecimal values + public static string ByteArrayToHexArrayString(byte[] array, int width = 16, bool color = false) + { + if(array is null) + return null; + + // TODO: Color list + // TODO: Allow to change width + string str = "Offset"; + int rows = array.Length / 16; + int last = array.Length % 16; + int offsetLength = $"{array.Length:X}".Length; + var sb = new StringBuilder(); + + if(last > 0) + rows++; + + if(last == 0) + last = 16; + + if(offsetLength < str.Length) + offsetLength = str.Length; + + while(str.Length < offsetLength) + str += ' '; + + if(color) + sb.Append("\u001b[36m"); + + sb.Append(str); + sb.Append(" "); + + for(int i = 0; i < 16; i++) + { + sb.AppendFormat(" {0:X2}", i); + } + + if(color) + sb.Append("\u001b[0m"); + + sb.AppendLine(); + + int b = 0; + + string format = $"{{0:X{offsetLength}}}"; + + for(int i = 0; i < rows; i++) + { + if(color) + sb.Append("\u001b[36m"); + + sb.AppendFormat(format, b); + + if(color) + sb.Append("\u001b[0m"); + + sb.Append(" "); + int lastBytes = i == rows - 1 ? last : 16; + int lastSpaces = 16 - lastBytes; + + for(int j = 0; j < lastBytes; j++) + { + sb.AppendFormat(" {0:X2}", array[b]); + b++; + } + + for(int j = 0; j < lastSpaces; j++) + sb.Append(" "); + + b -= lastBytes; + sb.Append(" "); + + for(int j = 0; j < lastBytes; j++) + { + int v = array[b]; + sb.Append((v > 31 && v < 127) || v > 159 ? (char)v : '.'); + b++; + } + + sb.AppendLine(); + } + + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/Aaru.Helpers/StringHandlers.cs b/Aaru.Helpers/StringHandlers.cs new file mode 100644 index 000000000..c566151b7 --- /dev/null +++ b/Aaru.Helpers/StringHandlers.cs @@ -0,0 +1,185 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : StringHandlers.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Convert byte arrays to C# strings. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System; +using System.Text; + +namespace Aaru.Helpers +{ + /// Helper operations to work with strings + public static class StringHandlers + { + /// Converts a null-terminated (aka C string) ASCII byte array to a C# string + /// The corresponding C# string + /// A null-terminated (aka C string) ASCII byte array + public static string CToString(byte[] cString) => CToString(cString, Encoding.ASCII); + + /// Converts a null-terminated (aka C string) byte array with the specified encoding to a C# string + /// The corresponding C# string + /// A null-terminated (aka C string) byte array in the specified encoding + /// Encoding. + /// Set if encoding uses 16-bit characters. + /// Start decoding at this position + public static string CToString(byte[] cString, Encoding encoding, bool twoBytes = false, int start = 0) + { + if(cString == null) + return null; + + int len = 0; + + for(int i = start; i < cString.Length; i++) + { + if(cString[i] == 0) + if(twoBytes) + { + if(i + 1 < cString.Length && + cString[i + 1] == 0) + { + len++; + + break; + } + } + else + break; + + len++; + } + + if(twoBytes && len % 2 > 0) + len--; + + byte[] dest = new byte[len]; + Array.Copy(cString, start, dest, 0, len); + + return len == 0 ? "" : encoding.GetString(dest); + } + + /// Converts a length-prefixed (aka Pascal string) ASCII byte array to a C# string + /// The corresponding C# string + /// A length-prefixed (aka Pascal string) ASCII byte array + public static string PascalToString(byte[] pascalString) => PascalToString(pascalString, Encoding.ASCII); + + /// Converts a length-prefixed (aka Pascal string) ASCII byte array to a C# string + /// The corresponding C# string + /// A length-prefixed (aka Pascal string) ASCII byte array + /// Encoding. + /// Start decoding at this position + public static string PascalToString(byte[] pascalString, Encoding encoding, int start = 0) + { + if(pascalString == null) + return null; + + byte length = pascalString[start]; + int len = 0; + + for(int i = start + 1; i < length + 1 && i < pascalString.Length; i++) + { + if(pascalString[i] == 0) + break; + + len++; + } + + byte[] dest = new byte[len]; + Array.Copy(pascalString, start + 1, dest, 0, len); + + return len == 0 ? "" : encoding.GetString(dest); + } + + /// Converts a space (' ', 0x20, ASCII SPACE) padded ASCII byte array to a C# string + /// The corresponding C# string + /// A space (' ', 0x20, ASCII SPACE) padded ASCII byte array + public static string SpacePaddedToString(byte[] spacePaddedString) => + SpacePaddedToString(spacePaddedString, Encoding.ASCII); + + /// Converts a space (' ', 0x20, ASCII SPACE) padded ASCII byte array to a C# string + /// The corresponding C# string + /// A space (' ', 0x20, ASCII SPACE) padded ASCII byte array + /// Encoding. + /// Start decoding at this position + public static string SpacePaddedToString(byte[] spacePaddedString, Encoding encoding, int start = 0) + { + if(spacePaddedString == null) + return null; + + int len = start; + + for(int i = spacePaddedString.Length; i >= start; i--) + { + if(i == start) + return ""; + + if(spacePaddedString[i - 1] == 0x20) + continue; + + len = i; + + break; + } + + return len == 0 ? "" : encoding.GetString(spacePaddedString, start, len); + } + + /// Converts an OSTA compressed unicode byte array to a C# string + /// The C# string. + /// OSTA compressed unicode byte array. + public static string DecompressUnicode(byte[] dstring) + { + ushort unicode; + byte compId = dstring[0]; + string temp = ""; + + if(compId != 8 && + compId != 16) + return null; + + for(int byteIndex = 1; byteIndex < dstring.Length;) + { + if(compId == 16) + unicode = (ushort)(dstring[byteIndex++] << 8); + else + unicode = 0; + + if(byteIndex < dstring.Length) + unicode |= dstring[byteIndex++]; + + if(unicode == 0) + break; + + temp += Encoding.Unicode.GetString(BitConverter.GetBytes(unicode)); + } + + return temp; + } + } +} \ No newline at end of file diff --git a/Aaru.Helpers/Swapping.cs b/Aaru.Helpers/Swapping.cs new file mode 100644 index 000000000..8d5e9ed3b --- /dev/null +++ b/Aaru.Helpers/Swapping.cs @@ -0,0 +1,112 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : Swapping.cs +// Author(s) : Natalia Portillo +// +// Component : Helpers. +// +// --[ Description ] ---------------------------------------------------------- +// +// Byte-swapping methods. +// +// --[ License ] -------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2023 Natalia Portillo +// ****************************************************************************/ + +using System.Runtime.CompilerServices; + +namespace Aaru.Helpers +{ + /// Helper operations to work with swapping endians + public static class Swapping + { + /// Gets the PDP endian equivalent of the given little endian unsigned integer + /// Little endian unsigned integer + /// PDP unsigned integer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint PDPFromLittleEndian(uint x) => ((x & 0xffff) << 16) | ((x & 0xffff0000) >> 16); + + /// Gets the PDP endian equivalent of the given big endian unsigned integer + /// Big endian unsigned integer + /// PDP unsigned integer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint PDPFromBigEndian(uint x) => ((x & 0xff00ff) << 8) | ((x & 0xff00ff00) >> 8); + + /// Swaps the endian of the specified unsigned short integer + /// Unsigned short integer + /// Swapped unsigned short integer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ushort Swap(ushort x) => (ushort)((x << 8) | (x >> 8)); + + /// Swaps the endian of the specified signed short integer + /// Signed short integer + /// Swapped signed short integer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static short Swap(short x) => (short)((x << 8) | ((x >> 8) & 0xFF)); + + /// Swaps the endian of the specified unsigned integer + /// Unsigned integer + /// Swapped unsigned integer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint Swap(uint x) + { + x = ((x << 8) & 0xFF00FF00) | ((x >> 8) & 0xFF00FF); + + return (x << 16) | (x >> 16); + } + + /// Swaps the endian of the specified signed integer + /// Signed integer + /// Swapped signed integer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Swap(int x) + { + x = (int)(((x << 8) & 0xFF00FF00) | (((uint)x >> 8) & 0xFF00FF)); + + return (int)(((uint)x << 16) | (((uint)x >> 16) & 0xFFFF)); + } + + /// Swaps the endian of the specified unsigned long integer + /// Unsigned long integer + /// Swapped unsigned long integer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ulong Swap(ulong x) + { + x = ((x & 0x00000000FFFFFFFF) << 32) | ((x & 0xFFFFFFFF00000000) >> 32); + x = ((x & 0x0000FFFF0000FFFF) << 16) | ((x & 0xFFFF0000FFFF0000) >> 16); + x = ((x & 0x00FF00FF00FF00FF) << 8) | ((x & 0xFF00FF00FF00FF00) >> 8); + + return x; + } + + /// Swaps the endian of the specified signed long integer + /// Signed long integer + /// Swapped signed long integer + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Swap(long x) + { + x = ((x & 0x00000000FFFFFFFF) << 32) | (long)(((ulong)x & 0xFFFFFFFF00000000) >> 32); + x = ((x & 0x0000FFFF0000FFFF) << 16) | (long)(((ulong)x & 0xFFFF0000FFFF0000) >> 16); + x = ((x & 0x00FF00FF00FF00FF) << 8) | (long)(((ulong)x & 0xFF00FF00FF00FF00) >> 8); + + return x; + } + } +} \ No newline at end of file diff --git a/CICMMetadata b/CICMMetadata deleted file mode 160000 index ec5031eff..000000000 --- a/CICMMetadata +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ec5031eff0536819f54f0c68907622895f8392ab diff --git a/CICMMetadata/.editorconfig b/CICMMetadata/.editorconfig new file mode 100644 index 000000000..7586c80d3 --- /dev/null +++ b/CICMMetadata/.editorconfig @@ -0,0 +1,631 @@ +[*] +charset = utf-8 +next_line = crlf +insert_final_newline = false +indent_style = space +indent_size = 4 + +# Generic non-language specific ones for Resharper and friends +brace_style = next_line +int_align = true +keep_existing_arrangement = false +place_simple_blocks_on_single_line = true +place_simple_declaration_blocks_on_single_line = true +place_attribute_on_same_line = false +space_after_unary_operator = false +space_after_comma = true +space_around_ternary_operator = true +space_around_binary_operator = true +space_around_member_access_operator = false +space_before_open_square_brackets = false +space_after_keywords_in_control_flow_statements = true +space_before_comma = false +space_between_method_call_name_and_opening_parenthesis = false +space_between_method_declaration_name_and_open_parenthesis = false +space_between_square_brackets = false +space_between_parentheses_of_control_flow_statements = false +accessor_owner_declaration_braces = next_line +accessor_declaration_braces = next_line +case_block_braces = next_line +initializer_braces = next_line +other_braces = next_line +allow_comment_after_lbrace = false +empty_block_style = together_same_line +braces_for_ifelse = not_required +braces_for_for = not_required +braces_for_foreach = not_required +braces_for_while = not_required +braces_for_dowhile = not_required +braces_for_using = not_required +braces_for_lock = not_required +braces_for_fixed = not_required +method_or_operator_body = expression_body +local_function_body = expression_body +constructor_or_destructor_body = expression_body +accessor_owner_body = expression_body +force_attribute_style = join +function_braces = next_line +force_control_statements_braces = always_remove +space_in_singleline_accessorholder = true +type_declaration_braces = next_line +invocable_declaration_braces = next_line +anonymous_method_declaration_braces = next_line +space_between_accessors_in_singleline_property = true +indent_nested_usings_stmt = true +space_within_empty_braces = false +indent_nested_fixed_stmt = true +indent_nested_lock_stmt = true +indent_nested_for_stmt = true +indent_nested_foreach_stmt = true +indent_nested_while_stmt = true +use_continuous_indent_inside_parens = true +indent_method_decl_pars = inside +indent_invocation_pars = inside +indent_statement_pars = inside +indent_typeparam_angles = inside +indent_typearg_angles = inside +indent_pars = inside +indent_preprocessor_if = outdent +indent_preprocessor_region = usual_indent +indent_preprocessor_other = usual_indent +indent_switch_labels = true +indent_type_constraints = true +stick_comment = false +alignment_tab_fill_style = use_spaces +align_multiline_parameter = true +align_multiline_extends_list = true +align_linq_query = true +align_multiline_binary_expressions_chain = true +outdent_binary_ops = true +align_multiline_calls_chain = true +outdent_dots = true +align_multiline_array_and_object_initializer = false +indent_anonymous_method_block = false +align_first_arg_by_paren = true +align_multiline_argument = true +align_tuple_components = true +align_multiline_expression = true +align_multiline_for_stmt = true +align_multiple_declaration = true +align_multline_type_parameter_list = true +align_multline_type_parameter_constrains = true +int_align_fields = true +int_align_properties = true +int_align_methods = true +int_align_parameters = false +int_align_variables = true +int_align_assignments = true +int_align_nested_ternary = true +int_align_invocations = false +int_align_binary_expressions = true +int_align_comments = true +int_align_switch_sections = true +keep_user_linebreaks = false +keep_existing_arrangement = false +keep_existing_linebreaks = false +max_line_length = 120 +wrap_before_comma = false +special_else_if_treatment = true +place_type_attribute_on_same_line = never +place_method_attribute_on_same_line = never +place_accessorholder_attribute_on_same_line = never +place_attribute_on_same_line = never +place_accessor_attribute_on_same_line = never +place_attribute_on_same_line = never +place_field_attribute_on_same_line = never +place_attribute_on_same_line = never +wrap_parameters_style = wrap_if_long +keep_existing_declaration_parens_arrangement = false +wrap_before_declaration_lpar = false +wrap_after_declaration_lpar = false +wrap_before_declaration_rpar = false +place_constructor_initializer_on_same_line = true +keep_existing_expr_member_arrangement = false +place_expr_method_on_single_line = true +place_expr_property_on_single_line = true +place_expr_accessor_on_single_line = true +wrap_before_arrow_with_expressions = false +place_type_constraints_on_same_line = true +wrap_before_first_type_parameter_constraint = true +wrap_multiple_type_parameter_constraints_style = wrap_if_long +wrap_before_type_parameter_langle = true +wrap_before_extends_colon = false +wrap_extends_list_style = wrap_if_long +keep_existing_declaration_block_arrangement = false +place_abstract_accessorholder_on_single_line = true +place_simple_accessorholder_on_single_line = false +place_accessor_with_attrs_holder_on_single_line = false +place_simple_accessor_on_single_line = true +place_simple_method_on_single_line = false +keep_existing_enum_arrangement = false +place_simple_enum_on_single_line = false +wrap_enum_declaration = wrap_if_long +new_line_before_else = true +new_line_before_while = false +wrap_for_stmt_header_style = wrap_if_long +wrap_multiple_declaration_style = wrap_if_long +keep_existing_embedded_arrangement = false +place_simple_embedded_statement_on_same_line = false +place_simple_case_statement_on_same_line = true +keep_existing_embedded_block_arrangement = false +place_simple_embedded_block_on_same_line = false +place_simple_anonymousmethod_on_single_line = false +keep_existing_initializer_arrangement = false +place_simple_initializer_on_single_line = false +wrap_object_and_collection_initializer_style = chop_always +wrap_array_initializer_style = wrap_if_long +wrap_arguments_style = wrap_if_long +keep_existing_invocation_parens_arrangement = false +wrap_after_invocation_lpar = false +wrap_before_invocation_rpar = false +wrap_after_dot_in_method_calls = true +wrap_chained_method_calls = wrap_if_long +wrap_before_binary_opsign = false +wrap_chained_binary_expressions = wrap_if_long +force_chop_compound_if_expression = true +force_chop_compound_while_expression = true +force_chop_compound_do_expression = true +wrap_before_ternary_opsigns = true +wrap_ternary_expr_style = wrap_if_long +nested_ternary_style = expanded +wrap_linq_expressions = wrap_if_long +wrap_before_linq_expression = false +place_linq_into_on_new_line = false +wrap_verbatim_interpolated_strings = wrap_if_long +extra_spaces = remove_all +space_after_keywords_in_control_flow_statements = false +space_between_method_call_name_and_opening_parenthesis = false +space_between_method_declaration_name_and_open_parenthesis = false +space_before_typeof_parentheses = false +space_before_checked_parentheses = false +space_before_sizeof_parentheses = false +space_before_nameof_parentheses = false +space_between_keyword_and_expression = true +space_between_keyword_and_type = true +space_around_assignment_op = true +space_around_logical_op = true +space_around_binary_operator = true +space_around_equality_op = true +space_around_relational_op = true +space_around_bitwise_op = true +space_around_additive_op = true +space_around_multiplicative_op = true +space_around_shift_op = true +space_around_nullcoalescing_op = true +space_around_arrow_op = false +space_after_logical_not_op = false +space_after_unary_operator = false +space_after_cast = false +space_around_dot = false +space_around_lambda_arrow = true +space_before_pointer_asterik_declaration = false +space_before_nullable_mark = false +blank_lines_around_class_definition = 1 +namespace_indentation = all +space_within_template_argument = false +align_union_type_usage = true +space_in_singleline_method = true +space_in_singleline_anonymous_method = true +space_within_single_line_array_initializer_braces = true +space_around_arrow_op = false + +# These are for markup languages (HTML, XML, etc) +spaces_around_eq_in_pi_attribute = false +space_after_last_pi_attribute = true +pi_attributes_indent = align_by_first_attribute +blank_line_after_pi = true +spaces_around_eq_in_attribute = false +space_after_last_attribute = false +space_before_self_closing = true +attribute_style = on_single_line +attribute_indent = align_by_first_attribute +sort_attributes = true +sort_class_selectors = true +max_blank_lines_between_tags = 0 +linebreak_before_all_elements = true +linebreak_before_multiline_elements = true +quote_style = doublequoted +delete_quotes_from_solid_values = false +normalize_tag_names = true + + +[{.babelrc,.stylelintrc,jest.config,.eslintrc,.prettierrc,*.json,*.jsb3,*.jsb2,*.bowerrc}] +indent_size = 2 + +[*.js.map] +indent_size = 2 + +[*.{css,scss}] +indent_size = 2 +declarations_style = separate_lines_for_nonsingle +media_query_style = separate_lines +selector_style = same_line +properties_style = separate_lines_for_nonsingle +brace_style = next_line + +[{.analysis_options,*.yml,*.yaml}] +indent_size = 2 + +# Xml project files +[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] +indent_size = 2 + +# Xml files +[*.{xml,stylecop,resx,ruleset}] +indent_size = 2 + +# Xml config files +[*.{props,targets,config,nuspec}] +indent_size = 2 + +# .net files +[*.{cs,vb}] +# These set the this. / Me. +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning + +# These make it suggest Int32 instead of int, etc. +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# This controls implicit access modifiers +dotnet_style_require_accessibility_modifiers = never:suggestion + +# Prefer non modified fields to be marked readonly +dotnet_style_readonly_field = true:warning + +# Parenthesis settings +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_operators = always_for_clarity:warning + +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:error +dotnet_style_prefer_inferred_tuple_names = true:warning +dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning +dotnet_style_prefer_conditional_expression_over_return = true:warning +dotnet_style_coalesce_expression = true:warning +dotnet_style_null_propagation = true:error + +dotnet_sort_system_directives_first = true + +# Constants in C style, all-caps +dotnet_naming_rule.constant_fields_caps.symbols = constant_fields +dotnet_naming_rule.constant_fields_caps.severity = warning +dotnet_naming_rule.constant_fields_caps.style = caps_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.required_modifiers = const +dotnet_naming_style.caps_style.capitalization = all_upper + +# interfaces should be prefixed with I +dotnet_naming_rule.pascal_case_for_interface.severity = error +dotnet_naming_rule.pascal_case_for_interface.symbols = interfaces_fields +dotnet_naming_rule.pascal_case_for_interface.style = pascal_case_interface_style +dotnet_naming_symbols.interfaces_fields.applicable_kinds = interface +dotnet_naming_style.pascal_case_interface_style.required_prefix = I +dotnet_naming_style.pascal_case_interface_style.capitalization = pascal_case + +## internal and private fields should be _camelCase +dotnet_naming_rule.camel_case_for_private_internal_fields.severity = warning +dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields +dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style +dotnet_naming_symbols.private_internal_fields.applicable_kinds = field +dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal +dotnet_naming_style.camel_case_underscore_style.required_prefix = _ +dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case + +# 2018-12-07 NP: This is not yet working in VS2017 +# local variables should be camelCase +#dotnet_naming_rule.camel_case_for_locals.severity = suggestion +#dotnet_naming_rule.camel_case_for_locals.symbols = local_fields +#dotnet_naming_rule.camel_case_for_locals.style = camel_case_style +#dotnet_naming_symbols.local_fields.applicable_kinds = local +#dotnet_naming_style.camel_case_style.capitalization = camel_case + +[*.cs] +# var var var +csharp_style_var_for_built_in_types = false:warning +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = false:warning + +csharp_style_expression_bodied_methods = when_on_single_line:suggestion +csharp_style_expression_bodied_constructors = when_on_single_line:suggestion +csharp_style_expression_bodied_operators = when_on_single_line:suggestion +csharp_style_expression_bodied_properties = when_on_single_line:suggestion +csharp_style_expression_bodied_indexers = when_on_single_line:suggestion +csharp_style_expression_bodied_accessors = when_on_single_line:suggestion + +csharp_style_pattern_matching_over_is_with_cast_check = true:warning +csharp_style_pattern_matching_over_as_with_null_check = when_on_single_line:warning + +csharp_style_inlined_variable_declaration = true:warning + +csharp_prefer_simple_default_expression = true:warning +csharp_style_deconstructed_variable_declaration = false:warning + +csharp_style_throw_expression = true:warning +csharp_style_conditional_delegate_call = true:warning + +csharp_prefer_braces = false + +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true + +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = flush_left + +csharp_space_after_cast = false +csharp_space_after_keywords_in_control_flow_statements = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = none +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false + +csharp_preserve_single_line_statements = false +csharp_preserve_single_line_blocks = true + +csharp_blank_lines_around_region = 0 +csharp_blank_lines_inside_region = 0 +csharp_blank_lines_before_single_line_comment = 1 +csharp_keep_blank_lines_in_declarations = 1 +csharp_remove_blank_lines_near_braces_in_declarations = true +csharp_blank_lines_after_start_comment = false +csharp_blank_lines_between_using_groups = 0 +csharp_blank_lines_after_using_list = 1 +csharp_blank_lines_around_namespace = 1 +csharp_blank_lines_inside_namespace = 0 +csharp_blank_lines_around_type = 1 +csharp_blank_lines_inside_type = 0 +csharp_blank_lines_around_field = 0 +csharp_blank_lines_around_single_line_field = 0 +csharp_blank_lines_around_property = 1 +csharp_blank_lines_around_single_line_property = 0 +csharp_blank_lines_around_auto_property = 0 +csharp_blank_lines_around_single_line_auto_property = 0 +csharp_blank_lines_around_invocable = 1 +csharp_blank_lines_around_single_line_invocable = 1 +csharp_keep_blank_lines_in_code = 1 +csharp_remove_blank_lines_near_braces_in_code = true +csharp_blank_lines_around_local_method = 1 +csharp_blank_lines_around_single_line_local_method = 1 +csharp_blank_lines_before_control_transfer_statements = 1 +csharp_blank_lines_after_control_transfer_statements = 1 +csharp_blank_lines_before_block_statements = 1 +csharp_blank_lines_after_block_statements = 1 +csharp_blank_lines_before_multiline_statements = 1 +csharp_blank_lines_after_multiline_statements = 1 + +csharp_type_declaration_braces = next_line +csharp_brace_style = next_line +csharp_indent_inside_namespace = true +csharp_invocable_declaration_braces = next_line +csharp_anonymous_method_declaration_braces = next_line +csharp_accessor_owner_declaration_braces = next_line +csharp_accessor_declaration_braces = next_line +csharp_case_block_braces = next_line +csharp_initializer_braces = next_line +csharp_other_braces = next_line +csharp_allow_comment_after_lbrace = false +csharp_empty_block_style = together_same_line + +csharp_for_built_in_types = use_explicit_type +csharp_for_simple_types = use_var_when_evident +csharp_for_other_types = use_explicit_type +csharp_prefer_separate_deconstructed_variables_declaration = true +csharp_prefer_explicit_discard_declaration = false + +csharp_instance_members_qualify_members = none +csharp_builtin_type_reference_style = use_keyword +csharp_prefer_qualified_reference = false +csharp_add_imports_to_deepest_scope = false +csharp_allow_alias = true +csharp_default_private_modifier = implicit +csharp_default_internal_modifier = implicit +csharp_arguments_literal = positional +csharp_arguments_string_literal = positional +csharp_arguments_named = positional +csharp_arguments_anonymous_function = positional +csharp_arguments_other = positional +csharp_braces_for_ifelse = not_required +csharp_braces_for_for = not_required +csharp_braces_for_foreach = not_required +csharp_braces_for_while = not_required +csharp_braces_for_dowhile = not_required +csharp_braces_for_using = not_required +csharp_braces_for_lock = not_required +csharp_braces_for_fixed = not_required +csharp_method_or_operator_body = expression_body +csharp_local_function_body = expression_body +csharp_constructor_or_destructor_body = expression_body +csharp_accessor_owner_body = expression_body +csharp_force_attribute_style = join +csharp_indent_nested_usings_stmt = true + +csharp_builtin_type_reference_for_member_access_style = use_keyword +csharp_indent_nested_fixed_stmt = true +csharp_indent_nested_lock_stmt = true +csharp_indent_nested_for_stmt = true +csharp_indent_nested_foreach_stmt = true +csharp_indent_nested_while_stmt = true +csharp_use_continuous_indent_inside_parens = true +csharp_indent_method_decl_pars = inside +csharp_indent_invocation_pars = inside +csharp_indent_statement_pars = inside +csharp_indent_typeparam_angles = inside +csharp_indent_typearg_angles = inside +csharp_indent_pars = inside +csharp_indent_preprocessor_if = outdent +csharp_indent_preprocessor_region = usual_indent +csharp_indent_preprocessor_other = usual_indent +csharp_indent_switch_labels = true +csharp_indent_type_constraints = true +csharp_stick_comment = false +csharp_alignment_tab_fill_style = use_spaces +csharp_align_multiline_parameter = true +csharp_align_multiline_extends_list = true +csharp_align_linq_query = true +csharp_align_multiline_binary_expressions_chain = true +csharp_outdent_binary_ops = true +csharp_align_multiline_calls_chain = true +csharp_outdent_dots = true +csharp_align_multiline_array_and_object_initializer = false +csharp_indent_anonymous_method_block = false +csharp_align_first_arg_by_paren = true +csharp_align_multiline_argument = true +csharp_align_tuple_components = true +csharp_align_multiline_expression = true +csharp_align_multiline_for_stmt = true +csharp_align_multiple_declaration = true +csharp_align_multline_type_parameter_list = true +csharp_align_multline_type_parameter_constrains = true +csharp_int_align_fields = true +csharp_int_align_properties = true +csharp_int_align_methods = true +csharp_int_align_parameters = false +csharp_int_align_variables = true +csharp_int_align_assignments = true +csharp_int_align_nested_ternary = true +csharp_int_align_invocations = false +csharp_int_align_binary_expressions = true +csharp_int_align_comments = true +csharp_int_align_switch_sections = true +csharp_int_align = true +csharp_keep_user_linebreaks = false +csharp_keep_existing_arrangement = false +csharp_keep_existing_linebreaks = false +csharp_max_line_length = 120 +csharp_wrap_before_comma = false +csharp_special_else_if_treatment = true +csharp_insert_final_newline = false +csharp_place_type_attribute_on_same_line = never +csharp_place_method_attribute_on_same_line = never +csharp_place_accessorholder_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_place_accessor_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_place_field_attribute_on_same_line = never +csharp_place_attribute_on_same_line = never +csharp_wrap_parameters_style = wrap_if_long +csharp_keep_existing_declaration_parens_arrangement = false +csharp_wrap_before_declaration_lpar = false +csharp_wrap_after_declaration_lpar = false +csharp_wrap_before_declaration_rpar = false +csharp_place_constructor_initializer_on_same_line = true +csharp_keep_existing_expr_member_arrangement = false +csharp_place_expr_method_on_single_line = true +csharp_place_expr_property_on_single_line = true +csharp_place_expr_accessor_on_single_line = true +csharp_wrap_before_arrow_with_expressions = false +csharp_place_type_constraints_on_same_line = true +csharp_wrap_before_first_type_parameter_constraint = true +csharp_wrap_multiple_type_parameter_constraints_style = wrap_if_long +csharp_wrap_before_type_parameter_langle = true +csharp_wrap_before_extends_colon = false +csharp_wrap_extends_list_style = wrap_if_long +csharp_keep_existing_declaration_block_arrangement = false +csharp_place_abstract_accessorholder_on_single_line = true +csharp_place_simple_accessorholder_on_single_line = false +csharp_place_accessor_with_attrs_holder_on_single_line = false +csharp_place_simple_accessor_on_single_line = true +csharp_place_simple_method_on_single_line = false +csharp_keep_existing_enum_arrangement = false +csharp_place_simple_enum_on_single_line = false +csharp_wrap_enum_declaration = wrap_if_long +csharp_new_line_before_else = true +csharp_new_line_before_while = false +csharp_wrap_for_stmt_header_style = wrap_if_long +csharp_wrap_multiple_declaration_style = wrap_if_long +csharp_keep_existing_embedded_arrangement = false +csharp_place_simple_embedded_statement_on_same_line = false +csharp_place_simple_case_statement_on_same_line = true +csharp_keep_existing_embedded_block_arrangement = false +csharp_place_simple_embedded_block_on_same_line = false +csharp_place_simple_anonymousmethod_on_single_line = false +csharp_keep_existing_initializer_arrangement = false +csharp_place_simple_initializer_on_single_line = false +csharp_wrap_object_and_collection_initializer_style = chop_always +csharp_wrap_array_initializer_style = wrap_if_long +csharp_wrap_arguments_style = wrap_if_long +csharp_keep_existing_invocation_parens_arrangement = false +csharp_wrap_after_invocation_lpar = false +csharp_wrap_before_invocation_rpar = false +csharp_wrap_after_dot_in_method_calls = true +csharp_wrap_chained_method_calls = wrap_if_long +csharp_wrap_before_binary_opsign = false +csharp_wrap_chained_binary_expressions = wrap_if_long +csharp_force_chop_compound_if_expression = true +csharp_force_chop_compound_while_expression = true +csharp_force_chop_compound_do_expression = true +csharp_wrap_before_ternary_opsigns = true +csharp_wrap_ternary_expr_style = wrap_if_long +csharp_nested_ternary_style = expanded +csharp_wrap_linq_expressions = wrap_if_long +csharp_wrap_before_linq_expression = false +csharp_place_linq_into_on_new_line = false +csharp_wrap_verbatim_interpolated_strings = wrap_if_long +csharp_extra_spaces = remove_all +csharp_space_after_keywords_in_control_flow_statements = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_before_typeof_parentheses = false +csharp_space_before_checked_parentheses = false +csharp_space_before_sizeof_parentheses = false +csharp_space_before_nameof_parentheses = false +csharp_space_between_keyword_and_expression = true +csharp_space_between_keyword_and_type = true +csharp_space_around_assignment_op = true +csharp_space_around_logical_op = true +csharp_space_around_binary_operator = true +csharp_space_around_equality_op = true +csharp_space_around_relational_op = true +csharp_space_around_bitwise_op = true +csharp_space_around_additive_op = true +csharp_space_around_multiplicative_op = true +csharp_space_around_shift_op = true +csharp_space_around_nullcoalescing_op = true +csharp_space_around_arrow_op = false +csharp_space_after_logical_not_op = false +csharp_space_after_unary_operator = false +csharp_space_after_cast = false +csharp_space_around_dot = false +csharp_space_around_lambda_arrow = true +csharp_space_before_pointer_asterik_declaration = false +csharp_space_before_nullable_mark = false +csharp_style_namespace_declarations = file_scoped:warning + +[*.cshtml] +linebreaks_around_razor_statements = true +blank_lines_around_razor_functions = true +blank_lines_around_razor_helpers = true +blank_lines_around_razor_sections = true + +# C++ +[*.{cc,cpp,cxx,h,hpp,hxx}] +cpp_indent_access_specifiers_from_class = true +cpp_indent_wrapped_function_names = false +cpp_align_multiline_type_argument = true + +# C, C++ and ObjectiveC +[*.{c,h,cc,cpp,cxx,m,hpp,hxx}] +indent_preprocessor_directives = normal +indent_type_constraints = true + +# Javascript and Typescript +[*.{js,js.map,ts}] +quote_style = doublequoted +termination_style = ensure_semicolon diff --git a/CICMMetadata/.externalToolBuilders/New_Builder.launch b/CICMMetadata/.externalToolBuilders/New_Builder.launch new file mode 100644 index 000000000..9ca5b2ef3 --- /dev/null +++ b/CICMMetadata/.externalToolBuilders/New_Builder.launch @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/CICMMetadata/.gitignore b/CICMMetadata/.gitignore new file mode 100644 index 000000000..09ecec446 --- /dev/null +++ b/CICMMetadata/.gitignore @@ -0,0 +1,597 @@ +### VisualStudio template +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ +### Linux template + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* +### Xcode template +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +### VisualStudioCode template +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +### C++ template +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o + +# Precompiled Headers +*.gch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +### MonoDevelop template +#User Specific +*.usertasks + +#Mono Project Files +*.resources +test-results/ +### GPG template +secring.* + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests +### CMake template +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +### C template +# Object files +*.ko +*.elf + +# Linker output +*.map +*.exp + +*.so.* + +# Executables +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf +### Windows template +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# NuGet Packages Directory +packages/ +## TODO: If the tool you use requires repositories.config uncomment the next line +#!packages/repositories.config + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +# This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented) +!packages/build/ + + +# Others +sql/ +*.Cache + +# Visual Studio 2017 +.vs + +workspace.xml +cmake-build-debug +### macOS template +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +pkg/**/pkg +pkg/**/src +pkg/**/*.asc +pkg/**/*.sig +pkg/**/*.tar.xz +pkg/**/*.zip +pkg/**/aaru + +.sonarqube + +build/* \ No newline at end of file diff --git a/CICMMetadata/.project b/CICMMetadata/.project new file mode 100644 index 000000000..9b6a5c893 --- /dev/null +++ b/CICMMetadata/.project @@ -0,0 +1,21 @@ + + + CICMMetadata + + + + + + org.eclipse.ui.externaltools.ExternalToolBuilder + full,incremental, + + + LaunchConfigHandle + <project>/.externalToolBuilders/New_Builder.launch + + + + + + + diff --git a/CICMMetadata/.settings/org.eclipse.wst.xsl.core.prefs b/CICMMetadata/.settings/org.eclipse.wst.xsl.core.prefs new file mode 100644 index 000000000..e28962cde --- /dev/null +++ b/CICMMetadata/.settings/org.eclipse.wst.xsl.core.prefs @@ -0,0 +1,11 @@ +CHECK_CALL_TEMPLATES=2 +CHECK_XPATHS=2 +CIRCULAR_REF=2 +DUPLICATE_PARAMETER=2 +EMPTY_PARAM=1 +MISSING_INCLUDE=2 +MISSING_PARAM=1 +NAME_ATTRIBUTE_EMPTY=2 +NAME_ATTRIBUTE_MISSING=2 +TEMPLATE_CONFLICT=2 +eclipse.preferences.version=1 diff --git a/CICMMetadata/CICMMetadata.iml b/CICMMetadata/CICMMetadata.iml new file mode 100644 index 000000000..48426fcce --- /dev/null +++ b/CICMMetadata/CICMMetadata.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/CICMMetadata/CICMMetadataEditor.sln b/CICMMetadata/CICMMetadataEditor.sln new file mode 100644 index 000000000..fea96170c --- /dev/null +++ b/CICMMetadata/CICMMetadataEditor.sln @@ -0,0 +1,29 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CICMMetadataEditor", "CICMMetadataEditor\CICMMetadataEditor\CICMMetadataEditor.csproj", "{189CFDC5-2630-46DE-A934-FF182F9F54AB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CICMMetadataEditor.Desktop", "CICMMetadataEditor\CICMMetadataEditor.Desktop\CICMMetadataEditor.Desktop.csproj", "{4D52B7A6-E945-4BDD-BAD3-0EB9A48FABB4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CICMMetadataEditor.XamMac", "CICMMetadataEditor\CICMMetadataEditor.XamMac\CICMMetadataEditor.XamMac.csproj", "{00CE3E32-7D00-4CB0-8951-3C27BF2D02CD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {189CFDC5-2630-46DE-A934-FF182F9F54AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {189CFDC5-2630-46DE-A934-FF182F9F54AB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {189CFDC5-2630-46DE-A934-FF182F9F54AB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {189CFDC5-2630-46DE-A934-FF182F9F54AB}.Release|Any CPU.Build.0 = Release|Any CPU + {4D52B7A6-E945-4BDD-BAD3-0EB9A48FABB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4D52B7A6-E945-4BDD-BAD3-0EB9A48FABB4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4D52B7A6-E945-4BDD-BAD3-0EB9A48FABB4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4D52B7A6-E945-4BDD-BAD3-0EB9A48FABB4}.Release|Any CPU.Build.0 = Release|Any CPU + {00CE3E32-7D00-4CB0-8951-3C27BF2D02CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {00CE3E32-7D00-4CB0-8951-3C27BF2D02CD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {00CE3E32-7D00-4CB0-8951-3C27BF2D02CD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {00CE3E32-7D00-4CB0-8951-3C27BF2D02CD}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.Desktop/CICMMetadataEditor.Desktop.csproj b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.Desktop/CICMMetadataEditor.Desktop.csproj new file mode 100644 index 000000000..05fddc8be --- /dev/null +++ b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.Desktop/CICMMetadataEditor.Desktop.csproj @@ -0,0 +1,20 @@ + + + WinExe + net461 + + + + + + + + + + + + LICENSE + Always + + + \ No newline at end of file diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.Desktop/Info.plist b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.Desktop/Info.plist new file mode 100644 index 000000000..f307f6e7d --- /dev/null +++ b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.Desktop/Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleName + CICMMetadataEditor + CFBundleIdentifier + com.example.CICMMetadataEditor + CFBundleShortVersionString + 1.0 + LSMinimumSystemVersion + 10.7 + CFBundleDevelopmentRegion + en + NSHumanReadableCopyright + + CFBundleIconFile + MacIcon.icns + + diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.Desktop/MacIcon.icns b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.Desktop/MacIcon.icns new file mode 100755 index 0000000000000000000000000000000000000000..8f385bb4a566b103508f8e67794100af1354a65c GIT binary patch literal 114177 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

_xJ5xY4e=C?^i2tFTK5P<-I5CRJQvn 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 SL>L$t7(8A5T-G@yGywpmy?smo literal 0 HcmV?d00001 diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-128@2x.png b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-128@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f4c8d29047b85e28ae6929073e0e6e7ad07633c9 GIT binary patch literal 20798 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 J%Q~loCIB^EXWRe) literal 0 HcmV?d00001 diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-16.png b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-16.png new file mode 100644 index 0000000000000000000000000000000000000000..ebb5a0fe4e7e4ac7ed527449ad2c0e9848b0389a GIT binary patch literal 711 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRd4mJh`2Kmqb6B!s77>k44ofy`glX=O&z|`pJ z;uvBf*gE;FpKzea@&Cqer#NK_t_<+;WnSCcd*K1QPRYYVM_O81FZNCpe{pC>;o`Oy zb_1_R%sUJY{$Nm3J2qj$fhLy?W{VbHZ8>&@Nw?&ep|f@I^6SOX%QiJlp0o4$y#D($ ztDo@|Y_ib2UF+GyRsE=droJ zGm+SwY!D%wKW+Pj@aW^YKT|!MqMrF1{;gt_mp6Z7{viI^wSBupW?xUM`8TgwbLU0z zxlQUutlwX#Jh@O>agOikh2!tL*YG7278*V-(>z)nR)bI6(Rs-n?IuE-PiFoyS)ttFSav3K2~oIXL^@oym{B{clYKszSy$&SK`u`TlMW< zw_EU~Ths zaSVyz+!`L89}+4OmwxWdoSnwTx^E{$xoJ#S(poB{lGG$%vgk+)`vvwmEknDH>=hS} zEOAl%@MgA3!h|*n;pFB{w>2RgjL~{i#nPjy65mZPdzXH0&f}<}_qUL$ z#G1v|Z?}I|)vZ6W;pQS|SGJN*PduMbRCX`hQfXs--D0k7Soc@a%_py%{JcjsUgy=3 zMJ$z5)~GnI-kqv^i&G;~S3#F)>ITVk^X>0%Oh11wu6%X&^0RsO6Sv+li$0^~?>ViN ziAh97WKHr-CXr{x3p7p{@${d5mo@9a_waRZtT+5WU~aZLwK+i~W|7KENr6VuZh^iVA zhS9~dSbFuhDBh?8|C-sWw?518@oliK{+7Le-gD8FD%UT^f3y%Ru)MqbLV)qZt1MHZ zx91&A-5C;N=*7&e^q|Z#-dQxx+t;_@nK3svci_PVQ)fp#J1?)y#MhoIoF%n&OE#y- zqKh}CEQq&dnsFjwYt-#ostWCg7PhaJWQ;Oh{!1|tIlgSD3nwe3G_ofleLCKPo?r1811!&07UmCW&{ zeV-P#`YI*FZ%)&mrEAR@rO{fUWSMMYvd1;trBT*(_uHjuoE{GYUR=z2*4Q(BietV( zwT;{^(di;5~!%xTNcVAv!zFS*c zE4X!%7~|7tA3oT>um7+xYJJ}Bj_=3%w=X~N;2q2NU11szvr_j=_4N9&&}wS$q4Mj; zAME|AzrVAu?aH}nsj7ZOYLidyp5XQS*mI{S%SGGTKtisx&i%bEZe%7o~=!%qGesp~jmx1*811CzD9$n)Na43k< ztxOBbOqM-0MIr5N%gK~N>6$NBr=`nHi#z`6V~x>F4ihhzU7Iw&H0@?qa+QmB?oK@J zw$%6J@e>Q4zck@L6t!Ns=b8V*x%#W4*NZYLDX}>##w#;j|IgcWLNXyJk5%&Uxo1P}Q81tqXWeVu1^UM(ZrGA1(DmdVRPU`KpEgXKO$!ImAV%ug7%3Ei`5p-%b6~E>g+u~b_=EN4Dt7TG(Jau zOP)W`(K}LfYL{|dkp<664!NU@W+BrLym*n}qjz%AHOmVxOA0E!iwQiD*=pi9L5!al z@ErRlzu2)x z;qj_-g?*x~XWA7d|A?i@s}&}k+!NNPJ8R?hZdq$T5hk?*OkAq` xmMgDZS(fr`!HmGH+DkS!*#cKBJZ`4_pZQJAuGL{zZ-Yu{22WQ%mvv4FO#o%3uXX?c literal 0 HcmV?d00001 diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-256.png b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-256.png new file mode 100644 index 0000000000000000000000000000000000000000..f4c8d29047b85e28ae6929073e0e6e7ad07633c9 GIT binary patch literal 20798 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 J%Q~loCIB^EXWRe) literal 0 HcmV?d00001 diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-256@2x.png b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-256@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a142c83fb1c390d168ade09b98f6108ae5083f44 GIT binary patch literal 59335 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 literal 0 HcmV?d00001 diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-32.png b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-32.png new file mode 100644 index 0000000000000000000000000000000000000000..0986d31bebb1199716226839d289d54925f9319c GIT binary patch literal 1484 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}jKx9jP7LeL$-HD>U~Ths zaSVyz+!`L89}+4OmwxWdoSnwTx^E{$xoJ#S(poB{lGG$%vgk+)`vvwmEknDH>=hS} zEOAl%@MgA3!h|*n;pFB{w>2RgjL~{i#nPjy65mZPdzXH0&f}<}_qUL$ z#G1v|Z?}I|)vZ6W;pQS|SGJN*PduMbRCX`hQfXs--D0k7Soc@a%_py%{JcjsUgy=3 zMJ$z5)~GnI-kqv^i&G;~S3#F)>ITVk^X>0%Oh11wu6%X&^0RsO6Sv+li$0^~?>ViN ziAh97WKHr-CXr{x3p7p{@${d5mo@9a_waRZtT+5WU~aZLwK+i~W|7KENr6VuZh^iVA zhS9~dSbFuhDBh?8|C-sWw?518@oliK{+7Le-gD8FD%UT^f3y%Ru)MqbLV)qZt1MHZ zx91&A-5C;N=*7&e^q|Z#-dQxx+t;_@nK3svci_PVQ)fp#J1?)y#MhoIoF%n&OE#y- zqKh}CEQq&dnsFjwYt-#ostWCg7PhaJWQ;Oh{!1|tIlgSD3nwe3G_ofleLCKPo?r1811!&07UmCW&{ zeV-P#`YI*FZ%)&mrEAR@rO{fUWSMMYvd1;trBT*(_uHjuoE{GYUR=z2*4Q(BietV( zwT;{^(di;5~!%xTNcVAv!zFS*c zE4X!%7~|7tA3oT>um7+xYJJ}Bj_=3%w=X~N;2q2NU11szvr_j=_4N9&&}wS$q4Mj; zAME|AzrVAu?aH}nsj7ZOYLidyp5XQS*mI{S%SGGTKtisx&i%bEZe%7o~=!%qGesp~jmx1*811CzD9$n)Na43k< ztxOBbOqM-0MIr5N%gK~N>6$NBr=`nHi#z`6V~x>F4ihhzU7Iw&H0@?qa+QmB?oK@J zw$%6J@e>Q4zck@L6t!Ns=b8V*x%#W4*NZYLDX}>##w#;j|IgcWLNXyJk5%&Uxo1P}Q81tqXWeVu1^UM(ZrGA1(DmdVRPU`KpEgXKO$!ImAV%ug7%3Ei`5p-%b6~E>g+u~b_=EN4Dt7TG(Jau zOP)W`(K}LfYL{|dkp<664!NU@W+BrLym*n}qjz%AHOmVxOA0E!iwQiD*=pi9L5!al z@ErRlzu2)x z;qj_-g?*x~XWA7d|A?i@s}&}k+!NNPJ8R?hZdq$T5hk?*OkAq` xmMgDZS(fr`!HmGH+DkS!*#cKBJZ`4_pZQJAuGL{zZ-Yu{22WQ%mvv4FO#o%3uXX?c literal 0 HcmV?d00001 diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-32@2x.png b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-32@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..412d6ca9b42cc0776ffd2cf3a35c3ace3a337e50 GIT binary patch literal 3428 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 literal 0 HcmV?d00001 diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e99022ae84d056ebf09328dcdd69a44b8ff8c74d GIT binary patch literal 177632 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 &28mIrFBuGvk3(D?R!0SZ1&o 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

v$o4*X6eW`DX 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 FCIAfJ$iM&q literal 0 HcmV?d00001 diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/Contents.json b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..6b2854529 --- /dev/null +++ b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images": [ + { + "filename": "AppIcon-16.png", + "size": "16x16", + "scale": "1x", + "idiom": "mac" + }, + { + "filename": "AppIcon-16@2x.png", + "size": "16x16", + "scale": "2x", + "idiom": "mac" + }, + { + "filename": "AppIcon-32.png", + "size": "32x32", + "scale": "1x", + "idiom": "mac" + }, + { + "filename": "AppIcon-32@2x.png", + "size": "32x32", + "scale": "2x", + "idiom": "mac" + }, + { + "filename": "AppIcon-128.png", + "size": "128x128", + "scale": "1x", + "idiom": "mac" + }, + { + "filename": "AppIcon-128@2x.png", + "size": "128x128", + "scale": "2x", + "idiom": "mac" + }, + { + "filename": "AppIcon-256.png", + "size": "256x256", + "scale": "1x", + "idiom": "mac" + }, + { + "filename": "AppIcon-256@2x.png", + "size": "256x256", + "scale": "2x", + "idiom": "mac" + }, + { + "filename": "AppIcon-512.png", + "size": "512x512", + "scale": "1x", + "idiom": "mac" + }, + { + "filename": "AppIcon-512@2x.png", + "size": "512x512", + "scale": "2x", + "idiom": "mac" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} \ No newline at end of file diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/Contents.json b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/Contents.json new file mode 100644 index 000000000..033a61844 --- /dev/null +++ b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info": { + "version": 1, + "author": "xcode" + } +} \ No newline at end of file diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/CICMMetadataEditor.XamMac.csproj b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/CICMMetadataEditor.XamMac.csproj new file mode 100644 index 000000000..66ae0338c --- /dev/null +++ b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/CICMMetadataEditor.XamMac.csproj @@ -0,0 +1,99 @@ + + + + Debug + AnyCPU + {00CE3E32-7D00-4CB0-8951-3C27BF2D02CD} + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + CICMMetadataEditor.XamMac + CICMMetadataEditor.XamMac + v2.0 + Xamarin.Mac + Resources + + + true + portable + false + bin\Debug + DEBUG; + prompt + 4 + false + Mac Developer + false + false + false + true + true + HttpClientHandler + None + + + + + false + + + true + bin\Release + + + prompt + 4 + false + true + false + true + true + true + SdkOnly + HttpClientHandler + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {189CFDC5-2630-46DE-A934-FF182F9F54AB} + CICMMetadataEditor + + + + + 2.4.1 + + + + + LICENSE + Always + + + + \ No newline at end of file diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Info.plist b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Info.plist new file mode 100644 index 000000000..3c15930d3 --- /dev/null +++ b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleName + EtoApp + CFBundleIdentifier + com.example.EtoApp + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.7 + CFBundleDevelopmentRegion + en + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + APPL + CFBundleSignature + ???? + NSHumanReadableCopyright + + NSPrincipalClass + NSApplication + XSAppIconAssets + Assets.xcassets/AppIcon.appiconset + + diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Program.cs b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Program.cs new file mode 100644 index 000000000..2b6f66190 --- /dev/null +++ b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor.XamMac/Program.cs @@ -0,0 +1,43 @@ +// +// Author: +// Natalia Portillo claunia@claunia.com +// +// Copyright (c) 2017-2018, © Natalia Portillo +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +// following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this list of conditions and the +// following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +// following disclaimer in the documentation and/or other materials provided with the distribution. +// * Neither the name of the [ORGANIZATION] nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +using AppKit; +using Eto.Forms; + +namespace CICMMetadataEditor.XamMac +{ + static class MainClass + { + static void Main(string[] args) + { + new Application(Eto.Platforms.XamMac2).Run(new dlgMetadata()); + } + } +} diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/CICMMetadataEditor.csproj b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/CICMMetadataEditor.csproj new file mode 100644 index 000000000..ad10a776b --- /dev/null +++ b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/CICMMetadataEditor.csproj @@ -0,0 +1,34 @@ + + + netstandard1.6 + CICMMetadataEditor + 1.0 + CICMMetadataEditor + Copyright © 2018 + Description of CICMMetadataEditor + + + + + + + + + + cicm.xsd + Always + + + cicm.xml + + + LICENSE + Always + + + + + cicm.cs + + + \ No newline at end of file diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/WrappersForEto.cs b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/WrappersForEto.cs new file mode 100644 index 000000000..2a9ae6743 --- /dev/null +++ b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/WrappersForEto.cs @@ -0,0 +1,64 @@ +// +// Author: +// Natalia Portillo claunia@claunia.com +// +// Copyright (c) 2017-2018, © Natalia Portillo +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +// following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this list of conditions and the +// following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +// following disclaimer in the documentation and/or other materials provided with the distribution. +// * Neither the name of the [ORGANIZATION] nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +using Schemas; + +namespace CICMMetadataEditor +{ + class StringEntry + { + public string str { get; set; } + } + + class BarcodeEntry + { + public string code { get; set; } + public BarcodeTypeType type { get; set; } + } + + class DiscEntry + { + public string path { get; set; } + public OpticalDiscType disc { get; set; } + } + + class DiskEntry + { + public string path { get; set; } + public BlockMediaType disk { get; set; } + } + + class TargetOsEntry + { + public string name { get; set; } + public string version { get; set; } + } +} \ No newline at end of file diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgBlockMedia.xeto b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgBlockMedia.xeto new file mode 100644 index 000000000..9ec79d2a3 --- /dev/null +++ b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgBlockMedia.xeto @@ -0,0 +1,678 @@ + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sequenced + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Known dimensions + + + + Round? + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Has ATA IDENTIFY information? + + + + + + + + Is PCI? + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Is PCMCIA? + Has CIS? + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Is Secure Digital or MMC? + + + + + + + Has CSD? + + + + Has Extended CSD? + + + + + + + + Is SCSI? + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Is USB? + + + + + + + + + + + + + + + + + + + + + + + + + + Has MAM? + + + + + + + + Has tracks? + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Known dumping + hardware + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgBlockMedia.xeto.cs b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgBlockMedia.xeto.cs new file mode 100644 index 000000000..904d13cef --- /dev/null +++ b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgBlockMedia.xeto.cs @@ -0,0 +1,1769 @@ +// +// Author: +// Natalia Portillo claunia@claunia.com +// +// Copyright (c) 2017-2018, © Natalia Portillo +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +// following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this list of conditions and the +// following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +// following disclaimer in the documentation and/or other materials provided with the distribution. +// * Neither the name of the [ORGANIZATION] nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using Eto.Forms; +using Eto.Serialization.Xaml; +using Schemas; + +namespace CICMMetadataEditor +{ + public class dlgBlockMedia : Dialog + { + ChecksumType[] checksums; + ChecksumType[] contentChks; + DumpHardwareType dumpHwIter; + bool editingDumpHw; + bool editingPartition; + FileSystemType filesystemIter; + ObservableCollection lstAdditionalInformation; + ObservableCollection lstAta; + ObservableCollection lstCID; + ObservableCollection lstCSD; + ObservableCollection lstDumpHw; + ObservableCollection lstECSD; + ObservableCollection lstEVPDs; + ObservableCollection lstInquiry; + ObservableCollection lstLogSense; + ObservableCollection lstMAM; + ObservableCollection lstModeSense; + ObservableCollection lstModeSense10; + ObservableCollection lstPartitions; + ObservableCollection lstPCIConfiguration; + ObservableCollection lstPCIOptionROM; + ObservableCollection lstPCMCIACIS; + ObservableCollection lstTracks; + ObservableCollection lstUSBDescriptors; + public BlockMediaType Metadata; + public bool Modified; + PartitionType partitionIter; + ScansType scans; + TapePartitionType[] tapeInformation; + BlockSizeType[] variableBlockSize; + + public dlgBlockMedia() + { + XamlReader.Load(this); + + Modified = false; + + #region Set partitions table + lstPartitions = new ObservableCollection(); + + treePartitions.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Sequence).Convert(v => v.ToString()) + }, + HeaderText = "Sequence" + }); + treePartitions.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.StartSector).Convert(v => v.ToString()) + }, + HeaderText = "Start" + }); + treePartitions.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.EndSector).Convert(v => v.ToString()) + }, + HeaderText = "End" + }); + treePartitions.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Type)}, + HeaderText = "Type" + }); + treePartitions.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Name)}, + HeaderText = "Name" + }); + treePartitions.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Description)}, + HeaderText = "Description" + }); + + treePartitions.DataStore = lstPartitions; + + treePartitions.AllowMultipleSelection = false; + #endregion Set partitions table + + #region Set filesystems table + treeFilesystems.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Type)}, + HeaderText = "Type" + }); + treeFilesystems.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.VolumeName)}, + HeaderText = "Name" + }); + + treeFilesystems.AllowMultipleSelection = false; + #endregion Set filesystems table + + #region Set dump hardware table + lstDumpHw = new ObservableCollection(); + + treeDumpHardware.Columns.Add(new GridColumn + { + DataCell = + new TextBoxCell {Binding = Binding.Property(r => r.Manufacturer)}, + HeaderText = "Manufacturer" + }); + treeDumpHardware.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Model)}, + HeaderText = "Model" + }); + treeDumpHardware.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Revision)}, + HeaderText = "Revision" + }); + treeDumpHardware.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Firmware)}, + HeaderText = "Firmware" + }); + treeDumpHardware.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Serial)}, + HeaderText = "Serial" + }); + treeDumpHardware.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Software).Convert(v => v?.Name) + }, + HeaderText = "Software" + }); + treeDumpHardware.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Software).Convert(v => v?.Version) + }, + HeaderText = "Version" + }); + treeDumpHardware.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Software) + .Convert(v => v?.OperatingSystem) + }, + HeaderText = "Operating system" + }); + + treeDumpHardware.DataStore = lstDumpHw; + + treeDumpHardware.AllowMultipleSelection = false; + + treeExtents.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Start).Convert(v => v.ToString()) + }, + HeaderText = "Start" + }); + treeExtents.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.End).Convert(v => v.ToString()) + }, + HeaderText = "End" + }); + #endregion Set dump hardware table + + #region Set ATA IDENTIFY table + lstAta = new ObservableCollection(); + treeATA.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeATA.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeATA.DataStore = lstAta; + #endregion Set ATA IDENTIFY table + + #region Set PCI configuration table + lstPCIConfiguration = new ObservableCollection(); + treeConfiguration.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeConfiguration.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeConfiguration.DataStore = lstPCIConfiguration; + #endregion Set PCI configuration table + + #region Set PCMCIA CIS table + lstPCMCIACIS = new ObservableCollection(); + treeCIS.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeCIS.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeCIS.DataStore = lstPCMCIACIS; + #endregion Set PCI option ROM table + + #region Set CID table + lstCID = new ObservableCollection(); + treeCID.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeCID.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeCID.DataStore = lstCID; + #endregion Set CID table + + #region Set CSD table + lstCSD = new ObservableCollection(); + treeCSD.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeCSD.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeCSD.DataStore = lstCSD; + #endregion Set CSD table + + #region Set Extended CSD table + lstECSD = new ObservableCollection(); + treeECSD.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeECSD.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeECSD.DataStore = lstECSD; + #endregion Set Extended CSD table + + #region Set SCSI INQUIRY table + lstInquiry = new ObservableCollection(); + treeInquiry.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeInquiry.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeInquiry.DataStore = lstInquiry; + #endregion Set SCSI INQUIRY table + + #region Set SCSI MODE SENSE table + lstModeSense = new ObservableCollection(); + treeModeSense.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeModeSense.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeModeSense.DataStore = lstModeSense; + #endregion Set SCSI MODE SENSE table + + #region Set SCSI MODE SENSE (10) table + lstModeSense10 = new ObservableCollection(); + treeModeSense10.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeModeSense10.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeModeSense10.DataStore = lstModeSense10; + #endregion Set SCSI MODE SENSE (10) table + + #region Set SCSI LOG SENSE table + lstLogSense = new ObservableCollection(); + treeLogSense.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeLogSense.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeLogSense.DataStore = lstLogSense; + #endregion Set SCSI MODE SENSE (10) table + + #region Set SCSI EVPDs table + lstEVPDs = new ObservableCollection(); + + treeEVPDs.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.page).Convert(v => v.ToString()) + }, + HeaderText = "Page" + }); + treeEVPDs.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeEVPDs.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + + treeEVPDs.DataStore = lstEVPDs; + + treeEVPDs.AllowMultipleSelection = false; + #endregion Set SCSI EVPDs table + + #region Set USB descriptors table + lstUSBDescriptors = new ObservableCollection(); + treeDescriptors.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeDescriptors.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeDescriptors.DataStore = lstUSBDescriptors; + #endregion Set USB descriptors table + + #region Set MAM table + lstMAM = new ObservableCollection(); + treeMAM.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeMAM.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeMAM.DataStore = lstMAM; + #endregion Set MAM table + + #region Set Option ROM table + lstPCIOptionROM = new ObservableCollection(); + + treeOptionROM.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image.Value)}, + HeaderText = "File" + }); + treeOptionROM.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Image.offset).Convert(v => v.ToString()) + }, + HeaderText = "Offset" + }); + treeOptionROM.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + + treeOptionROM.DataStore = lstPCIOptionROM; + + treeOptionROM.AllowMultipleSelection = false; + #endregion Set Option ROM table + + #region Set tracks table + lstTracks = new ObservableCollection(); + + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image.Value)}, + HeaderText = "File" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Image.offset).Convert(v => v.ToString()) + }, + HeaderText = "Offset" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image.format)}, + HeaderText = "Image format" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Head).Convert(v => v.ToString()) + }, + HeaderText = "Head" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Cylinder).Convert(v => v.ToString()) + }, + HeaderText = "Cylinder" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.StartSector).Convert(v => v.ToString()) + }, + HeaderText = "Start" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.EndSector).Convert(v => v.ToString()) + }, + HeaderText = "End" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Sectors).Convert(v => v.ToString()) + }, + HeaderText = "Sectors" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.BytesPerSector).Convert(v => v.ToString()) + }, + HeaderText = "Bytes per sector" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Format)}, + HeaderText = "Track format" + }); + + treeTracks.DataStore = lstTracks; + + treeTracks.AllowMultipleSelection = false; + #endregion Set tracks table + + lstAdditionalInformation = new ObservableCollection(); + treeAdditionalInformation.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.str)}, + HeaderText = "Information" + }); + treeAdditionalInformation.DataStore = lstAdditionalInformation; + treeAdditionalInformation.AllowMultipleSelection = false; + + txtImage.ToolTip = "This is the disk image containing this media."; + txtFormat.ToolTip = "This is the format of the disk image."; + txtOffset.ToolTip = "Byte offset where the media dump starts in the disk image."; + txtSize.ToolTip = "Size of the disk dump."; + txtManufacturer.ToolTip = "Disk manufacturer."; + txtModel.ToolTip = "Disk model."; + txtSerial.ToolTip = "Disk serial number."; + txtFirmware.ToolTip = "Disk firmware revision."; + txtInterface.ToolTip = "Disk interface."; + txtCopyProtection.ToolTip = "Disk copy protection."; + txtMediaType.ToolTip = "Disk type."; + txtMediaSubtype.ToolTip = "Disk subtype."; + chkSequence.ToolTip = "If checked means this disk is one in a sequence of several."; + txtMediaTitle.ToolTip = "Title of disk."; + spSequence.ToolTip = "Number of this disk in the sequence."; + spTotalMedia.ToolTip = "How many disks make the sequence."; + spSide.ToolTip = "On flippy disks, which side of the disk is represented by this dump."; + spLayer.ToolTip = + "On PTP layered disks, which layer of the side of the disk is represented by this dump."; + txtBlocks.ToolTip = "How many individual blocks (sectors) are in this dump."; + spPhysicalBlockSize.ToolTip = "Size of the biggest physical block in bytes."; + spLogicalBlockSize.ToolTip = "Size of the biggest logical block in bytes."; + spCylinders.ToolTip = "Cylinders of disk."; + spHeads.ToolTip = "Heads of disk."; + spSectors.ToolTip = "Sectors per track of disk."; + chkDimensions.ToolTip = "If checked, physical dimensions of disk are known."; + chkRound.ToolTip = "If checked, disk is physicaly round."; + spDiameter.ToolTip = "Diameter in milimeters of disk."; + spHeight.ToolTip = "Height in milimeters of disk."; + spWidth.ToolTip = "Width in milimeters of disk."; + spThickness.ToolTip = "Thickness in milimeters of disk."; + chkATA.ToolTip = "If checked, disk dump contains ATA(PI) IDENTIFY information."; + } + + public void FillFields() + { + if(Metadata == null) return; + + txtImage.Text = Metadata.Image.Value; + txtFormat.Text = Metadata.Image.format; + if(Metadata.Image.offsetSpecified) txtOffset.Text = Metadata.Image.offset.ToString(); + txtSize.Text = Metadata.Size.ToString(); + checksums = Metadata.Checksums; + contentChks = Metadata.ContentChecksums; + if(Metadata.Sequence != null) + { + lblMediaTitle.Visible = true; + txtMediaTitle.Visible = true; + lblSequence.Visible = true; + spSequence.Visible = true; + lblTotalMedia.Visible = true; + spTotalMedia.Visible = true; + lblSide.Visible = true; + spSide.Visible = true; + lblLayer.Visible = true; + spLayer.Visible = true; + chkSequence.Checked = true; + txtMediaTitle.Text = Metadata.Sequence.MediaTitle; + spSequence.Value = Metadata.Sequence.MediaSequence; + spTotalMedia.Value = Metadata.Sequence.TotalMedia; + if(Metadata.Sequence.SideSpecified) spSide.Value = Metadata.Sequence.Side; + if(Metadata.Sequence.LayerSpecified) spLayer.Value = Metadata.Sequence.Layer; + } + + if(Metadata.Manufacturer != null) txtManufacturer.Text = Metadata.Manufacturer; + if(Metadata.Model != null) txtModel.Text = Metadata.Model; + if(Metadata.Serial != null) txtSerial.Text = Metadata.Serial; + if(Metadata.Firmware != null) txtFirmware.Text = Metadata.Firmware; + if(Metadata.Interface != null) txtInterface.Text = Metadata.Interface; + spPhysicalBlockSize.Value = Metadata.PhysicalBlockSize; + spLogicalBlockSize.Value = Metadata.LogicalBlockSize; + txtBlocks.Text = Metadata.LogicalBlocks.ToString(); + variableBlockSize = Metadata.VariableBlockSize; + tapeInformation = Metadata.TapeInformation; + scans = Metadata.Scans; + if(Metadata.ATA?.Identify != null) + { + chkATA.Checked = true; + treeATA.Visible = true; + lstAta.Add(Metadata.ATA.Identify); + } + + if(Metadata.PCI != null) + { + chkPCI.Checked = true; + lblPCIVendor.Visible = true; + txtPCIVendor.Visible = true; + lblPCIProduct.Visible = true; + txtPCIProduct.Visible = true; + txtPCIVendor.Text = $"0x{Metadata.PCI.VendorID:X4}"; + txtPCIProduct.Text = $"0x{Metadata.PCI.DeviceID:X4}"; + if(Metadata.PCI.Configuration != null) + { + frmPCIConfiguration.Visible = true; + lstPCIConfiguration.Add(Metadata.PCI.Configuration); + } + + if(Metadata.PCI.ExpansionROM != null) + { + frmOptionROM.Visible = true; + lstPCIOptionROM.Add(Metadata.PCI.ExpansionROM); + } + } + + if(Metadata.PCMCIA != null) + { + chkPCMCIA.Checked = true; + chkCIS.Visible = true; + lblPCMCIAManufacturer.Visible = true; + txtPCMCIAManufacturer.Visible = true; + lblMfgCode.Visible = true; + txtMfgCode.Visible = true; + lblPCMCIAProductName.Visible = true; + txtPCMCIAProductName.Visible = true; + lblCardCode.Visible = true; + txtCardCode.Visible = true; + lblCompliance.Visible = true; + txtCompliance.Visible = true; + + if(Metadata.PCMCIA.CIS != null) + { + treeCIS.Visible = true; + lstPCMCIACIS.Add(Metadata.PCMCIA.CIS); + } + + if(Metadata.PCMCIA.Compliance != null) txtCompliance.Text = Metadata.PCMCIA.Compliance; + if(Metadata.PCMCIA.ManufacturerCodeSpecified) + txtMfgCode.Text = $"0x{Metadata.PCMCIA.ManufacturerCode:X4}"; + if(Metadata.PCMCIA.CardCodeSpecified) + txtCardCode.Text = $"0x{Metadata.PCMCIA.CardCode:X4}"; + if(Metadata.PCMCIA.Manufacturer != null) txtPCMCIAManufacturer.Text = Metadata.PCMCIA.Manufacturer; + if(Metadata.PCMCIA.ProductName != null) txtPCMCIAProductName.Text = Metadata.PCMCIA.ProductName; + if(Metadata.PCMCIA.AdditionalInformation != null) + { + lblAdditionalInformation.Visible = true; + treeAdditionalInformation.Visible = true; + + foreach(string addinfo in Metadata.PCMCIA.AdditionalInformation) + lstAdditionalInformation.Add(new StringEntry {str = addinfo}); + } + } + + if(Metadata.SecureDigital?.CID != null) + { + chkSecureDigital.Checked = true; + chkCSD.Visible = true; + chkECSD.Visible = true; + lblCID.Visible = true; + treeCID.Visible = true; + lstCID.Add(Metadata.SecureDigital.CID); + + if(Metadata.SecureDigital.CSD != null) + { + chkCSD.Checked = true; + treeCSD.Visible = true; + lstCSD.Add(Metadata.SecureDigital.CSD); + } + + if(Metadata.MultiMediaCard.ExtendedCSD != null) + { + chkECSD.Checked = true; + treeECSD.Visible = true; + lstECSD.Add(Metadata.MultiMediaCard.ExtendedCSD); + } + } + + if(Metadata.SCSI?.Inquiry != null) + { + chkSCSI.Checked = true; + frmInquiry.Visible = true; + lstInquiry.Add(Metadata.SCSI.Inquiry); + + if(Metadata.SCSI.ModeSense != null) + { + frmModeSense.Visible = true; + lstModeSense.Add(Metadata.SCSI.ModeSense); + } + + if(Metadata.SCSI.ModeSense10 != null) + { + frmModeSense10.Visible = true; + lstModeSense10.Add(Metadata.SCSI.ModeSense10); + } + + if(Metadata.SCSI.LogSense != null) + { + frmLogSense.Visible = true; + lstLogSense.Add(Metadata.SCSI.LogSense); + } + + if(Metadata.SCSI.EVPD != null) + { + frmEVPDs.Visible = true; + lstEVPDs = new ObservableCollection(Metadata.SCSI.EVPD); + treeEVPDs.DataStore = lstEVPDs; // TODO: Really needed? + } + } + + if(Metadata.USB != null) + { + chkUSB.Checked = true; + lblUSBVendor.Visible = true; + txtUSBVendor.Visible = true; + lblUSBProduct.Visible = true; + txtUSBProduct.Visible = true; + txtUSBVendor.Text = $"0x{Metadata.USB.VendorID:X4}"; + txtUSBProduct.Text = $"0x{Metadata.USB.ProductID:X4}"; + if(Metadata.USB.Descriptors != null) + { + frmDescriptors.Visible = true; + lstUSBDescriptors.Add(Metadata.USB.Descriptors); + } + } + + if(Metadata.MAM != null) + { + chkMAM.Checked = true; + treeMAM.Visible = true; + lstMAM.Add(Metadata.MAM); + } + + if(Metadata.HeadsSpecified) spHeads.Value = Metadata.Heads; + if(Metadata.CylindersSpecified) spCylinders.Value = Metadata.Cylinders; + if(Metadata.SectorsPerTrackSpecified) spSectors.Value = Metadata.SectorsPerTrack; + if(Metadata.Track != null) + { + chkTracks.Checked = true; + treeTracks.Visible = true; + lstTracks = new ObservableCollection(Metadata.Track); + treeTracks.DataStore = lstTracks; // TODO: Really needed? + } + + if(Metadata.CopyProtection != null) txtCopyProtection.Text = Metadata.CopyProtection; + if(Metadata.Dimensions != null) + { + chkDimensions.Checked = true; + if(Metadata.Dimensions.DiameterSpecified) + { + chkRound.Checked = true; + stkDiameter.Visible = true; + stkHeight.Visible = false; + stkWidth.Visible = false; + spDiameter.Value = Metadata.Dimensions.Diameter; + } + else + { + stkDiameter.Visible = false; + stkHeight.Visible = true; + stkWidth.Visible = true; + spHeight.Value = Metadata.Dimensions.Height; + spWidth.Value = Metadata.Dimensions.Width; + } + + stkThickness.Visible = true; + spThickness.Value = Metadata.Dimensions.Thickness; + } + + if(Metadata.FileSystemInformation != null) + { + lstPartitions = new ObservableCollection(Metadata.FileSystemInformation); + treePartitions.DataStore = lstPartitions; // TODO: Really needed? + } + + if(Metadata.DumpHardwareArray != null) + { + chkDumpHardware.Checked = true; + treeDumpHardware.Visible = true; + btnAddHardware.Visible = true; + btnEditHardware.Visible = true; + btnRemoveHardware.Visible = true; + + lstDumpHw = new ObservableCollection(Metadata.DumpHardwareArray); + treeDumpHardware.DataStore = lstDumpHw; // TODO: Really needed? + } + + if(Metadata.DiskType != null) txtMediaType.Text = Metadata.DiskType; + if(Metadata.DiskSubType != null) txtMediaSubtype.Text = Metadata.DiskSubType; + } + + protected void OnChkSequenceToggled(object sender, EventArgs e) + { + lblMediaTitle.Visible = chkSequence.Checked.Value; + txtMediaTitle.Visible = chkSequence.Checked.Value; + lblSequence.Visible = chkSequence.Checked.Value; + spSequence.Visible = chkSequence.Checked.Value; + lblTotalMedia.Visible = chkSequence.Checked.Value; + spTotalMedia.Visible = chkSequence.Checked.Value; + lblSide.Visible = chkSequence.Checked.Value; + spSide.Visible = chkSequence.Checked.Value; + lblLayer.Visible = chkSequence.Checked.Value; + spLayer.Visible = chkSequence.Checked.Value; + } + + protected void OnChkDimensionsToggled(object sender, EventArgs e) + { + chkRound.Visible = chkDimensions.Checked.Value; + stkThickness.Visible = chkDimensions.Checked.Value; + if(chkDimensions.Checked.Value) OnChkRoundToggled(sender, e); + else + { + stkDiameter.Visible = false; + stkHeight.Visible = false; + stkWidth.Visible = false; + } + } + + protected void OnChkRoundToggled(object sender, EventArgs e) + { + stkDiameter.Visible = chkRound.Checked.Value; + stkHeight.Visible = !chkRound.Checked.Value; + stkWidth.Visible = !chkRound.Checked.Value; + } + + protected void OnChkPCMCIAToggled(object sender, EventArgs e) + { + chkCIS.Visible = chkPCMCIA.Checked.Value; + treeCIS.Visible = chkPCMCIA.Checked.Value; + lblPCMCIAManufacturer.Visible = chkPCMCIA.Checked.Value; + txtPCMCIAManufacturer.Visible = chkPCMCIA.Checked.Value; + lblMfgCode.Visible = chkPCMCIA.Checked.Value; + txtMfgCode.Visible = chkPCMCIA.Checked.Value; + lblPCMCIAProductName.Visible = chkPCMCIA.Checked.Value; + txtPCMCIAProductName.Visible = chkPCMCIA.Checked.Value; + lblCardCode.Visible = chkPCMCIA.Checked.Value; + txtCardCode.Visible = chkPCMCIA.Checked.Value; + lblCompliance.Visible = chkPCMCIA.Checked.Value; + txtCompliance.Visible = chkPCMCIA.Checked.Value; + lblAdditionalInformation.Visible = false; + treeAdditionalInformation.Visible = false; + } + + protected void OnBtnCancelPartitionClicked(object sender, EventArgs e) + { + btnCancelPartition.Visible = false; + btnApplyPartition.Visible = false; + btnRemovePartition.Visible = true; + btnEditPartition.Visible = true; + btnAddPartition.Visible = true; + stkPartitionFields1.Visible = false; + stkPartitionFields2.Visible = false; + frmFilesystems.Visible = false; + } + + protected void OnBtnRemovePartitionClicked(object sender, EventArgs e) + { + if(treePartitions.SelectedItem != null) lstPartitions.Remove((PartitionType)treePartitions.SelectedItem); + } + + protected void OnBtnEditPartitionClicked(object sender, EventArgs e) + { + if(treePartitions.SelectedItem == null) return; + + partitionIter = (PartitionType)treePartitions.SelectedItem; + + spPartitionSequence.Value = partitionIter.Sequence; + txtPartitionStart.Text = partitionIter.StartSector.ToString(); + txtPartitionEnd.Text = partitionIter.EndSector.ToString(); + txtPartitionType.Text = partitionIter.Type; + txtPartitionName.Text = partitionIter.Name; + txtPartitionDescription.Text = partitionIter.Description; + treeFilesystems.DataStore = new ObservableCollection(partitionIter.FileSystems); + + btnCancelPartition.Visible = true; + btnApplyPartition.Visible = true; + btnRemovePartition.Visible = false; + btnEditPartition.Visible = false; + btnAddPartition.Visible = false; + stkPartitionFields1.Visible = true; + stkPartitionFields2.Visible = true; + frmFilesystems.Visible = true; + + editingPartition = true; + } + + protected void OnBtnApplyPartitionClicked(object sender, EventArgs e) + { + if(!int.TryParse(txtPartitionStart.Text, out int temp)) + { + MessageBox.Show("Partition start must be a number", MessageBoxType.Error); + return; + } + + if(!int.TryParse(txtPartitionEnd.Text, out int temp2)) + { + MessageBox.Show("Partition end must be a number", MessageBoxType.Error); + return; + } + + if(temp2 <= temp) + { + MessageBox.Show("Partition must end after start, and be bigger than 1 sector", MessageBoxType.Error); + return; + } + + if(editingPartition) lstPartitions.Remove(partitionIter); + + partitionIter = new PartitionType + { + Sequence = (uint)spPartitionSequence.Value, + StartSector = ulong.Parse(txtPartitionStart.Text), + EndSector = ulong.Parse(txtPartitionEnd.Text), + Type = txtPartitionType.Text, + Name = txtPartitionName.Text, + Description = txtPartitionDescription.Text + }; + if(((ObservableCollection)treeFilesystems.DataStore).Count > 0) + partitionIter.FileSystems = ((ObservableCollection)treeFilesystems.DataStore).ToArray(); + + btnCancelPartition.Visible = false; + btnApplyPartition.Visible = false; + btnRemovePartition.Visible = true; + btnEditPartition.Visible = true; + btnAddPartition.Visible = true; + stkPartitionFields1.Visible = false; + stkPartitionFields2.Visible = false; + frmFilesystems.Visible = false; + } + + protected void OnBtnAddPartitionClicked(object sender, EventArgs e) + { + spPartitionSequence.Value = 0; + txtPartitionStart.Text = ""; + txtPartitionEnd.Text = ""; + txtPartitionType.Text = ""; + txtPartitionName.Text = ""; + txtPartitionDescription.Text = ""; + treeFilesystems.DataStore = new ObservableCollection(); + + btnCancelPartition.Visible = true; + btnApplyPartition.Visible = true; + btnRemovePartition.Visible = false; + btnEditPartition.Visible = false; + btnAddPartition.Visible = false; + stkPartitionFields1.Visible = true; + stkPartitionFields2.Visible = true; + frmFilesystems.Visible = true; + + editingPartition = false; + } + + protected void OnBtnRemoveFilesystemClicked(object sender, EventArgs e) + { + if(treeFilesystems.SelectedItem != null) + ((ObservableCollection)treeFilesystems.DataStore).Remove((FileSystemType)treeFilesystems + .SelectedItem); + } + + protected void OnBtnEditFilesystemClicked(object sender, EventArgs e) + { + /* + if(treeFilesystems.SelectedItem == null) return; + + filesystemIter = (FileSystemType)treeFilesystems.SelectedItem; + + dlgFilesystem _dlgFilesystem = new dlgFilesystem {Metadata = filesystemIter}; + _dlgFilesystem.FillFields(); + _dlgFilesystem.ShowModal(this); + + if(!_dlgFilesystem.Modified) return; + + ((ObservableCollection)treeFilesystems.DataStore).Remove(filesystemIter); + ((ObservableCollection)treeFilesystems.DataStore).Add(_dlgFilesystem.Metadata);*/ + } + + protected void OnBtnAddFilesystemClicked(object sender, EventArgs e) + { + /* + dlgFilesystem _dlgFilesystem = new dlgFilesystem(); + _dlgFilesystem.ShowModal(this); + + if(_dlgFilesystem.Modified) + ((ObservableCollection)treeFilesystems.DataStore).Add(_dlgFilesystem.Metadata);*/ + } + + protected void OnChkDumpHardwareToggled(object sender, EventArgs e) + { + treeDumpHardware.Visible = chkDumpHardware.Checked.Value; + btnAddHardware.Visible = chkDumpHardware.Checked.Value; + btnRemoveHardware.Visible = chkDumpHardware.Checked.Value; + btnEditHardware.Visible = chkDumpHardware.Checked.Value; + + btnCancelHardware.Visible = false; + btnApplyHardware.Visible = false; + frmHardware.Visible = false; + } + + protected void OnBtnCancelHardwareClicked(object sender, EventArgs e) + { + btnAddHardware.Visible = true; + btnRemoveHardware.Visible = true; + btnCancelHardware.Visible = false; + btnEditHardware.Visible = true; + btnApplyHardware.Visible = false; + frmHardware.Visible = false; + } + + protected void OnBtnRemoveHardwareClicked(object sender, EventArgs e) + { + if(treeDumpHardware.SelectedItem != null) lstDumpHw.Remove((DumpHardwareType)treeDumpHardware.SelectedItem); + } + + protected void OnBtnEditHardwareClicked(object sender, EventArgs e) + { + if(treeDumpHardware.SelectedItem == null) return; + + dumpHwIter = (DumpHardwareType)treeDumpHardware.SelectedItem; + + txtHWManufacturer.Text = dumpHwIter.Manufacturer; + txtHWModel.Text = dumpHwIter.Model; + txtHWRevision.Text = dumpHwIter.Revision; + txtHWFirmware.Text = dumpHwIter.Firmware; + txtHWSerial.Text = dumpHwIter.Serial; + if(dumpHwIter.Software != null) + { + txtDumpName.Text = dumpHwIter.Software.Name; + txtDumpVersion.Text = dumpHwIter.Software.Version; + txtDumpOS.Text = dumpHwIter.Software.OperatingSystem; + } + + treeExtents.DataStore = new ObservableCollection(dumpHwIter.Extents); + + btnAddHardware.Visible = false; + btnRemoveHardware.Visible = false; + btnCancelHardware.Visible = true; + btnEditHardware.Visible = false; + btnApplyHardware.Visible = true; + frmHardware.Visible = true; + + editingDumpHw = true; + } + + protected void OnBtnApplyHardwareClicked(object sender, EventArgs e) + { + if(editingDumpHw) lstDumpHw.Remove(dumpHwIter); + + dumpHwIter = new DumpHardwareType + { + Manufacturer = txtHWManufacturer.Text, + Model = txtHWModel.Text, + Revision = txtHWRevision.Text, + Firmware = txtHWFirmware.Text, + Serial = txtHWSerial.Text + }; + if(!string.IsNullOrWhiteSpace(txtDumpName.Text) || !string.IsNullOrWhiteSpace(txtDumpVersion.Text) || + !string.IsNullOrWhiteSpace(txtDumpOS.Text)) + dumpHwIter.Software = new SoftwareType + { + Name = txtDumpName.Text, + Version = txtDumpVersion.Text, + OperatingSystem = txtDumpOS.Text + }; + if(((ObservableCollection)treeExtents.DataStore).Count > 0) + dumpHwIter.Extents = ((ObservableCollection)treeExtents.DataStore).ToArray(); + + lstDumpHw.Add(dumpHwIter); + + btnAddHardware.Visible = true; + btnRemoveHardware.Visible = true; + btnCancelHardware.Visible = false; + btnEditHardware.Visible = true; + btnApplyHardware.Visible = false; + frmHardware.Visible = false; + } + + protected void OnBtnAddHardwareClicked(object sender, EventArgs e) + { + txtHWManufacturer.Text = ""; + txtHWModel.Text = ""; + txtHWRevision.Text = ""; + txtHWFirmware.Text = ""; + txtHWSerial.Text = ""; + txtDumpName.Text = ""; + txtDumpVersion.Text = ""; + txtDumpOS.Text = ""; + treeExtents.DataStore = new ObservableCollection(); + + btnAddHardware.Visible = false; + btnRemoveHardware.Visible = false; + btnCancelHardware.Visible = true; + btnEditHardware.Visible = false; + btnApplyHardware.Visible = true; + frmHardware.Visible = true; + + editingDumpHw = false; + } + + protected void OnBtnRemoveExtentClicked(object sender, EventArgs e) + { + if(treeExtents.SelectedItem != null) + ((ObservableCollection)treeExtents.DataStore).Remove((ExtentType)treeExtents.SelectedItem); + } + + protected void OnBtnAddExtentClicked(object sender, EventArgs e) + { + ((ObservableCollection)treeExtents.DataStore).Add(new ExtentType + { + Start = (ulong)spExtentStart.Value, + End = (ulong)spExtentEnd.Value + }); + } + + protected void OnBtnCancelClicked(object sender, EventArgs e) + { + Close(); + } + + protected void OnBtnSaveClicked(object sender, EventArgs e) + { + #region Sanity checks + if(string.IsNullOrEmpty(txtFormat.Text)) + { + MessageBox.Show("Image format cannot be null", MessageBoxType.Error); + return; + } + + if(chkSequence.Checked.Value) + { + if(spSequence.Value < 1) + { + MessageBox.Show("Media sequence must be bigger than 0", MessageBoxType.Error); + return; + } + + if(spTotalMedia.Value < 1) + { + MessageBox.Show("Total medias must be bigger than 0", MessageBoxType.Error); + return; + } + + if(spSequence.Value > spTotalMedia.Value) + { + MessageBox.Show("Media sequence cannot be bigger than total medias", MessageBoxType.Error); + return; + } + } + + if(string.IsNullOrEmpty(txtBlocks.Text) || !long.TryParse(txtBlocks.Text, out long ltmp)) + { + MessageBox.Show("Blocks must be a number", MessageBoxType.Error); + return; + } + + if(ltmp < 1) + { + MessageBox.Show("Blocks must be bigger than 0", MessageBoxType.Error); + return; + } + + if(spPhysicalBlockSize.Value < 1) + { + MessageBox.Show("Physical Block Size must be bigger than 0", MessageBoxType.Error); + return; + } + + if(spLogicalBlockSize.Value < 1) + { + MessageBox.Show("Logical Block Size must be bigger than 0", MessageBoxType.Error); + return; + } + + if(spPhysicalBlockSize.Value < spLogicalBlockSize.Value) + { + MessageBox.Show("Physical Block Size must be bigger than Logical Block Size", MessageBoxType.Error); + return; + } + + if(chkDimensions.Checked.Value) + { + if(chkRound.Checked.Value) + { + if(spDiameter.Value <= 0) + { + MessageBox.Show("Diameter must be bigger than 0", MessageBoxType.Error); + return; + } + } + else + { + if(spHeight.Value <= 0) + { + MessageBox.Show("Height must be bigger than 0", MessageBoxType.Error); + return; + } + + if(spWidth.Value <= 0) + { + MessageBox.Show("Width must be bigger than 0", MessageBoxType.Error); + return; + } + } + + if(spThickness.Value <= 0) + { + MessageBox.Show("Thickness must be bigger than 0", MessageBoxType.Error); + return; + } + } + + if(chkPCI.Checked.Value) + { + if(string.IsNullOrWhiteSpace(txtPCIVendor.Text)) + { + MessageBox.Show("PCI Vendor ID must be set", MessageBoxType.Error); + return; + } + + if(string.IsNullOrWhiteSpace(txtPCIProduct.Text)) + { + MessageBox.Show("PCI Product ID must be set", MessageBoxType.Error); + return; + } + + try + { + if(Convert.ToInt32(txtPCIVendor.Text, 16) < 0 || Convert.ToInt32(txtPCIVendor.Text, 16) > 0xFFFF) + { + MessageBox.Show("PCI Vendor ID must be between 0x0000 and 0xFFFF", MessageBoxType.Error); + return; + } + } + catch(FormatException) + { + MessageBox.Show("PCI Vendor ID must be a number in hexadecimal format", MessageBoxType.Error); + return; + } + catch(OverflowException) + { + MessageBox.Show("PCI Vendor ID must not be negative", MessageBoxType.Error); + return; + } + + try + { + if(Convert.ToInt32(txtPCIProduct.Text, 16) < 0 || Convert.ToInt32(txtPCIProduct.Text, 16) > 0xFFFF) + { + MessageBox.Show("PCI Product ID must be between 0x0000 and 0xFFFF", MessageBoxType.Error); + return; + } + } + catch(FormatException) + { + MessageBox.Show("PCI Product ID must be a number in hexadecimal format", MessageBoxType.Error); + return; + } + catch(OverflowException) + { + MessageBox.Show("PCI Product ID must not be negative", MessageBoxType.Error); + return; + } + } + + if(chkPCMCIA.Checked.Value) + { + if(string.IsNullOrWhiteSpace(txtPCMCIAManufacturer.Text)) + { + MessageBox.Show("PCMCIA Manufacturer Code must be set", MessageBoxType.Error); + return; + } + + if(string.IsNullOrWhiteSpace(txtCardCode.Text)) + { + MessageBox.Show("PCMCIA Card Code must be set", MessageBoxType.Error); + return; + } + + try + { + if(Convert.ToInt32(txtMfgCode.Text, 16) < 0 || Convert.ToInt32(txtMfgCode.Text, 16) > 0xFFFF) + { + MessageBox.Show("PCMCIA Manufacturer Code must be between 0x0000 and 0xFFFF", + MessageBoxType.Error); + return; + } + } + catch(FormatException) + { + MessageBox.Show("PCMCIA Manufacturer Code must be a number in hexadecimal format", + MessageBoxType.Error); + return; + } + catch(OverflowException) + { + MessageBox.Show("PCMCIA Manufacturer Code must not be negative", MessageBoxType.Error); + return; + } + + try + { + if(Convert.ToInt32(txtCardCode.Text, 16) < 0 || Convert.ToInt32(txtCardCode.Text, 16) > 0xFFFF) + { + MessageBox.Show("PCMCIA Card Code must be between 0x0000 and 0xFFFF", MessageBoxType.Error); + return; + } + } + catch(FormatException) + { + MessageBox.Show("PCMCIA Card Code must be a number in hexadecimal format", MessageBoxType.Error); + return; + } + catch(OverflowException) + { + MessageBox.Show("PCMCIA Card Code must not be negative", MessageBoxType.Error); + return; + } + } + + if(chkUSB.Checked.Value) + { + if(string.IsNullOrWhiteSpace(txtUSBVendor.Text)) + { + MessageBox.Show("USB Vendor ID must be set", MessageBoxType.Error); + return; + } + + if(string.IsNullOrWhiteSpace(txtUSBProduct.Text)) + { + MessageBox.Show("USB Product ID must be set", MessageBoxType.Error); + return; + } + + try + { + if(Convert.ToInt32(txtUSBVendor.Text, 16) < 0 || Convert.ToInt32(txtUSBVendor.Text, 16) > 0xFFFF) + { + MessageBox.Show("USB Vendor ID must be between 0x0000 and 0xFFFF", MessageBoxType.Error); + return; + } + } + catch(FormatException) + { + MessageBox.Show("USB Vendor ID must be a number in hexadecimal format", MessageBoxType.Error); + return; + } + catch(OverflowException) + { + MessageBox.Show("USB Vendor ID must not be negative", MessageBoxType.Error); + return; + } + + try + { + if(Convert.ToInt32(txtUSBProduct.Text, 16) < 0 || Convert.ToInt32(txtUSBProduct.Text, 16) > 0xFFFF) + { + MessageBox.Show("USB Product ID must be between 0x0000 and 0xFFFF", MessageBoxType.Error); + return; + } + } + catch(FormatException) + { + MessageBox.Show("USB Product ID must be a number in hexadecimal format", MessageBoxType.Error); + return; + } + catch(OverflowException) + { + MessageBox.Show("USB Product ID must not be negative", MessageBoxType.Error); + return; + } + } + + if(chkDumpHardware.Checked.Value) + if(lstDumpHw.Count < 1) + { + MessageBox.Show("If dump hardware is known at least an entry must be created"); + return; + } + #endregion Sanity checks + + Metadata = new BlockMediaType {Image = new ImageType {Value = txtImage.Text, format = txtFormat.Text}}; + + if(!string.IsNullOrWhiteSpace(txtOffset.Text) && long.TryParse(txtOffset.Text, out ltmp)) + { + Metadata.Image.offsetSpecified = true; + Metadata.Image.offset = ulong.Parse(txtOffset.Text); + } + + Metadata.Size = ulong.Parse(txtSize.Text); + Metadata.Checksums = checksums; + Metadata.ContentChecksums = contentChks; + + if(chkSequence.Checked.Value) + { + Metadata.Sequence = new SequenceType + { + MediaTitle = txtMediaTitle.Text, + MediaSequence = (uint)spSequence.Value, + TotalMedia = (uint)spTotalMedia.Value + }; + if(spSide.Value > 0) + { + Metadata.Sequence.SideSpecified = true; + Metadata.Sequence.Side = (byte)spSide.Value; + } + + if(spLayer.Value > 0) + { + Metadata.Sequence.LayerSpecified = true; + Metadata.Sequence.Layer = (byte)spLayer.Value; + } + } + + if(!string.IsNullOrWhiteSpace(txtManufacturer.Text)) Metadata.Manufacturer = txtManufacturer.Text; + if(!string.IsNullOrWhiteSpace(txtModel.Text)) Metadata.Model = txtModel.Text; + if(!string.IsNullOrWhiteSpace(txtSerial.Text)) Metadata.Serial = txtSerial.Text; + if(!string.IsNullOrWhiteSpace(txtFirmware.Text)) Metadata.Firmware = txtFirmware.Text; + if(!string.IsNullOrWhiteSpace(txtInterface.Text)) Metadata.Interface = txtInterface.Text; + + Metadata.PhysicalBlockSize = (uint)spPhysicalBlockSize.Value; + Metadata.LogicalBlockSize = (uint)spLogicalBlockSize.Value; + Metadata.LogicalBlocks = ulong.Parse(txtBlocks.Text); + Metadata.VariableBlockSize = variableBlockSize; + Metadata.TapeInformation = tapeInformation; + Metadata.Scans = scans; + + if(chkATA.Checked.Value && lstAta.Count == 1) Metadata.ATA = new ATAType {Identify = lstAta[0]}; + + if(chkPCI.Checked.Value) + { + Metadata.PCI = new PCIType + { + VendorID = Convert.ToUInt16(txtPCIVendor.Text, 16), + DeviceID = Convert.ToUInt16(txtPCIProduct.Text, 16) + }; + + if(lstPCIConfiguration.Count == 1) Metadata.PCI.Configuration = lstPCIConfiguration[0]; + + if(lstPCIOptionROM.Count == 1) Metadata.PCI.ExpansionROM = lstPCIOptionROM[0]; + } + + if(chkPCMCIA.Checked.Value) + { + Metadata.PCMCIA = new PCMCIAType(); + + if(lstPCMCIACIS.Count == 1) Metadata.PCMCIA.CIS = lstPCMCIACIS[0]; + + if(!string.IsNullOrWhiteSpace(txtCompliance.Text)) Metadata.PCMCIA.Compliance = txtCompliance.Text; + if(!string.IsNullOrWhiteSpace(txtPCMCIAManufacturer.Text)) + Metadata.PCMCIA.Manufacturer = txtPCMCIAManufacturer.Text; + if(!string.IsNullOrWhiteSpace(txtPCMCIAProductName.Text)) + Metadata.PCMCIA.ProductName = txtPCMCIAProductName.Text; + if(!string.IsNullOrWhiteSpace(txtMfgCode.Text)) + { + Metadata.PCMCIA.ManufacturerCodeSpecified = true; + Metadata.PCMCIA.ManufacturerCode = Convert.ToUInt16(txtMfgCode.Text, 16); + } + + if(!string.IsNullOrWhiteSpace(txtCardCode.Text)) + { + Metadata.PCMCIA.CardCodeSpecified = true; + Metadata.PCMCIA.CardCode = Convert.ToUInt16(txtCardCode.Text, 16); + } + + if(lstAdditionalInformation.Count > 0) + { + List addinfos = new List(); + foreach(StringEntry entry in lstAdditionalInformation) addinfos.Add(entry.str); + Metadata.PCMCIA.AdditionalInformation = addinfos.ToArray(); + } + } + + if(chkSecureDigital.Checked.Value) + { + Metadata.SecureDigital = new SecureDigitalType(); + + if(lstCID.Count == 1) Metadata.SecureDigital.CID = lstCID[0]; + if(lstCSD.Count == 1) Metadata.SecureDigital.CSD = lstCSD[0]; + if(lstECSD.Count == 1) Metadata.MultiMediaCard.ExtendedCSD = lstECSD[0]; + } + + if(chkSCSI.Checked.Value) + { + Metadata.SCSI = new SCSIType(); + + if(lstInquiry.Count == 1) Metadata.SCSI.Inquiry = lstInquiry[0]; + if(lstModeSense.Count == 1) Metadata.SCSI.ModeSense = lstModeSense[0]; + if(lstModeSense10.Count == 1) Metadata.SCSI.ModeSense10 = lstModeSense10[0]; + if(lstLogSense.Count == 1) Metadata.SCSI.LogSense = lstLogSense[0]; + if(lstEVPDs.Count > 0) Metadata.SCSI.EVPD = lstEVPDs.ToArray(); + } + + if(chkUSB.Checked.Value) + { + Metadata.USB = new USBType + { + VendorID = Convert.ToUInt16(txtUSBVendor.Text, 16), + ProductID = Convert.ToUInt16(txtUSBProduct.Text, 16) + }; + + if(lstUSBDescriptors.Count == 1) Metadata.USB.Descriptors = lstUSBDescriptors[0]; + } + + if(chkMAM.Checked.Value && lstMAM.Count == 1) Metadata.MAM = lstMAM[0]; + + if(spHeads.Value > 0 && spCylinders.Value > 0 && spSectors.Value > 0) + { + Metadata.HeadsSpecified = true; + Metadata.CylindersSpecified = true; + Metadata.SectorsPerTrackSpecified = true; + Metadata.Heads = (ushort)spHeads.Value; + Metadata.Cylinders = (uint)spCylinders.Value; + Metadata.SectorsPerTrack = (ulong)spSectors.Value; + } + + if(lstTracks.Count > 0) Metadata.Track = lstTracks.ToArray(); + + if(!string.IsNullOrWhiteSpace(txtCopyProtection.Text)) Metadata.CopyProtection = txtCopyProtection.Text; + + if(chkDimensions.Checked.Value) + { + Metadata.Dimensions = new DimensionsType(); + if(chkRound.Checked.Value) + { + Metadata.Dimensions.DiameterSpecified = true; + Metadata.Dimensions.Diameter = spDiameter.Value; + } + else + { + Metadata.Dimensions.HeightSpecified = true; + Metadata.Dimensions.WidthSpecified = true; + Metadata.Dimensions.Height = spHeight.Value; + Metadata.Dimensions.Width = spWidth.Value; + } + + Metadata.Dimensions.Thickness = spThickness.Value; + } + + if(lstPartitions.Count > 0) Metadata.FileSystemInformation = lstPartitions.ToArray(); + + if(chkDumpHardware.Checked.Value && lstDumpHw.Count > 0) Metadata.DumpHardwareArray = lstDumpHw.ToArray(); + + if(!string.IsNullOrWhiteSpace(txtMediaType.Text)) Metadata.DiskType = txtMediaType.Text; + if(!string.IsNullOrWhiteSpace(txtMediaSubtype.Text)) Metadata.DiskSubType = txtMediaSubtype.Text; + + Modified = true; + Close(); + } + + class StringEntry + { + public string str; + } + + #region XAML UI elements + #pragma warning disable 0649 + TextBox txtImage; + TextBox txtFormat; + TextBox txtOffset; + TextBox txtSize; + TextBox txtManufacturer; + TextBox txtModel; + TextBox txtSerial; + TextBox txtFirmware; + TextBox txtInterface; + TextBox txtCopyProtection; + TextBox txtMediaType; + TextBox txtMediaSubtype; + CheckBox chkSequence; + Label lblMediaTitle; + TextBox txtMediaTitle; + Label lblSequence; + NumericUpDown spSequence; + Label lblTotalMedia; + NumericUpDown spTotalMedia; + Label lblSide; + NumericUpDown spSide; + Label lblLayer; + NumericUpDown spLayer; + TextBox txtBlocks; + NumericUpDown spPhysicalBlockSize; + NumericUpDown spLogicalBlockSize; + NumericUpDown spCylinders; + NumericUpDown spHeads; + NumericUpDown spSectors; + CheckBox chkDimensions; + CheckBox chkRound; + StackLayout stkDiameter; + NumericUpDown spDiameter; + StackLayout stkHeight; + NumericUpDown spHeight; + StackLayout stkWidth; + NumericUpDown spWidth; + StackLayout stkThickness; + NumericUpDown spThickness; + CheckBox chkATA; + GridView treeATA; + CheckBox chkPCI; + Label lblPCIVendor; + TextBox txtPCIVendor; + Label lblPCIProduct; + TextBox txtPCIProduct; + GroupBox frmPCIConfiguration; + GridView treeConfiguration; + GroupBox frmOptionROM; + GridView treeOptionROM; + CheckBox chkPCMCIA; + CheckBox chkCIS; + GridView treeCIS; + Label lblPCMCIAManufacturer; + Label lblMfgCode; + Label lblPCMCIAProductName; + Label lblCardCode; + Label lblCompliance; + TextBox txtPCMCIAManufacturer; + TextBox txtMfgCode; + TextBox txtPCMCIAProductName; + TextBox txtCardCode; + TextBox txtCompliance; + GroupBox lblAdditionalInformation; + GridView treeAdditionalInformation; + CheckBox chkSecureDigital; + GridView treeCID; + CheckBox chkCSD; + GridView treeCSD; + CheckBox chkECSD; + GridView treeECSD; + CheckBox chkSCSI; + GroupBox frmInquiry; + GridView treeInquiry; + GroupBox frmModeSense; + GridView treeModeSense; + GroupBox frmModeSense10; + GridView treeModeSense10; + GroupBox frmLogSense; + GridView treeLogSense; + GroupBox frmEVPDs; + GridView treeEVPDs; + CheckBox chkUSB; + TextBox txtUSBVendor; + TextBox txtUSBProduct; + GridView treeDescriptors; + CheckBox chkMAM; + GridView treeMAM; + CheckBox chkTracks; + GridView treeTracks; + GridView treePartitions; + Button btnCancelPartition; + Button btnRemovePartition; + Button btnEditPartition; + Button btnApplyPartition; + Button btnAddPartition; + NumericUpDown spPartitionSequence; + TextBox txtPartitionStart; + TextBox txtPartitionEnd; + TextBox txtPartitionType; + TextBox txtPartitionName; + TextBox txtPartitionDescription; + GroupBox frmFilesystems; + GridView treeFilesystems; + CheckBox chkDumpHardware; + GridView treeDumpHardware; + Button btnCancelHardware; + Button btnRemoveHardware; + Button btnEditHardware; + Button btnApplyHardware; + Button btnAddHardware; + GroupBox frmHardware; + TextBox txtHWManufacturer; + TextBox txtHWModel; + TextBox txtHWRevision; + TextBox txtHWFirmware; + TextBox txtHWSerial; + GridView treeExtents; + NumericUpDown spExtentStart; + NumericUpDown spExtentEnd; + TextBox txtDumpName; + TextBox txtDumpVersion; + TextBox txtDumpOS; + Label lblCID; + Label lblUSBVendor; + Label lblUSBProduct; + GroupBox frmDescriptors; + StackLayout stkPartitionFields1; + StackLayout stkPartitionFields2; + #pragma warning restore 0649 + #endregion XAML UI elements + } +} \ No newline at end of file diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgMetadata.xeto b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgMetadata.xeto new file mode 100644 index 000000000..bfb024522 --- /dev/null +++ b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgMetadata.xeto @@ -0,0 +1,373 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Known release type? + + + + + + + Unknown or unreleased + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgMetadata.xeto.cs b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgMetadata.xeto.cs new file mode 100644 index 000000000..7e2e9223c --- /dev/null +++ b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgMetadata.xeto.cs @@ -0,0 +1,1291 @@ +// +// Author: +// Natalia Portillo claunia@claunia.com +// +// Copyright (c) 2017-2018, © Natalia Portillo +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +// following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this list of conditions and the +// following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +// following disclaimer in the documentation and/or other materials provided with the distribution. +// * Neither the name of the [ORGANIZATION] nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Xml; +using System.Xml.Serialization; +using Eto.Forms; +using Eto.Serialization.Xaml; +using Eto.Threading; +using Schemas; +using BorderType = Schemas.BorderType; + +namespace CICMMetadataEditor +{ + public class dlgMetadata : Form + { + AdvertisementType[] adverts; + AudioMediaType[] audiomedias; + BookType[] books; + string currentFile; + LinearMediaType[] linearmedias; + ObservableCollection lstArchitectures; + ObservableCollection lstArchitecturesTypes; + ObservableCollection lstBarcodes; + ObservableCollection lstBarcodeTypes; + ObservableCollection lstCategories; + ObservableCollection lstDiscs; + ObservableCollection lstDisks; + ObservableCollection lstFilesForMedia; + ObservableCollection lstKeywords; + ObservableCollection lstLanguages; + ObservableCollection lstLanguageTypes; + ObservableCollection lstOses; + ObservableCollection lstSubcategories; + + // TODO: Add the options to edit these fields + MagazineType[] magazines; + CICMMetadataType metadata; + + bool modified; + PCIType[] pcis; + bool stopped; + + Thread thdDisc; + Thread thdDisk; + UserManualType[] usermanuals; + + public dlgMetadata() + { + XamlReader.Load(this); + + cmbReleaseType = new EnumDropDown(); + stkReleaseType.Items.Add(new StackLayoutItem {Control = cmbReleaseType, Expand = true}); + + treeKeywords.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.str)}, + HeaderText = "Keyword" + }); + treeBarcodes.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.code)}, + HeaderText = "Barcode" + }); + treeBarcodes.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.type).Convert(v => v.ToString()) + }, + HeaderText = "Type" + }); + treeCategories.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.str)}, + HeaderText = "Category" + }); + treeSubcategories.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.str)}, + HeaderText = "Subcategory" + }); + treeLanguages.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.str)}, + HeaderText = "Language" + }); + treeOses.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.name)}, + HeaderText = "Name" + }); + treeOses.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.version)}, + HeaderText = "Version" + }); + treeArchitectures.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.str)}, + HeaderText = "Architecture" + }); + treeDiscs.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.path)}, + HeaderText = "File" + }); + treeDisks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.path)}, + HeaderText = "File" + }); + + treeKeywords.AllowMultipleSelection = false; + treeBarcodes.AllowMultipleSelection = false; + treeCategories.AllowMultipleSelection = false; + treeSubcategories.AllowMultipleSelection = false; + treeLanguages.AllowMultipleSelection = false; + treeOses.AllowMultipleSelection = false; + treeArchitectures.AllowMultipleSelection = false; + treeDiscs.AllowMultipleSelection = false; + treeDisks.AllowMultipleSelection = false; + + txtDeveloper.ToolTip = "Who developed the application."; + txtPublisher.ToolTip = "Who published the application."; + txtAuthor.ToolTip = "Author of the audiovisual media."; + txtPerformer.ToolTip = "Performer of the audiovisual media."; + txtName.ToolTip = "Application name."; + txtVersion.ToolTip = "Application version."; + txtPartNumber.ToolTip = "Part number of the application distribution."; + txtSerialNumber.ToolTip = + "Serial number of the application distribution. Not to be confused with serial number required to install."; + + lstBarcodeTypes = new ObservableCollection(); + lstLanguageTypes = new ObservableCollection(); + lstArchitecturesTypes = new ObservableCollection(); + lstFilesForMedia = new ObservableCollection(); + + //cmbBarcodes.ItemTextBinding = Binding.Property(r => r.str); + cmbBarcodes.DataStore = lstBarcodeTypes; + cmbLanguages.DataStore = lstLanguageTypes; + cmbArchitectures.DataStore = lstArchitecturesTypes; + cmbFilesForNewDisc.DataStore = lstFilesForMedia; + cmbFilesForNewDisk.DataStore = lstFilesForMedia; + + FillBarcodeCombo(); + FillLanguagesCombo(); + FillArchitecturesCombo(); + FillFilesCombos(); + } + + protected void OnAboutClicked(object sender, EventArgs e) + { + new AboutDialog().ShowDialog(this); + } + + protected void OnQuitClicked(object sender, EventArgs e) + { + Application.Instance.Quit(); + } + + protected void OnNewClicked(object sender, EventArgs e) + { + metadata = null; + modified = false; + currentFile = null; + LoadData(); + } + + protected void OnOpenClicked(object sender, EventArgs e) + { + OpenFileDialog dlgOpen = new OpenFileDialog + { + CheckFileExists = true, + MultiSelect = false, + Title = "Choose existing metadata file" + }; + dlgOpen.Filters.Add(new FileFilter("Metadata files", ".xml")); + + DialogResult result = dlgOpen.ShowDialog(this); + + if(result != DialogResult.Ok) return; + + try + { + XmlSerializer reader = new XmlSerializer(typeof(CICMMetadataType)); + FileStream fs = new FileStream(dlgOpen.FileName, FileMode.Open, FileAccess.Read); + metadata = (CICMMetadataType)reader.Deserialize(fs); + fs.Dispose(); + LoadData(); + currentFile = dlgOpen.FileName; + } + catch(XmlException) + { + MessageBox.Show("The chosen file is not a correct CICM Metadata file.", MessageBoxType.Error); + } + } + + protected void OnSaveClicked(object sender, EventArgs e) + { + if(!string.IsNullOrEmpty(currentFile)) OnSaveAsClicked(sender, e); + else Save(currentFile); + } + + protected void OnSaveAsClicked(object sender, EventArgs e) + { + SaveFileDialog dlgSave = new SaveFileDialog {CheckFileExists = true, Title = "Choose new metadata file"}; + dlgSave.Filters.Add(new FileFilter("Metadata files", ".xml")); + DialogResult result = dlgSave.ShowDialog(this); + + if(result != DialogResult.Ok) return; + + Save(dlgSave.FileName); + } + + void Save(string destination) + { + try + { + XmlSerializer writer = new XmlSerializer(typeof(CICMMetadataType)); + FileStream fs = new FileStream(destination, FileMode.Create, FileAccess.Write); + writer.Serialize(fs, metadata); + fs.Dispose(); + currentFile = destination; + } + catch(Exception) + { + if(Debugger.IsAttached) throw; + + MessageBox.Show("Could not save metadata.", MessageBoxType.Error); + } + } + + void LoadData() + { + modified = false; + + lstKeywords = new ObservableCollection(); + lstBarcodes = new ObservableCollection(); + lstCategories = new ObservableCollection(); + lstSubcategories = new ObservableCollection(); + lstLanguages = new ObservableCollection(); + lstOses = new ObservableCollection(); + lstArchitectures = new ObservableCollection(); + lstDiscs = new ObservableCollection(); + lstDisks = new ObservableCollection(); + + treeKeywords.DataStore = lstKeywords; + treeBarcodes.DataStore = lstBarcodes; + treeCategories.DataStore = lstCategories; + treeSubcategories.DataStore = lstSubcategories; + treeLanguages.DataStore = lstLanguages; + treeOses.DataStore = lstOses; + treeArchitectures.DataStore = lstArchitectures; + treeDiscs.DataStore = lstDiscs; + treeDisks.DataStore = lstDisks; + + txtDeveloper.Text = ""; + txtPublisher.Text = ""; + txtAuthor.Text = ""; + txtPerformer.Text = ""; + txtName.Text = ""; + txtVersion.Text = ""; + chkKnownReleaseType.Checked = false; + cldReleaseDate.Value = DateTime.UtcNow; + chkReleaseDate.Checked = false; + txtPartNumber.Text = ""; + txtSerialNumber.Text = ""; + txtNewKeyword.Text = ""; + txtNewBarcode.Text = ""; + txtNewCategory.Text = ""; + txtNewSubcategory.Text = ""; + txtNewOsName.Text = ""; + txtNewOsVersion.Text = ""; + + FillFields(); + } + + void FillBarcodeCombo() + { + lstBarcodeTypes.Clear(); + foreach(BarcodeTypeType type in Enum.GetValues(typeof(BarcodeTypeType))) + lstBarcodeTypes.Add(type.ToString()); + } + + void FillLanguagesCombo() + { + lstLanguageTypes.Clear(); + foreach(LanguagesTypeLanguage type in Enum.GetValues(typeof(LanguagesTypeLanguage))) + lstLanguageTypes.Add(type.ToString()); + } + + void FillArchitecturesCombo() + { + lstArchitecturesTypes.Clear(); + foreach(ArchitecturesTypeArchitecture type in Enum.GetValues(typeof(ArchitecturesTypeArchitecture))) + lstArchitecturesTypes.Add(type.ToString()); + } + + void FillFilesCombos() + { + /* TODO + foreach(KeyValuePair files in Context.Hashes) lstFilesForMedia.Add(files.Key); + */ + } + + void FillFields() + { + if(metadata == null) return; + + if(metadata.Developer != null) + foreach(string developer in metadata.Developer) + { + if(!string.IsNullOrWhiteSpace(txtDeveloper.Text)) txtDeveloper.Text += ","; + txtDeveloper.Text += developer; + } + + if(metadata.Publisher != null) + foreach(string publisher in metadata.Publisher) + { + if(!string.IsNullOrWhiteSpace(txtPublisher.Text)) txtPublisher.Text += ","; + txtPublisher.Text += publisher; + } + + if(metadata.Author != null) + foreach(string author in metadata.Author) + { + if(!string.IsNullOrWhiteSpace(txtPublisher.Text)) txtPublisher.Text += ","; + txtPublisher.Text += author; + } + + if(metadata.Performer != null) + foreach(string performer in metadata.Performer) + { + if(!string.IsNullOrWhiteSpace(txtPublisher.Text)) txtPublisher.Text += ","; + txtPublisher.Text += performer; + } + + txtName.Text = metadata.Name; + txtVersion.Text = metadata.Version; + txtPartNumber.Text = metadata.PartNumber; + txtSerialNumber.Text = metadata.SerialNumber; + + if(metadata.ReleaseTypeSpecified) + { + chkKnownReleaseType.Checked = true; + cmbReleaseType.Enabled = true; + cmbReleaseType.SelectedValue = metadata.ReleaseType; + } + + if(metadata.ReleaseDateSpecified) + { + chkReleaseDate.Checked = false; + cldReleaseDate.Enabled = true; + cldReleaseDate.Value = metadata.ReleaseDate; + } + + if(metadata.Keywords != null) + foreach(string keyword in metadata.Keywords) + lstKeywords.Add(new StringEntry {str = keyword}); + if(metadata.Categories != null) + foreach(string category in metadata.Categories) + lstCategories.Add(new StringEntry {str = category}); + if(metadata.Subcategories != null) + foreach(string subcategory in metadata.Subcategories) + lstSubcategories.Add(new StringEntry {str = subcategory}); + + if(metadata.Languages != null) + foreach(LanguagesTypeLanguage language in metadata.Languages) + { + lstLanguages.Add(new StringEntry {str = language.ToString()}); + lstLanguageTypes.Remove(language.ToString()); + } + + if(metadata.RequiredOperatingSystems != null) + foreach(RequiredOperatingSystemType reqos in metadata.RequiredOperatingSystems) + foreach(string reqver in reqos.Version) + lstOses.Add(new TargetOsEntry {name = reqos.Name, version = reqver}); + + if(metadata.Architectures != null) + foreach(ArchitecturesTypeArchitecture architecture in metadata.Architectures) + { + lstArchitectures.Add(new StringEntry {str = architecture.ToString()}); + lstArchitecturesTypes.Remove(architecture.ToString()); + } + + if(metadata.OpticalDisc != null) + foreach(OpticalDiscType disc in metadata.OpticalDisc) + { + lstDiscs.Add(new DiscEntry {path = disc.Image.Value, disc = disc}); + List files = new List {disc.Image.Value}; + if(disc.ADIP != null) files.Add(disc.ADIP.Image); + if(disc.ATIP != null) files.Add(disc.ATIP.Image); + if(disc.BCA != null) files.Add(disc.BCA.Image); + if(disc.CMI != null) files.Add(disc.CMI.Image); + if(disc.DCB != null) files.Add(disc.DCB.Image); + if(disc.DDS != null) files.Add(disc.DDS.Image); + if(disc.DMI != null) files.Add(disc.DMI.Image); + if(disc.LastRMD != null) files.Add(disc.LastRMD.Image); + if(disc.LeadIn != null) + foreach(BorderType border in disc.LeadIn) + files.Add(border.Image); + if(disc.LeadInCdText != null) files.Add(disc.LeadInCdText.Image); + if(disc.LeadOut != null) + foreach(BorderType border in disc.LeadOut) + files.Add(border.Image); + if(disc.MediaID != null) files.Add(disc.MediaID.Image); + if(disc.PAC != null) files.Add(disc.PAC.Image); + if(disc.PFI != null) files.Add(disc.PFI.Image); + if(disc.PFIR != null) files.Add(disc.PFIR.Image); + if(disc.PMA != null) files.Add(disc.PMA.Image); + if(disc.PRI != null) files.Add(disc.PRI.Image); + if(disc.SAI != null) files.Add(disc.SAI.Image); + if(disc.TOC != null) files.Add(disc.TOC.Image); + if(disc.Track != null) files.AddRange(disc.Track.Select(track => track.Image.Value)); + + foreach(string file in files) + if(lstFilesForMedia.Contains(file)) + lstFilesForMedia.Remove(file); + } + + if(metadata.BlockMedia != null) + foreach(BlockMediaType disk in metadata.BlockMedia) + { + lstDisks.Add(new DiskEntry {path = disk.Image.Value, disk = disk}); + List files = new List {disk.Image.Value}; + if(disk.ATA?.Identify != null) files.Add(disk.ATA.Identify.Image); + if(disk.MAM != null) files.Add(disk.MAM.Image); + if(disk.PCI?.ExpansionROM != null) files.Add(disk.PCI.ExpansionROM.Image.Value); + if(disk.PCMCIA?.CIS != null) files.Add(disk.PCMCIA.CIS.Image); + if(disk.SCSI != null) + { + if(disk.SCSI.Inquiry != null) files.Add(disk.SCSI.Inquiry.Image); + if(disk.SCSI.LogSense != null) files.Add(disk.SCSI.LogSense.Image); + if(disk.SCSI.ModeSense != null) files.Add(disk.SCSI.ModeSense.Image); + if(disk.SCSI.ModeSense10 != null) files.Add(disk.SCSI.ModeSense10.Image); + if(disk.SCSI.EVPD != null) files.AddRange(disk.SCSI.EVPD.Select(evpd => evpd.Image)); + } + + if(disk.SecureDigital != null) + { + if(disk.SecureDigital.CID != null) files.Add(disk.SecureDigital.CID.Image); + if(disk.SecureDigital.CSD != null) files.Add(disk.SecureDigital.CSD.Image); + if(disk.MultiMediaCard.ExtendedCSD != null) files.Add(disk.MultiMediaCard.ExtendedCSD.Image); + } + + if(disk.TapeInformation != null) + files.AddRange(disk.TapeInformation.Select(tapePart => tapePart.Image.Value)); + if(disk.Track != null) files.AddRange(disk.Track.Select(track => track.Image.Value)); + if(disk.USB?.Descriptors != null) files.Add(disk.USB.Descriptors.Image); + + foreach(string file in files) + if(lstFilesForMedia.Contains(file)) + lstFilesForMedia.Remove(file); + } + + magazines = metadata.Magazine; + books = metadata.Book; + usermanuals = metadata.UserManual; + adverts = metadata.Advertisement; + linearmedias = metadata.LinearMedia; + pcis = metadata.PCICard; + audiomedias = metadata.AudioMedia; + } + + protected void OnChkKnownReleaseTypeToggled(object sender, EventArgs e) + { + cmbReleaseType.Enabled = chkKnownReleaseType.Checked.Value; + } + + protected void OnChkReleaseDateToggled(object sender, EventArgs e) + { + cldReleaseDate.Enabled = !chkReleaseDate.Checked.Value; + } + + protected void OnBtnAddKeywordClicked(object sender, EventArgs e) + { + lstKeywords.Add(new StringEntry {str = txtNewKeyword.Text}); + txtNewKeyword.Text = ""; + } + + protected void OnBtnRemoveKeywordClicked(object sender, EventArgs e) + { + if(treeKeywords.SelectedItem != null) lstKeywords.Remove((StringEntry)treeKeywords.SelectedItem); + } + + protected void OnBtnClearKeywordsClicked(object sender, EventArgs e) + { + lstKeywords.Clear(); + } + + protected void OnBtnAddBarcodeClicked(object sender, EventArgs e) + { + if(string.IsNullOrEmpty(cmbBarcodes.Text)) return; + + lstBarcodes.Add(new BarcodeEntry + { + code = txtNewBarcode.Text, + type = (BarcodeTypeType)Enum.Parse(typeof(BarcodeTypeType), cmbBarcodes.Text) + }); + txtNewBarcode.Text = ""; + } + + protected void OnBtnClearBarcodesClicked(object sender, EventArgs e) + { + lstBarcodes.Clear(); + } + + protected void OnBtnRemoveBarcodeClicked(object sender, EventArgs e) + { + if(treeBarcodes.SelectedItem != null) lstBarcodes.Remove((BarcodeEntry)treeBarcodes.SelectedItem); + } + + protected void OnBtnAddCategoryClicked(object sender, EventArgs e) + { + lstCategories.Add(new StringEntry {str = txtNewCategory.Text}); + txtNewCategory.Text = ""; + } + + protected void OnBtnAddSubcategoryClicked(object sender, EventArgs e) + { + lstSubcategories.Add(new StringEntry {str = txtNewSubcategory.Text}); + txtNewSubcategory.Text = ""; + } + + protected void OnBtnRemoveSubcategoryClicked(object sender, EventArgs e) + { + if(treeSubcategories.SelectedItem != null) + lstSubcategories.Remove((StringEntry)treeSubcategories.SelectedItem); + } + + protected void OnBtnClearSubcategoriesClicked(object sender, EventArgs e) + { + lstSubcategories.Clear(); + } + + protected void OnBtnRemoveCategoryClicked(object sender, EventArgs e) + { + if(treeCategories.SelectedItem != null) lstCategories.Remove((StringEntry)treeCategories.SelectedItem); + } + + protected void OnBtnClearCategoriesClicked(object sender, EventArgs e) + { + lstCategories.Clear(); + } + + protected void OnBtnAddLanguageClicked(object sender, EventArgs e) + { + if(string.IsNullOrWhiteSpace(cmbLanguages.Text)) return; + + lstLanguages.Add(new StringEntry {str = cmbLanguages.Text}); + lstLanguageTypes.Remove(cmbLanguages.Text); + } + + protected void OnBtnRemoveLanguageClicked(object sender, EventArgs e) + { + if(treeLanguages.SelectedItem == null) return; + + lstLanguageTypes.Add(((StringEntry)treeLanguages.SelectedItem).str); + lstLanguages.Remove((StringEntry)treeLanguages.SelectedItem); + } + + protected void OnBtnClearLanguagesClicked(object sender, EventArgs e) + { + lstLanguages.Clear(); + FillLanguagesCombo(); + } + + protected void OnBtnAddNewOsClicked(object sender, EventArgs e) + { + if(string.IsNullOrWhiteSpace(txtNewOsName.Text)) + { + MessageBox.Show("Operating system name cannot be empty.", MessageBoxType.Error); + return; + } + + if(string.IsNullOrWhiteSpace(txtNewOsVersion.Text)) + { + MessageBox.Show("Operating system version cannot be empty.", MessageBoxType.Error); + return; + } + + lstOses.Add(new TargetOsEntry {name = txtNewOsName.Text, version = txtNewOsVersion.Text}); + txtNewOsName.Text = ""; + txtNewOsVersion.Text = ""; + } + + protected void OnBtnClearOsesClicked(object sender, EventArgs e) + { + lstOses.Clear(); + } + + protected void OnBtnRemoveOsClicked(object sender, EventArgs e) + { + if(treeOses.SelectedItem != null) lstOses.Remove((TargetOsEntry)treeOses.SelectedItem); + } + + protected void OnBtnAddArchitectureClicked(object sender, EventArgs e) + { + if(string.IsNullOrWhiteSpace(cmbArchitectures.Text)) return; + + lstArchitectures.Add(new StringEntry {str = cmbArchitectures.Text}); + lstArchitecturesTypes.Remove(cmbArchitectures.Text); + } + + protected void OnBtnClearArchitecturesClicked(object sender, EventArgs e) + { + lstArchitectures.Clear(); + FillArchitecturesCombo(); + } + + protected void OnBtnRemoveArchitectureClicked(object sender, EventArgs e) + { + if(treeArchitectures.SelectedItem == null) return; + + lstArchitecturesTypes.Add(((StringEntry)treeArchitectures.SelectedItem).str); + lstArchitectures.Remove((StringEntry)treeArchitectures.SelectedItem); + } + + protected void OnBtnAddDiscClicked(object sender, EventArgs e) + { + /* TODO + Context.SelectedFile = cmbFilesForNewDisc.Text; + */ + tabGeneral.Visible = false; + tabKeywords.Visible = false; + tabBarcodes.Visible = false; + tabCategories.Visible = false; + tabLanguages.Visible = false; + tabTargetOs.Visible = false; + tabArchitectures.Visible = false; + tabDisks.Visible = false; + prgAddDisc1.Visible = true; + prgAddDisc2.Visible = true; + lblAddDisc1.Visible = true; + lblAddDisc2.Visible = true; + btnCancel.Visible = false; + btnOK.Visible = false; + btnEditDisc.Visible = false; + btnClearDiscs.Visible = false; + /* TODO + Workers.Failed += OnDiscAddFailed; + Workers.Finished += OnDiscAddFinished; + Workers.UpdateProgress += UpdateDiscProgress1; + Workers.UpdateProgress2 += UpdateDiscProgress2; + Context.WorkingDisc = null; + */ + btnStopAddDisc.Visible = true; + btnAddDisc.Visible = false; + btnRemoveDisc.Visible = false; + /* TODO + thdDisc = new Thread(Workers.AddMedia); + thdDisc.Start(); + */ + } + + protected void OnBtnStopAddDiscClicked(object sender, EventArgs e) + { + thdDisc?.Abort(); + stopped = true; + OnDiscAddFailed(null); + } + + void UpdateDiscProgress1(string text, string inner, long current, long maximum) + { + Application.Instance.Invoke(delegate + { + lblAddDisc1.Text = !string.IsNullOrWhiteSpace(inner) ? inner : text; + if(maximum > 0) + { + if(current < int.MinValue || current > int.MaxValue || maximum < int.MinValue || + maximum > int.MaxValue) + { + current /= 100; + maximum /= 100; + } + + prgAddDisc1.Indeterminate = false; + prgAddDisc1.MinValue = 0; + prgAddDisc1.MaxValue = (int)maximum; + prgAddDisc1.Value = (int)current; + } + else prgAddDisc1.Indeterminate = true; + }); + } + + void UpdateDiscProgress2(string text, string inner, long current, long maximum) + { + Application.Instance.Invoke(delegate + { + lblAddDisc2.Text = !string.IsNullOrWhiteSpace(inner) ? inner : text; + if(maximum > 0) + { + if(current < int.MinValue || current > int.MaxValue || maximum < int.MinValue || + maximum > int.MaxValue) + { + current /= 100; + maximum /= 100; + } + + prgAddDisc2.Indeterminate = false; + prgAddDisc2.MinValue = 0; + prgAddDisc2.MaxValue = (int)maximum; + prgAddDisc2.Value = (int)current; + } + else prgAddDisc2.Indeterminate = true; + }); + } + + void OnDiscAddFailed(string text) + { + Application.Instance.Invoke(delegate + { + if(!stopped) MessageBox.Show(text, MessageBoxType.Error); + /* TODO + Context.SelectedFile = ""; + */ + tabGeneral.Visible = true; + tabKeywords.Visible = true; + tabBarcodes.Visible = true; + tabCategories.Visible = true; + tabLanguages.Visible = true; + tabTargetOs.Visible = true; + tabArchitectures.Visible = true; + tabDisks.Visible = true; + prgAddDisc1.Visible = false; + prgAddDisc2.Visible = false; + lblAddDisc1.Visible = false; + lblAddDisc2.Visible = false; + btnCancel.Visible = true; + btnOK.Visible = true; + btnEditDisc.Visible = true; + btnClearDiscs.Visible = true; + /* TODO + Workers.Failed -= OnDiscAddFailed; + Workers.Finished -= OnDiscAddFinished; + Workers.UpdateProgress -= UpdateDiscProgress1; + Workers.UpdateProgress2 -= UpdateDiscProgress2; + Context.WorkingDisc = null; + */ + btnStopAddDisc.Visible = false; + btnAddDisc.Visible = true; + btnRemoveDisc.Visible = true; + thdDisc = null; + }); + } + + void OnDiscAddFinished() + { + Application.Instance.Invoke(delegate + { + /* TODO + if(Context.WorkingDisc == null) return; + + OpticalDiscType disc = Context.WorkingDisc; + + lstDiscs.Add(new DiscEntry {path = Context.SelectedFile, disc = disc}); + List files = new List {disc.Image.Value}; + if(disc.ADIP != null) files.Add(disc.ADIP.Image); + if(disc.ATIP != null) files.Add(disc.ATIP.Image); + if(disc.BCA != null) files.Add(disc.BCA.Image); + if(disc.CMI != null) files.Add(disc.CMI.Image); + if(disc.DCB != null) files.Add(disc.DCB.Image); + if(disc.DDS != null) files.Add(disc.DDS.Image); + if(disc.DMI != null) files.Add(disc.DMI.Image); + if(disc.LastRMD != null) files.Add(disc.LastRMD.Image); + if(disc.LeadIn != null) files.AddRange(disc.LeadIn.Select(border => border.Image)); + if(disc.LeadInCdText != null) files.Add(disc.LeadInCdText.Image); + if(disc.LeadOut != null) files.AddRange(disc.LeadOut.Select(border => border.Image)); + if(disc.MediaID != null) files.Add(disc.MediaID.Image); + if(disc.PAC != null) files.Add(disc.PAC.Image); + if(disc.PFI != null) files.Add(disc.PFI.Image); + if(disc.PFIR != null) files.Add(disc.PFIR.Image); + if(disc.PMA != null) files.Add(disc.PMA.Image); + if(disc.PRI != null) files.Add(disc.PRI.Image); + if(disc.SAI != null) files.Add(disc.SAI.Image); + if(disc.TOC != null) files.Add(disc.TOC.Image); + if(disc.Track != null) files.AddRange(disc.Track.Select(track => track.Image.Value)); + + foreach(string file in files) lstFilesForMedia.Remove(file); +*/ + /* TODO + Context.SelectedFile = ""; + */ + tabGeneral.Visible = true; + tabKeywords.Visible = true; + tabBarcodes.Visible = true; + tabCategories.Visible = true; + tabLanguages.Visible = true; + tabTargetOs.Visible = true; + tabArchitectures.Visible = true; + tabDisks.Visible = true; + prgAddDisc1.Visible = false; + prgAddDisc2.Visible = false; + lblAddDisc1.Visible = false; + lblAddDisc2.Visible = false; + btnCancel.Visible = true; + btnOK.Visible = true; + btnEditDisc.Visible = true; + btnClearDiscs.Visible = true; + /* TODO + Workers.Failed -= OnDiscAddFailed; + Workers.Finished -= OnDiscAddFinished; + Workers.UpdateProgress -= UpdateDiscProgress1; + Workers.UpdateProgress2 -= UpdateDiscProgress2; + Context.WorkingDisc = null; + */ + btnStopAddDisc.Visible = false; + btnAddDisc.Visible = true; + btnRemoveDisc.Visible = true; + thdDisc = null; + }); + } + + protected void OnBtnClearDiscsClicked(object sender, EventArgs e) + { + lstDiscs.Clear(); + // TODO: Don't add files that are in disks + FillFilesCombos(); + } + + protected void OnBtnRemoveDiscClicked(object sender, EventArgs e) + { + if(treeDiscs.SelectedItem == null) return; + + lstFilesForMedia.Add(((DiscEntry)treeDiscs.SelectedItem).path); + lstDiscs.Remove((DiscEntry)treeDiscs.SelectedItem); + } + + protected void OnBtnAddDiskClicked(object sender, EventArgs e) + { + /* TODO + Context.SelectedFile = cmbFilesForNewDisk.Text; + */ + tabGeneral.Visible = false; + tabKeywords.Visible = false; + tabBarcodes.Visible = false; + tabCategories.Visible = false; + tabLanguages.Visible = false; + tabTargetOs.Visible = false; + tabArchitectures.Visible = false; + tabDiscs.Visible = false; + prgAddDisk1.Visible = true; + prgAddDisk2.Visible = true; + lblAddDisk1.Visible = true; + lblAddDisk2.Visible = true; + btnCancel.Visible = false; + btnOK.Visible = false; + btnEditDisk.Visible = false; + btnClearDisks.Visible = false; + /* TODO + Workers.Failed += OnDiskAddFailed; + Workers.Finished += OnDiskAddFinished; + Workers.UpdateProgress += UpdateDiskProgress1; + Workers.UpdateProgress2 += UpdateDiskProgress2; + Context.WorkingDisk = null; + */ + btnStopAddDisk.Visible = true; + btnAddDisk.Visible = false; + btnRemoveDisk.Visible = false; + /* TODO + +thdDisk = new Thread(Workers.AddMedia); +thdDisk.Start(); +*/ + } + + protected void OnBtnStopAddDiskClicked(object sender, EventArgs e) + { + thdDisk?.Abort(); + stopped = true; + OnDiskAddFailed(null); + } + + void UpdateDiskProgress1(string text, string inner, long current, long maximum) + { + Application.Instance.Invoke(delegate + { + lblAddDisk1.Text = !string.IsNullOrWhiteSpace(inner) ? inner : text; + if(maximum > 0) + { + if(current < int.MinValue || current > int.MaxValue || maximum < int.MinValue || + maximum > int.MaxValue) + { + current /= 100; + maximum /= 100; + } + + prgAddDisk1.Indeterminate = false; + prgAddDisk1.MinValue = 0; + prgAddDisk1.MaxValue = (int)maximum; + prgAddDisk1.Value = (int)current; + } + else prgAddDisk1.Indeterminate = true; + }); + } + + void UpdateDiskProgress2(string text, string inner, long current, long maximum) + { + Application.Instance.Invoke(delegate + { + lblAddDisk2.Text = !string.IsNullOrWhiteSpace(inner) ? inner : text; + if(maximum > 0) + { + if(current < int.MinValue || current > int.MaxValue || maximum < int.MinValue || + maximum > int.MaxValue) + { + current /= 100; + maximum /= 100; + } + + prgAddDisk2.Indeterminate = false; + prgAddDisk2.MinValue = 0; + prgAddDisk2.MaxValue = (int)maximum; + prgAddDisk2.Value = (int)current; + } + else prgAddDisk2.Indeterminate = true; + }); + } + + void OnDiskAddFailed(string text) + { + Application.Instance.Invoke(delegate + { + if(!stopped) MessageBox.Show(text, MessageBoxType.Error); + /* TODO + Context.SelectedFile = ""; + */ + tabGeneral.Visible = true; + tabKeywords.Visible = true; + tabBarcodes.Visible = true; + tabCategories.Visible = true; + tabLanguages.Visible = true; + tabTargetOs.Visible = true; + tabArchitectures.Visible = true; + tabDiscs.Visible = true; + prgAddDisk1.Visible = false; + prgAddDisk2.Visible = false; + lblAddDisk1.Visible = false; + lblAddDisk2.Visible = false; + btnCancel.Visible = true; + btnOK.Visible = true; + btnEditDisk.Visible = true; + btnClearDisks.Visible = true; + /* TODO + Workers.Failed -= OnDiskAddFailed; + Workers.Finished -= OnDiskAddFinished; + Workers.UpdateProgress -= UpdateDiskProgress1; + Workers.UpdateProgress2 -= UpdateDiskProgress2; + Context.WorkingDisk = null; + */ + btnStopAddDisk.Visible = false; + btnAddDisk.Visible = true; + btnRemoveDisk.Visible = true; + thdDisk = null; + }); + } + + void OnDiskAddFinished() + { + Application.Instance.Invoke(delegate + { + /* TODO + if(Context.WorkingDisk == null) return; + + BlockMediaType disk = Context.WorkingDisk; + + + lstDisks.Add(new DiskEntry {path = disk.Image.Value, disk = disk}); + List files = new List {disk.Image.Value}; + if(disk.ATA?.Identify != null) files.Add(disk.ATA.Identify.Image); + if(disk.MAM != null) files.Add(disk.MAM.Image); + if(disk.PCI?.ExpansionROM != null) files.Add(disk.PCI.ExpansionROM.Image.Value); + if(disk.PCMCIA?.CIS != null) files.Add(disk.PCMCIA.CIS.Image); + if(disk.SCSI != null) + { + if(disk.SCSI.Inquiry != null) files.Add(disk.SCSI.Inquiry.Image); + if(disk.SCSI.LogSense != null) files.Add(disk.SCSI.LogSense.Image); + if(disk.SCSI.ModeSense != null) files.Add(disk.SCSI.ModeSense.Image); + if(disk.SCSI.ModeSense10 != null) files.Add(disk.SCSI.ModeSense10.Image); + if(disk.SCSI.EVPD != null) files.AddRange(disk.SCSI.EVPD.Select(evpd => evpd.Image)); + } + + if(disk.SecureDigital != null) + { + if(disk.SecureDigital.CID != null) files.Add(disk.SecureDigital.CID.Image); + if(disk.SecureDigital.CSD != null) files.Add(disk.SecureDigital.CSD.Image); + if(disk.MultiMediaCard.ExtendedCSD != null) files.Add(disk.MultiMediaCard.ExtendedCSD.Image); + } + + if(disk.TapeInformation != null) + files.AddRange(disk.TapeInformation.Select(tapePart => tapePart.Image.Value)); + if(disk.Track != null) files.AddRange(disk.Track.Select(track => track.Image.Value)); + if(disk.USB?.Descriptors != null) files.Add(disk.USB.Descriptors.Image); + + foreach(string file in files) lstFilesForMedia.Remove(file); +*/ + /* TODO + Context.SelectedFile = ""; + */ + tabGeneral.Visible = true; + tabKeywords.Visible = true; + tabBarcodes.Visible = true; + tabCategories.Visible = true; + tabLanguages.Visible = true; + tabTargetOs.Visible = true; + tabArchitectures.Visible = true; + tabDiscs.Visible = true; + prgAddDisk1.Visible = false; + prgAddDisk2.Visible = false; + lblAddDisk1.Visible = false; + lblAddDisk2.Visible = false; + btnCancel.Visible = true; + btnOK.Visible = true; + btnEditDisk.Visible = true; + btnClearDisks.Visible = true; + /* TODO + Workers.Failed -= OnDiskAddFailed; + Workers.Finished -= OnDiskAddFinished; + Workers.UpdateProgress -= UpdateDiskProgress1; + Workers.UpdateProgress2 -= UpdateDiskProgress2; + Context.WorkingDisk = null;*/ + btnStopAddDisk.Visible = false; + btnAddDisk.Visible = true; + btnRemoveDisk.Visible = true; + thdDisk = null; + }); + } + + protected void OnBtnClearDisksClicked(object sender, EventArgs e) + { + lstDisks.Clear(); + // TODO: Don't add files that are discs + FillFilesCombos(); + } + + protected void OnBtnRemoveDiskClicked(object sender, EventArgs e) + { + if(treeDisks.SelectedItem == null) return; + + lstFilesForMedia.Add(((DiskEntry)treeDisks.SelectedItem).path); + lstDisks.Remove((DiskEntry)treeDisks.SelectedItem); + } + + protected void OnBtnCancelClicked(object sender, EventArgs e) + { + modified = false; + Close(); + } + + protected void OnBtnOKClicked(object sender, EventArgs e) + { + metadata = new CICMMetadataType(); + List architectures = new List(); + List barcodes = new List(); + List disks = new List(); + List categories = new List(); + List keywords = new List(); + List languages = new List(); + List discs = new List(); + List subcategories = new List(); + List systems = new List(); + + if(!string.IsNullOrEmpty(txtAuthor.Text)) metadata.Author = txtAuthor.Text.Split(','); + if(!string.IsNullOrEmpty(txtDeveloper.Text)) metadata.Developer = txtDeveloper.Text.Split(','); + if(!string.IsNullOrEmpty(txtName.Text)) metadata.Name = txtName.Text; + if(!string.IsNullOrEmpty(txtPartNumber.Text)) metadata.PartNumber = txtPartNumber.Text; + if(!string.IsNullOrEmpty(txtPerformer.Text)) metadata.Performer = txtPerformer.Text.Split(','); + if(!string.IsNullOrEmpty(txtPublisher.Text)) metadata.Publisher = txtPublisher.Text.Split(','); + if(!string.IsNullOrEmpty(txtSerialNumber.Text)) metadata.SerialNumber = txtSerialNumber.Text; + if(!string.IsNullOrEmpty(txtVersion.Text)) metadata.Version = txtVersion.Text; + if(!chkReleaseDate.Checked.Value) + { + metadata.ReleaseDate = cldReleaseDate.Value.Value; + metadata.ReleaseDateSpecified = true; + } + + if(chkKnownReleaseType.Checked.Value) + { + metadata.ReleaseType = cmbReleaseType.SelectedValue; + metadata.ReleaseTypeSpecified = true; + } + + foreach(StringEntry entry in lstArchitectures) + architectures.Add((ArchitecturesTypeArchitecture)Enum.Parse(typeof(ArchitecturesTypeArchitecture), + entry.str)); + + foreach(BarcodeEntry entry in lstBarcodes) + { + BarcodeType barcode = new BarcodeType {type = entry.type, Value = entry.code}; + barcodes.Add(barcode); + } + + foreach(DiskEntry entry in lstDisks) disks.Add(entry.disk); + + foreach(StringEntry entry in lstCategories) categories.Add(entry.str); + + foreach(StringEntry entry in lstKeywords) keywords.Add(entry.str); + + foreach(StringEntry entry in lstLanguages) + languages.Add((LanguagesTypeLanguage)Enum.Parse(typeof(LanguagesTypeLanguage), entry.str)); + + foreach(DiscEntry entry in lstDiscs) discs.Add(entry.disc); + + foreach(StringEntry entry in lstSubcategories) subcategories.Add(entry.str); + + if(lstOses.Count > 0) + { + Dictionary> osesDict = new Dictionary>(); + foreach(TargetOsEntry entry in lstOses.OrderBy(t => t.name).ThenBy(t => t.version)) + { + osesDict.TryGetValue(entry.name, out List versList); + + if(versList == null) versList = new List(); + + if(versList.Contains(entry.version)) continue; + + versList.Add(entry.version); + versList.Sort(); + osesDict.Remove(entry.name); + osesDict.Add(entry.name, versList); + } + + metadata.RequiredOperatingSystems = osesDict + .OrderBy(t => t.Key) + .Select(entry => new RequiredOperatingSystemType + { + Name = entry.Key, + Version = entry.Value.ToArray() + }).ToArray(); + } + + if(architectures.Count > 0) metadata.Architectures = architectures.ToArray(); + if(barcodes.Count > 0) metadata.Barcodes = barcodes.ToArray(); + if(disks.Count > 0) metadata.BlockMedia = disks.ToArray(); + if(categories.Count > 0) metadata.Categories = categories.ToArray(); + if(keywords.Count > 0) metadata.Keywords = keywords.ToArray(); + if(languages.Count > 0) metadata.Languages = languages.ToArray(); + if(discs.Count > 0) metadata.OpticalDisc = discs.ToArray(); + if(subcategories.Count > 0) metadata.Subcategories = subcategories.ToArray(); + if(systems.Count > 0) metadata.Systems = systems.ToArray(); + + metadata.Magazine = magazines; + metadata.Book = books; + metadata.UserManual = usermanuals; + metadata.Advertisement = adverts; + metadata.LinearMedia = linearmedias; + metadata.PCICard = pcis; + metadata.AudioMedia = audiomedias; + + modified = true; + Close(); + } + + protected void OnBtnEditDiscClicked(object sender, EventArgs e) + { + if(treeDiscs.SelectedItem == null) return; + + dlgOpticalDisc _dlgOpticalDisc = new dlgOpticalDisc + { + Title = $"Editing disc metadata for {((DiscEntry)treeDiscs.SelectedItem).path}", + Metadata = ((DiscEntry)treeDiscs.SelectedItem).disc + }; + _dlgOpticalDisc.FillFields(); + _dlgOpticalDisc.ShowModal(this); + + if(!_dlgOpticalDisc.Modified) return; + + lstDiscs.Remove((DiscEntry)treeDiscs.SelectedItem); + lstDiscs.Add(new DiscEntry {path = _dlgOpticalDisc.Metadata.Image.Value, disc = _dlgOpticalDisc.Metadata}); + } + + protected void OnBtnEditDiskClicked(object sender, EventArgs e) + { + if(treeDisks.SelectedItem == null) return; + + dlgBlockMedia _dlgBlockMedia = new dlgBlockMedia + { + Title = $"Editing disk metadata for {((DiskEntry)treeDisks.SelectedItem).path}", + Metadata = ((DiskEntry)treeDisks.SelectedItem).disk + }; + _dlgBlockMedia.FillFields(); + _dlgBlockMedia.ShowModal(this); + + if(!_dlgBlockMedia.Modified) return; + + lstDisks.Remove((DiskEntry)treeDisks.SelectedItem); + lstDisks.Add(new DiskEntry {path = _dlgBlockMedia.Metadata.Image.Value, disk = _dlgBlockMedia.Metadata}); + } + + #region XAML UI elements + #pragma warning disable 0649 + TabPage tabGeneral; + TextBox txtDeveloper; + TextBox txtPublisher; + TextBox txtAuthor; + TextBox txtPerformer; + TextBox txtName; + TextBox txtVersion; + StackLayout stkReleaseType; + CheckBox chkKnownReleaseType; + EnumDropDown cmbReleaseType; + DateTimePicker cldReleaseDate; + CheckBox chkReleaseDate; + TextBox txtPartNumber; + TextBox txtSerialNumber; + TabPage tabKeywords; + TextBox txtNewKeyword; + GridView treeKeywords; + TabPage tabBarcodes; + TextBox txtNewBarcode; + ComboBox cmbBarcodes; + GridView treeBarcodes; + TabPage tabCategories; + TextBox txtNewCategory; + GridView treeCategories; + TextBox txtNewSubcategory; + GridView treeSubcategories; + TabPage tabLanguages; + ComboBox cmbLanguages; + GridView treeLanguages; + TabPage tabTargetOs; + TextBox txtNewOsName; + TextBox txtNewOsVersion; + GridView treeOses; + TabPage tabArchitectures; + ComboBox cmbArchitectures; + GridView treeArchitectures; + TabPage tabDiscs; + ComboBox cmbFilesForNewDisc; + Button btnAddDisc; + GridView treeDiscs; + Button btnStopAddDisc; + Button btnEditDisc; + Button btnClearDiscs; + Button btnRemoveDisc; + Label lblAddDisc1; + ProgressBar prgAddDisc1; + Label lblAddDisc2; + ProgressBar prgAddDisc2; + TabPage tabDisks; + ComboBox cmbFilesForNewDisk; + Button btnAddDisk; + GridView treeDisks; + Button btnStopAddDisk; + Button btnEditDisk; + Button btnClearDisks; + Button btnRemoveDisk; + Label lblAddDisk1; + ProgressBar prgAddDisk1; + Label lblAddDisk2; + ProgressBar prgAddDisk2; + Button btnCancel; + Button btnOK; + #pragma warning restore 0649 + #endregion XAML UI elements + } +} \ No newline at end of file diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgOpticalDisc.xeto b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgOpticalDisc.xeto new file mode 100644 index 000000000..59de361f3 --- /dev/null +++ b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgOpticalDisc.xeto @@ -0,0 +1,778 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sequenced + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Known dimensions + + + + Round? + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Has layers? + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Known dumping + hardware + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgOpticalDisc.xeto.cs b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgOpticalDisc.xeto.cs new file mode 100644 index 000000000..cb4ec08b2 --- /dev/null +++ b/CICMMetadata/CICMMetadataEditor/CICMMetadataEditor/dlgOpticalDisc.xeto.cs @@ -0,0 +1,1979 @@ +// +// Author: +// Natalia Portillo claunia@claunia.com +// +// Copyright (c) 2017-2018, © Natalia Portillo +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +// following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this list of conditions and the +// following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +// following disclaimer in the documentation and/or other materials provided with the distribution. +// * Neither the name of the [ORGANIZATION] nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +using System; +using System.Collections.ObjectModel; +using System.Linq; +using Eto.Forms; +using Eto.Serialization.Xaml; +using Schemas; +using BorderType = Schemas.BorderType; + +namespace CICMMetadataEditor +{ + public class dlgOpticalDisc : Dialog + { + ChecksumType[] checksums; + DumpHardwareType dumpHwIter; + bool editingDumpHw; + bool editingPartition; + FileSystemType filesystemIter; + ObservableCollection lstADIP; + ObservableCollection lstATIP; + ObservableCollection lstBCA; + ObservableCollection lstCDText; + ObservableCollection lstCMI; + ObservableCollection lstDCB; + ObservableCollection lstDDS; + ObservableCollection lstDI; + ObservableCollection lstDMI; + ObservableCollection lstDumpHw; + ObservableCollection lstLastRMD; + ObservableCollection lstLayers; + ObservableCollection lstLeadIns; + ObservableCollection lstLeadOuts; + ObservableCollection lstMasteringSIDs; + ObservableCollection lstMediaID; + ObservableCollection lstMouldSIDs; + ObservableCollection lstMouldTexts; + ObservableCollection lstPAC; + ObservableCollection lstPFI; + ObservableCollection lstPFIR; + ObservableCollection lstPMA; + ObservableCollection lstPRI; + ObservableCollection lstRingCodes; + ObservableCollection lstSAI; + ObservableCollection lstTOC; + ObservableCollection lstToolstamps; + ObservableCollection lstTracks; + CaseType mediaCase; + public OpticalDiscType Metadata; + public bool Modified; + PartitionType partitionIter; + ScansType scans; + TrackType trackIter; + XboxType xbox; + + public dlgOpticalDisc() + { + XamlReader.Load(this); + + Modified = false; + + #region Set partitions table + treePartitions.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Sequence).Convert(v => v.ToString()) + }, + HeaderText = "Sequence" + }); + treePartitions.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.StartSector).Convert(v => v.ToString()) + }, + HeaderText = "Start" + }); + treePartitions.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.EndSector).Convert(v => v.ToString()) + }, + HeaderText = "End" + }); + treePartitions.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Type)}, + HeaderText = "Type" + }); + treePartitions.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Name)}, + HeaderText = "Name" + }); + treePartitions.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Description)}, + HeaderText = "Description" + }); + + treePartitions.AllowMultipleSelection = false; + #endregion Set partitions table + + #region Set filesystems table + treeFilesystems.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Type)}, + HeaderText = "Type" + }); + treeFilesystems.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.VolumeName)}, + HeaderText = "Name" + }); + + treeFilesystems.AllowMultipleSelection = false; + #endregion Set filesystems table + + #region Set dump hardware table + lstDumpHw = new ObservableCollection(); + + treeDumpHardware.Columns.Add(new GridColumn + { + DataCell = + new TextBoxCell {Binding = Binding.Property(r => r.Manufacturer)}, + HeaderText = "Manufacturer" + }); + treeDumpHardware.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Model)}, + HeaderText = "Model" + }); + treeDumpHardware.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Revision)}, + HeaderText = "Revision" + }); + treeDumpHardware.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Firmware)}, + HeaderText = "Firmware" + }); + treeDumpHardware.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Serial)}, + HeaderText = "Serial" + }); + treeDumpHardware.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Software).Convert(v => v?.Name) + }, + HeaderText = "Software" + }); + treeDumpHardware.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Software).Convert(v => v?.Version) + }, + HeaderText = "Version" + }); + treeDumpHardware.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Software) + .Convert(v => v?.OperatingSystem) + }, + HeaderText = "Operating system" + }); + + treeDumpHardware.DataStore = lstDumpHw; + + treeDumpHardware.AllowMultipleSelection = false; + + treeExtents.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Start).Convert(v => v.ToString()) + }, + HeaderText = "Start" + }); + treeExtents.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.End).Convert(v => v.ToString()) + }, + HeaderText = "End" + }); + #endregion Set dump hardware table + + #region Set TOC table + lstTOC = new ObservableCollection(); + treeTOC.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeTOC.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeTOC.DataStore = lstTOC; + #endregion Set TOC table + + #region Set CD-Text table + lstCDText = new ObservableCollection(); + treeCDText.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeCDText.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeCDText.DataStore = lstCDText; + #endregion Set CD-Text table + + #region Set ATIP table + lstATIP = new ObservableCollection(); + treeATIP.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeATIP.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeATIP.DataStore = lstATIP; + #endregion Set ATIP table + + #region Set PMA table + lstPMA = new ObservableCollection(); + treePMA.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treePMA.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treePMA.DataStore = lstPMA; + #endregion Set PMA table + + #region Set PFI table + lstPFI = new ObservableCollection(); + treePFI.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treePFI.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treePFI.DataStore = lstPFI; + #endregion Set PFI table + + #region Set DMI table + lstDMI = new ObservableCollection(); + treeDMI.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeDMI.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeDMI.DataStore = lstDMI; + #endregion Set DMI table + + #region Set CMI table + lstCMI = new ObservableCollection(); + treeCMI.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeCMI.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeCMI.DataStore = lstCMI; + #endregion Set CMI table + + #region Set BCA table + lstBCA = new ObservableCollection(); + treeBCA.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeBCA.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeBCA.DataStore = lstBCA; + #endregion Set BCA table + + #region Set DCB table + lstDCB = new ObservableCollection(); + treeDCB.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeDCB.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeDCB.DataStore = lstDCB; + #endregion Set DCB table + + #region Set PRI table + lstPRI = new ObservableCollection(); + treePRI.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treePRI.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treePRI.DataStore = lstPRI; + #endregion Set PRI table + + #region Set MediaID table + lstMediaID = new ObservableCollection(); + treeMediaID.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeMediaID.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeMediaID.DataStore = lstMediaID; + #endregion Set MediaID table + + #region Set PFIR table + lstPFIR = new ObservableCollection(); + treePFIR.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treePFIR.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treePFIR.DataStore = lstPFIR; + #endregion Set PFIR table + + #region Set LastRMD table + lstLastRMD = new ObservableCollection(); + treeLastRMD.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeLastRMD.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeLastRMD.DataStore = lstLastRMD; + #endregion Set LastRMD table + + #region Set ADIP table + lstADIP = new ObservableCollection(); + treeADIP.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeADIP.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeADIP.DataStore = lstADIP; + #endregion Set ADIP table + + #region Set DDS table + lstDDS = new ObservableCollection(); + treeDDS.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeDDS.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeDDS.DataStore = lstDDS; + #endregion Set DDS table + + #region Set SAI table + lstSAI = new ObservableCollection(); + treeSAI.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeSAI.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeSAI.DataStore = lstSAI; + #endregion Set SAI table + + #region Set DI table + lstDI = new ObservableCollection(); + treeDI.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeDI.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeDI.DataStore = lstDI; + #endregion Set DI table + + #region Set PAC table + lstPAC = new ObservableCollection(); + treePAC.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treePAC.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treePAC.DataStore = lstPAC; + #endregion Set PAC table + + #region Set ring code table + lstRingCodes = new ObservableCollection(); + treeRingCodes.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.layer).Convert(v => v.ToString()) + }, + HeaderText = "Layer" + }); + treeRingCodes.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Value)}, + HeaderText = "Code" + }); + treeRingCodes.DataStore = lstRingCodes; + #endregion Set ring code table + + #region Set mastering sid table + lstMasteringSIDs = new ObservableCollection(); + treeMasteringSIDs.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.layer).Convert(v => v.ToString()) + }, + HeaderText = "Layer" + }); + treeMasteringSIDs.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Value)}, + HeaderText = "Code" + }); + treeMasteringSIDs.DataStore = lstMasteringSIDs; + #endregion Set mastering sid table + + #region Set toolstamp table + lstToolstamps = new ObservableCollection(); + treeToolstamps.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.layer).Convert(v => v.ToString()) + }, + HeaderText = "Layer" + }); + treeToolstamps.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Value)}, + HeaderText = "Code" + }); + treeToolstamps.DataStore = lstToolstamps; + #endregion Set toolstamp table + + #region Set mould sid table + lstMouldSIDs = new ObservableCollection(); + treeMouldSIDs.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.layer).Convert(v => v.ToString()) + }, + HeaderText = "Layer" + }); + treeMouldSIDs.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Value)}, + HeaderText = "Code" + }); + treeMouldSIDs.DataStore = lstMouldSIDs; + #endregion Set mould sid table + + #region Set mould text table + lstMouldTexts = new ObservableCollection(); + treeMouldTexts.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.layer).Convert(v => v.ToString()) + }, + HeaderText = "Layer" + }); + treeMouldTexts.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Value)}, + HeaderText = "Code" + }); + treeMouldTexts.DataStore = lstMouldTexts; + #endregion Set mould text table + + #region Set layer type combo box + cmbLayerType = new EnumDropDown(); + stkLayers.Items.Add(new StackLayoutItem {Control = cmbLayerType}); + #endregion Set layer type combo box + + #region Set layers table + lstLayers = new ObservableCollection(); + + treeLayers.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.layer).Convert(v => v.ToString()) + }, + HeaderText = "Layer" + }); + treeLayers.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Value).Convert(v => v.ToString()) + }, + HeaderText = "Start" + }); + + treeLayers.DataStore = lstLayers; + + treeLayers.AllowMultipleSelection = false; + #endregion Set layers table + + #region Set Lead-In table + lstLeadIns = new ObservableCollection(); + treeLeadIn.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeLeadIn.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeLeadIn.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.session).Convert(v => v.ToString()) + }, + HeaderText = "Session" + }); + treeLeadIn.DataStore = lstLeadIns; + #endregion Set Lead-In table + + #region Set Lead-Out table + lstLeadOuts = new ObservableCollection(); + treeLeadOut.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image)}, + HeaderText = "File" + }); + treeLeadOut.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeLeadOut.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.session).Convert(v => v.ToString()) + }, + HeaderText = "Session" + }); + treeLeadOut.DataStore = lstLeadOuts; + #endregion Set Lead-Out table + + #region Set tracks table + lstTracks = new ObservableCollection(); + + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Sequence.TrackNumber).Convert(v => v.ToString()) + }, + HeaderText = "Track" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Sequence.Session).Convert(v => v.ToString()) + }, + HeaderText = "Session" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image.Value)}, + HeaderText = "File" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Size).Convert(v => v.ToString()) + }, + HeaderText = "Size" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.Image.format)}, + HeaderText = "Format" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.Image.offset).Convert(v => v.ToString()) + }, + HeaderText = "Offset" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.StartMSF)}, + HeaderText = "MSF Start" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.EndMSF)}, + HeaderText = "MSF End" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.StartSector).Convert(v => v.ToString()) + }, + HeaderText = "LBA Start" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.EndSector).Convert(v => v.ToString()) + }, + HeaderText = "LBA End" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.TrackType1) + .Convert(v => v.ToString()) + }, + HeaderText = "Type" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell + { + Binding = Binding.Property(r => r.BytesPerSector).Convert(v => v.ToString()) + }, + HeaderText = "Bytes per sector" + }); + treeTracks.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r.AccoustID)}, + HeaderText = "Accoust ID" + }); + + treeTracks.DataStore = lstTracks; + + treeTracks.AllowMultipleSelection = false; + #endregion Set tracks table + + spExtentStart.MaxValue = double.MaxValue; + spExtentEnd.MaxValue = double.MaxValue; + + txtImage.ToolTip = "This is the disc image containing this media."; + txtFormat.ToolTip = "This is the format of the disc image."; + txtOffset.ToolTip = "Byte offset where the media dump starts in the disc image."; + txtSize.ToolTip = "Size of the disc dump."; + txtWriteOffset.ToolTip = "Write offset in bytes (can be negative)."; + txtMediaTracks.ToolTip = "How many tracks?"; + txtMediaSessions.ToolTip = "How many sessions?"; + txtCopyProtection.ToolTip = "Disc copy protection."; + txtDiscType.ToolTip = "Disc type."; + txtDiscSubtype.ToolTip = "Disc subtype."; + chkSequence.ToolTip = "If checked means this disc is one in a sequence of several."; + txtDiscTitle.ToolTip = "Title of disc."; + spSequence.ToolTip = "Number of this disc in the sequence."; + spTotalMedia.ToolTip = "How many diskc make the sequence."; + spSide.ToolTip = "On double sided discs, which side of the disc is represented by this dump."; + spLayer.ToolTip = + "On PTP layered discs, which layer of the side of the disc is represented by this dump."; + chkDimensions.ToolTip = "If checked, physical dimensions of disk are known."; + chkRound.ToolTip = "If checked, disk is physicaly round."; + spDiameter.ToolTip = "Diameter in milimeters of disk."; + spHeight.ToolTip = "Height in milimeters of disk."; + spWidth.ToolTip = "Width in milimeters of disk."; + spThickness.ToolTip = "Thickness in milimeters of disk."; + } + + public void FillFields() + { + if(Metadata == null) return; + + txtImage.Text = Metadata.Image.Value; + txtFormat.Text = Metadata.Image.format; + if(Metadata.Image.offsetSpecified) txtOffset.Text = Metadata.Image.offset.ToString(); + txtSize.Text = Metadata.Size.ToString(); + if(Metadata.Sequence != null) + { + lblDiscTitle.Visible = true; + lblDiscTitle.Visible = true; + lblSequence.Visible = true; + spSequence.Visible = true; + lblTotalMedia.Visible = true; + spTotalMedia.Visible = true; + lblSide.Visible = true; + spSide.Visible = true; + lblLayer.Visible = true; + spLayer.Visible = true; + chkSequence.Checked = true; + txtDiscTitle.Text = Metadata.Sequence.MediaTitle; + spSequence.Value = Metadata.Sequence.MediaSequence; + spTotalMedia.Value = Metadata.Sequence.TotalMedia; + if(Metadata.Sequence.SideSpecified) spSide.Value = Metadata.Sequence.Side; + if(Metadata.Sequence.LayerSpecified) spLayer.Value = Metadata.Sequence.Layer; + } + + if(Metadata.Layers != null) + { + chkLayers.Checked = true; + frmLayers.Visible = true; + + cmbLayerType.SelectedValue = Metadata.Layers.type; + lstLayers = new ObservableCollection(Metadata.Layers.Sectors); + treeLayers.DataStore = lstLayers; + } + + checksums = Metadata.Checksums; + xbox = Metadata.Xbox; + + if(Metadata.RingCode != null) + { + lstRingCodes = new ObservableCollection(Metadata.RingCode); + treeRingCodes.DataStore = lstRingCodes; + } + + if(Metadata.MasteringSID != null) + { + lstMasteringSIDs = new ObservableCollection(Metadata.MasteringSID); + treeMasteringSIDs.DataStore = lstMasteringSIDs; + } + + if(Metadata.Toolstamp != null) + { + lstToolstamps = new ObservableCollection(Metadata.Toolstamp); + treeToolstamps.DataStore = lstToolstamps; + } + + if(Metadata.MouldSID != null) + { + lstMouldSIDs = new ObservableCollection(Metadata.MouldSID); + treeMouldSIDs.DataStore = lstMouldSIDs; + } + + if(Metadata.MouldText != null) + { + lstMouldTexts = new ObservableCollection(Metadata.MouldText); + treeMouldTexts.DataStore = lstMouldTexts; + } + + if(Metadata.DiscType != null) txtDiscType.Text = Metadata.DiscType; + if(Metadata.DiscSubType != null) txtDiscSubtype.Text = Metadata.DiscSubType; + if(Metadata.OffsetSpecified) txtWriteOffset.Text = Metadata.Offset.ToString(); + txtMediaTracks.Text = Metadata.Tracks[0].ToString(); + txtMediaSessions.Text = Metadata.Sessions.ToString(); + if(Metadata.CopyProtection != null) txtCopyProtection.Text = Metadata.CopyProtection; + + if(Metadata.Dimensions != null) + { + chkDimensions.Checked = true; + if(Metadata.Dimensions.DiameterSpecified) + { + chkRound.Checked = true; + stkDiameter.Visible = true; + spDiameter.Value = Metadata.Dimensions.Diameter; + } + else + { + stkHeight.Visible = true; + spHeight.Value = Metadata.Dimensions.Height; + stkWidth.Visible = true; + spWidth.Value = Metadata.Dimensions.Width; + } + + stkThickness.Visible = true; + spThickness.Value = Metadata.Dimensions.Thickness; + } + + mediaCase = Metadata.Case; + scans = Metadata.Scans; + + if(Metadata.PFI != null) + { + frmPFI.Visible = true; + lstPFI.Add(Metadata.PFI); + } + + if(Metadata.DMI != null) + { + frmDMI.Visible = true; + lstDMI.Add(Metadata.DMI); + } + + if(Metadata.CMI != null) + { + frmCMI.Visible = true; + lstCMI.Add(Metadata.CMI); + } + + if(Metadata.BCA != null) + { + frmBCA.Visible = true; + lstBCA.Add(Metadata.BCA); + } + + if(Metadata.ATIP != null) + { + frmATIP.Visible = true; + lstATIP.Add(Metadata.ATIP); + } + + if(Metadata.ADIP != null) + { + frmADIP.Visible = true; + lstADIP.Add(Metadata.ADIP); + } + + if(Metadata.PMA != null) + { + frmPMA.Visible = true; + lstPMA.Add(Metadata.PMA); + } + + if(Metadata.DDS != null) + { + frmDDS.Visible = true; + lstDDS.Add(Metadata.DDS); + } + + if(Metadata.SAI != null) + { + frmSAI.Visible = true; + lstSAI.Add(Metadata.SAI); + } + + if(Metadata.LastRMD != null) + { + frmLastRMD.Visible = true; + lstLastRMD.Add(Metadata.LastRMD); + } + + if(Metadata.PRI != null) + { + frmPRI.Visible = true; + lstPRI.Add(Metadata.PRI); + } + + if(Metadata.MediaID != null) + { + frmMediaID.Visible = true; + lstMediaID.Add(Metadata.MediaID); + } + + if(Metadata.PFIR != null) + { + frmPFIR.Visible = true; + lstPFIR.Add(Metadata.PFIR); + } + + if(Metadata.DCB != null) + { + frmDCB.Visible = true; + lstDCB.Add(Metadata.DCB); + } + + if(Metadata.DI != null) + { + frmDI.Visible = true; + lstDI.Add(Metadata.DI); + } + + if(Metadata.PAC != null) + { + frmPAC.Visible = true; + lstPAC.Add(Metadata.PAC); + } + + if(Metadata.TOC != null) + { + frmTOC.Visible = true; + lstTOC.Add(Metadata.TOC); + } + + if(Metadata.LeadInCdText != null) + { + frmCDText.Visible = true; + lstCDText.Add(Metadata.LeadInCdText); + } + + if(Metadata.LeadIn != null) + { + frmLeadIns.Visible = true; + lstLeadIns = new ObservableCollection(Metadata.LeadIn); + treeLeadIn.DataStore = lstLeadIns; + } + + if(Metadata.LeadOut != null) + { + frmLeadOuts.Visible = true; + lstLeadOuts = new ObservableCollection(Metadata.LeadOut); + treeLeadOut.DataStore = lstLeadOuts; + } + + if(Metadata.PS3Encryption != null) + { + txtPS3Key.Text = Metadata.PS3Encryption.Key; + txtPS3Serial.Text = Metadata.PS3Encryption.Serial; + } + + lstTracks = new ObservableCollection(Metadata.Track); + treeTracks.DataStore = lstTracks; + + if(Metadata.DumpHardwareArray != null) + { + chkDumpHardware.Checked = true; + treeDumpHardware.Visible = true; + btnAddHardware.Visible = true; + btnEditHardware.Visible = true; + btnRemoveHardware.Visible = true; + + lstDumpHw = new ObservableCollection(Metadata.DumpHardwareArray); + treeDumpHardware.DataStore = lstDumpHw; + } + } + + protected void OnChkSequenceToggled(object sender, EventArgs e) + { + lblDiscTitle.Visible = chkSequence.Checked.Value; + txtDiscTitle.Visible = chkSequence.Checked.Value; + lblSequence.Visible = chkSequence.Checked.Value; + spSequence.Visible = chkSequence.Checked.Value; + lblTotalMedia.Visible = chkSequence.Checked.Value; + spTotalMedia.Visible = chkSequence.Checked.Value; + lblSide.Visible = chkSequence.Checked.Value; + spSide.Visible = chkSequence.Checked.Value; + lblLayer.Visible = chkSequence.Checked.Value; + spLayer.Visible = chkSequence.Checked.Value; + } + + protected void OnChkDimensionsToggled(object sender, EventArgs e) + { + chkRound.Visible = chkDimensions.Checked.Value; + stkThickness.Visible = chkDimensions.Checked.Value; + if(chkDimensions.Checked.Value) OnChkRoundToggled(sender, e); + else + { + stkDiameter.Visible = false; + stkHeight.Visible = false; + stkWidth.Visible = false; + } + } + + void OnChkRoundToggled(object sender, EventArgs e) + { + stkDiameter.Visible = chkRound.Checked.Value; + stkHeight.Visible = !chkRound.Checked.Value; + stkWidth.Visible = !chkRound.Checked.Value; + } + + protected void OnChkLayersToggled(object sender, EventArgs e) + { + frmLayers.Visible = chkLayers.Checked.Value; + } + + static void ErrorMessageBox(string text) + { + MessageBox.Show(text, MessageBoxType.Error); + } + + protected void OnBtnAddLayerClicked(object sender, EventArgs e) + { + if(string.IsNullOrWhiteSpace(txtLayerSize.Text)) ErrorMessageBox("Layer size must not be empty"); + + if(!long.TryParse(txtLayerSize.Text, out long ltmp)) ErrorMessageBox("Layer size must be a number"); + + if(ltmp < 0) ErrorMessageBox("Layer size must be a positive"); + + if(ltmp == 0) ErrorMessageBox("Layer size must be bigger than 0"); + + lstLayers.Add(new SectorsType + { + layer = (byte)spNewLayer.Value, + layerSpecified = true, + Value = ulong.Parse(txtLayerSize.Text) + }); + } + + protected void OnBtnRemoveLayerClicked(object sender, EventArgs e) + { + if(treeLayers.SelectedItem != null) lstLayers.Remove((SectorsType)treeLayers.SelectedItem); + } + + protected void OnBtnRemovePartitionClicked(object sender, EventArgs e) + { + if(treePartitions.SelectedItem != null) + ((ObservableCollection)treePartitions.DataStore).Remove((PartitionType)treePartitions + .SelectedItem); + } + + protected void OnBtnEditPartitionClicked(object sender, EventArgs e) + { + if(treePartitions.SelectedItem == null) return; + + partitionIter = (PartitionType)treePartitions.SelectedItem; + + spPartitionSequence.Value = partitionIter.Sequence; + txtPartitionStart.Text = partitionIter.StartSector.ToString(); + txtPartitionEnd.Text = partitionIter.EndSector.ToString(); + txtPartitionType.Text = partitionIter.Type; + txtPartitionName.Text = partitionIter.Name; + txtPartitionDescription.Text = partitionIter.Description; + treeFilesystems.DataStore = partitionIter.FileSystems != null + ? new ObservableCollection(partitionIter.FileSystems) + : new ObservableCollection(); + btnCancelPartition.Visible = true; + btnApplyPartition.Visible = true; + btnRemovePartition.Visible = false; + btnEditPartition.Visible = false; + btnAddPartition.Visible = false; + stkPartitionFields1.Visible = true; + stkPartitionFields2.Visible = true; + frmFilesystems.Visible = true; + + editingPartition = true; + } + + protected void OnBtnApplyPartitionClicked(object sender, EventArgs e) + { + if(!int.TryParse(txtPartitionStart.Text, out int temp)) + { + ErrorMessageBox("Partition start must be a number"); + return; + } + + if(!int.TryParse(txtPartitionEnd.Text, out int temp2)) + { + ErrorMessageBox("Partition end must be a number"); + return; + } + + if(temp2 <= temp) + { + ErrorMessageBox("Partition must end after start, and be bigger than 1 sector"); + return; + } + + if(editingPartition) ((ObservableCollection)treePartitions.DataStore).Remove(partitionIter); + partitionIter = new PartitionType + { + Sequence = (uint)spPartitionSequence.Value, + StartSector = ulong.Parse(txtPartitionStart.Text), + EndSector = ulong.Parse(txtPartitionEnd.Text), + Type = txtPartitionType.Text, + Name = txtPartitionName.Text, + Description = txtPartitionDescription.Text + }; + if(((ObservableCollection)treeFilesystems.DataStore).Count > 0) + partitionIter.FileSystems = ((ObservableCollection)treeFilesystems.DataStore).ToArray(); + + ((ObservableCollection)treePartitions.DataStore).Add(partitionIter); + btnCancelPartition.Visible = false; + btnApplyPartition.Visible = false; + btnRemovePartition.Visible = true; + btnEditPartition.Visible = true; + btnAddPartition.Visible = true; + stkPartitionFields1.Visible = false; + stkPartitionFields2.Visible = false; + frmFilesystems.Visible = false; + } + + protected void OnBtnAddPartitionClicked(object sender, EventArgs e) + { + spPartitionSequence.Value = 0; + txtPartitionStart.Text = ""; + txtPartitionEnd.Text = ""; + txtPartitionType.Text = ""; + txtPartitionName.Text = ""; + txtPartitionDescription.Text = ""; + treeFilesystems.DataStore = new ObservableCollection(); + + btnCancelPartition.Visible = true; + btnApplyPartition.Visible = true; + btnRemovePartition.Visible = false; + btnEditPartition.Visible = false; + btnAddPartition.Visible = false; + stkPartitionFields1.Visible = true; + stkPartitionFields2.Visible = true; + frmFilesystems.Visible = true; + + editingPartition = false; + } + + protected void OnBtnRemoveFilesystemClicked(object sender, EventArgs e) + { + if(treeFilesystems.SelectedItem != null) + ((ObservableCollection)treeFilesystems.DataStore).Remove((FileSystemType)treeFilesystems + .SelectedItem); + } + + protected void OnBtnEditFilesystemClicked(object sender, EventArgs e) + { + /* + if(treeFilesystems.SelectedItem == null) return; + + filesystemIter = (FileSystemType)treeFilesystems.SelectedItem; + + dlgFilesystem _dlgFilesystem = new dlgFilesystem {Metadata = filesystemIter}; + _dlgFilesystem.FillFields(); + _dlgFilesystem.ShowModal(this); + + if(!_dlgFilesystem.Modified) return; + + ((ObservableCollection)treeFilesystems.DataStore).Remove(filesystemIter); + ((ObservableCollection)treeFilesystems.DataStore).Add(_dlgFilesystem.Metadata);*/ + } + + protected void OnBtnAddFilesystemClicked(object sender, EventArgs e) + { + /* + dlgFilesystem _dlgFilesystem = new dlgFilesystem(); + _dlgFilesystem.ShowModal(this); + + if(_dlgFilesystem.Modified) + ((ObservableCollection)treeFilesystems.DataStore).Add(_dlgFilesystem.Metadata);*/ + } + + protected void OnBtnCancelTrackClicked(object sender, EventArgs e) + { + btnEditTrack.Visible = true; + btnApplyTrack.Visible = false; + btnCancelTrack.Visible = false; + + frmPartitions.Visible = false; + stkTrackFields1.Visible = false; + stkTrackFields2.Visible = false; + stkTrackFields3.Visible = false; + } + + protected void OnBtnApplyTrackClicked(object sender, EventArgs e) + { + string file = trackIter.Image.Value; + ulong filesize = trackIter.Size; + string fileformat = trackIter.Image.format; + ulong fileoffset = trackIter.Image.offset; + ChecksumType[] checksums = trackIter.Checksums; + SubChannelType subchannel = trackIter.SubChannel; + TrackTypeTrackType trackType = + (TrackTypeTrackType)Enum.Parse(typeof(TrackTypeTrackType), cmbTrackType.Text); + + lstTracks.Remove(trackIter); + + trackIter = new TrackType + { + AccoustID = txtAcoustID.Text, + BytesPerSector = uint.Parse(txtBytesPerSector.Text), + Checksums = checksums, + EndMSF = txtMSFEnd.Text, + EndSector = ulong.Parse(txtTrackEnd.Text), + Image = + new ImageType {format = fileformat, offset = fileoffset, offsetSpecified = true, Value = file}, + Sequence = + new TrackSequenceType + { + Session = uint.Parse(txtSessionSequence.Text), + TrackNumber = uint.Parse(txtTrackSequence.Text) + }, + Size = filesize, + StartMSF = txtMSFStart.Text, + StartSector = ulong.Parse(txtTrackStart.Text), + SubChannel = subchannel, + TrackType1 = trackType + }; + if(((ObservableCollection)treePartitions.DataStore).Count > 0) + trackIter.FileSystemInformation = + ((ObservableCollection)treePartitions.DataStore).ToArray(); + lstTracks.Add(trackIter); + + btnEditTrack.Visible = true; + btnApplyTrack.Visible = false; + btnCancelTrack.Visible = false; + frmPartitions.Visible = false; + stkTrackFields1.Visible = false; + stkTrackFields2.Visible = false; + stkTrackFields3.Visible = false; + } + + protected void OnBtnEditTrackClicked(object sender, EventArgs e) + { + if(treeTracks.SelectedItem == null) return; + + trackIter = (TrackType)treeTracks.SelectedItem; + + txtTrackSequence.Text = trackIter.Sequence.TrackNumber.ToString(); + txtSessionSequence.Text = trackIter.Sequence.Session.ToString(); + txtMSFStart.Text = trackIter.StartMSF; + txtMSFEnd.Text = trackIter.EndMSF; + txtTrackStart.Text = trackIter.StartSector.ToString(); + txtTrackEnd.Text = trackIter.EndSector.ToString(); + cmbTrackType.Text = trackIter.TrackType1.ToString(); + txtBytesPerSector.Text = trackIter.BytesPerSector.ToString(); + txtAcoustID.Text = trackIter.AccoustID; + treePartitions.DataStore = new ObservableCollection(trackIter.FileSystemInformation); + + btnEditTrack.Visible = false; + btnApplyTrack.Visible = true; + btnCancelTrack.Visible = true; + frmPartitions.Visible = true; + stkTrackFields1.Visible = true; + stkTrackFields2.Visible = true; + stkTrackFields3.Visible = true; + } + + protected void OnChkDumpHardwareToggled(object sender, EventArgs e) + { + treeDumpHardware.Visible = chkDumpHardware.Checked.Value; + btnAddHardware.Visible = chkDumpHardware.Checked.Value; + btnRemoveHardware.Visible = chkDumpHardware.Checked.Value; + btnEditHardware.Visible = chkDumpHardware.Checked.Value; + + btnCancelHardware.Visible = false; + btnApplyHardware.Visible = false; + frmHardware.Visible = false; + } + + protected void OnBtnCancelHardwareClicked(object sender, EventArgs e) + { + btnAddHardware.Visible = true; + btnRemoveHardware.Visible = true; + btnCancelHardware.Visible = false; + btnEditHardware.Visible = true; + btnApplyHardware.Visible = false; + frmHardware.Visible = false; + } + + protected void OnBtnRemoveHardwareClicked(object sender, EventArgs e) + { + if(treeDumpHardware.SelectedItem != null) lstDumpHw.Remove((DumpHardwareType)treeDumpHardware.SelectedItem); + } + + protected void OnBtnApplyHardwareClicked(object sender, EventArgs e) + { + if(editingDumpHw) lstDumpHw.Remove(dumpHwIter); + + dumpHwIter = new DumpHardwareType + { + Manufacturer = txtHWManufacturer.Text, + Model = txtHWModel.Text, + Revision = txtHWRevision.Text, + Firmware = txtHWFirmware.Text, + Serial = txtHWSerial.Text + }; + if(!string.IsNullOrWhiteSpace(txtDumpName.Text) || !string.IsNullOrWhiteSpace(txtDumpVersion.Text) || + !string.IsNullOrWhiteSpace(txtDumpOS.Text)) + dumpHwIter.Software = new SoftwareType + { + Name = txtDumpName.Text, + Version = txtDumpVersion.Text, + OperatingSystem = txtDumpOS.Text + }; + if(((ObservableCollection)treeExtents.DataStore).Count > 0) + dumpHwIter.Extents = ((ObservableCollection)treeExtents.DataStore).ToArray(); + + lstDumpHw.Add(dumpHwIter); + + btnAddHardware.Visible = true; + btnRemoveHardware.Visible = true; + btnCancelHardware.Visible = false; + btnEditHardware.Visible = true; + btnApplyHardware.Visible = false; + frmHardware.Visible = false; + } + + protected void OnBtnAddHardwareClicked(object sender, EventArgs e) + { + txtHWManufacturer.Text = ""; + txtHWModel.Text = ""; + txtHWRevision.Text = ""; + txtHWFirmware.Text = ""; + txtHWSerial.Text = ""; + txtDumpName.Text = ""; + txtDumpVersion.Text = ""; + txtDumpOS.Text = ""; + treeExtents.DataStore = new ObservableCollection(); + + btnAddHardware.Visible = false; + btnRemoveHardware.Visible = false; + btnCancelHardware.Visible = true; + btnEditHardware.Visible = false; + btnApplyHardware.Visible = true; + frmHardware.Visible = true; + + editingDumpHw = false; + } + + protected void OnBtnRemoveExtentClicked(object sender, EventArgs e) + { + if(treeExtents.SelectedItem != null) + ((ObservableCollection)treeExtents.DataStore).Remove((ExtentType)treeExtents.SelectedItem); + } + + protected void OnBtnEditHardwareClicked(object sender, EventArgs e) + { + if(treeDumpHardware.SelectedItem == null) return; + + dumpHwIter = (DumpHardwareType)treeDumpHardware.SelectedItem; + + txtHWManufacturer.Text = dumpHwIter.Manufacturer; + txtHWModel.Text = dumpHwIter.Model; + txtHWRevision.Text = dumpHwIter.Revision; + txtHWFirmware.Text = dumpHwIter.Firmware; + txtHWSerial.Text = dumpHwIter.Serial; + if(dumpHwIter.Software != null) + { + txtDumpName.Text = dumpHwIter.Software.Name; + txtDumpVersion.Text = dumpHwIter.Software.Version; + txtDumpOS.Text = dumpHwIter.Software.OperatingSystem; + } + + treeExtents.DataStore = new ObservableCollection(dumpHwIter.Extents); + + btnAddHardware.Visible = false; + btnRemoveHardware.Visible = false; + btnCancelHardware.Visible = true; + btnEditHardware.Visible = false; + btnApplyHardware.Visible = true; + frmHardware.Visible = true; + + editingDumpHw = true; + } + + protected void OnBtnAddExtentClicked(object sender, EventArgs e) + { + ((ObservableCollection)treeExtents.DataStore).Add(new ExtentType + { + Start = (ulong)spExtentStart.Value, + End = (ulong)spExtentEnd.Value + }); + } + + protected void OnBtnAddRingCodeClicked(object sender, EventArgs e) + { + lstRingCodes.Add(new LayeredTextType + { + layer = (uint)spRingCodeLayer.Value, + layerSpecified = true, + Value = txtRingCode.Text + }); + } + + protected void OnBtnRemoveRingCodeClicked(object sender, EventArgs e) + { + if(treeRingCodes.SelectedItem != null) lstRingCodes.Remove((LayeredTextType)treeRingCodes.SelectedItem); + } + + protected void OnBtnAddMasteringSIDClicked(object sender, EventArgs e) + { + lstMasteringSIDs.Add(new LayeredTextType + { + layer = (uint)spMasteringSIDLayer.Value, + layerSpecified = true, + Value = txtMasteringSID.Text + }); + } + + protected void OnBtnRemoveMasteringSIDClicked(object sender, EventArgs e) + { + if(treeMasteringSIDs.SelectedItem != null) + lstMasteringSIDs.Remove((LayeredTextType)treeMasteringSIDs.SelectedItem); + } + + protected void OnBtnAddToolstampClicked(object sender, EventArgs e) + { + lstToolstamps.Add(new LayeredTextType + { + layer = (uint)spToolstampLayer.Value, + layerSpecified = true, + Value = txtToolstamp.Text + }); + } + + protected void OnBtnRemoveToolstampClicked(object sender, EventArgs e) + { + if(treeToolstamps.SelectedItem != null) lstToolstamps.Remove((LayeredTextType)treeToolstamps.SelectedItem); + } + + protected void OnBtnAddMouldSIDClicked(object sender, EventArgs e) + { + lstMouldSIDs.Add(new LayeredTextType + { + layer = (uint)spMouldSIDLayer.Value, + layerSpecified = true, + Value = txtMouldSID.Text + }); + } + + protected void OnBtnRemoveMouldSIDClicked(object sender, EventArgs e) + { + if(treeMouldSIDs.SelectedItem != null) lstMouldSIDs.Remove((LayeredTextType)treeMouldSIDs.SelectedItem); + } + + protected void OnBtnAddMouldTextClicked(object sender, EventArgs e) + { + lstMouldTexts.Add(new LayeredTextType + { + layer = (uint)spMouldTextLayer.Value, + layerSpecified = true, + Value = txtMouldText.Text + }); + } + + protected void OnBtnRemoveMouldTextClicked(object sender, EventArgs e) + { + if(treeMouldTexts.SelectedItem != null) lstMouldTexts.Remove((LayeredTextType)treeMouldTexts.SelectedItem); + } + + protected void OnBtnSaveClicked(object sender, EventArgs e) + { + #region Sanity checks + if(string.IsNullOrEmpty(txtFormat.Text)) + { + ErrorMessageBox("Image format cannot be null"); + return; + } + + if(chkSequence.Checked.Value) + { + if(spSequence.Value < 1) + { + ErrorMessageBox("Media sequence must be bigger than 0"); + return; + } + + if(spTotalMedia.Value < 1) + { + ErrorMessageBox("Total medias must be bigger than 0"); + return; + } + + if(spSequence.Value > spTotalMedia.Value) + { + ErrorMessageBox("Media sequence cannot be bigger than total medias"); + return; + } + } + + if(!string.IsNullOrEmpty(txtWriteOffset.Text) && !long.TryParse(txtWriteOffset.Text, out long ltmp)) + { + ErrorMessageBox("Write offset must be a number"); + return; + } + + if(string.IsNullOrEmpty(txtMediaTracks.Text) || !long.TryParse(txtMediaTracks.Text, out ltmp)) + { + ErrorMessageBox("Tracks must be a number"); + return; + } + + if(ltmp < 1) + { + ErrorMessageBox("Tracks must be bigger than 0"); + return; + } + + if(string.IsNullOrEmpty(txtMediaSessions.Text) || !long.TryParse(txtMediaSessions.Text, out ltmp)) + { + ErrorMessageBox("Sessions must be a number"); + return; + } + + if(ltmp < 1) + { + ErrorMessageBox("Sessions must be bigger than 0"); + return; + } + + if(chkDimensions.Checked.Value) + { + if(chkRound.Checked.Value) + { + if(spDiameter.Value <= 0) + { + ErrorMessageBox("Diameter must be bigger than 0"); + return; + } + } + else + { + if(spHeight.Value <= 0) + { + ErrorMessageBox("Height must be bigger than 0"); + return; + } + + if(spWidth.Value <= 0) + { + ErrorMessageBox("Width must be bigger than 0"); + return; + } + } + + if(spThickness.Value <= 0) + { + ErrorMessageBox("Thickness must be bigger than 0"); + return; + } + } + + if(chkDumpHardware.Checked.Value) + if(lstDumpHw.Count < 1) + { + ErrorMessageBox("If dump hardware is known at least an entry must be created"); + return; + } + #endregion Sanity checks + + Metadata = new OpticalDiscType {Image = new ImageType {Value = txtImage.Text, format = txtFormat.Text}}; + + if(!string.IsNullOrWhiteSpace(txtOffset.Text) && long.TryParse(txtOffset.Text, out ltmp)) + { + Metadata.Image.offsetSpecified = true; + Metadata.Image.offset = ulong.Parse(txtOffset.Text); + } + + Metadata.Size = ulong.Parse(txtSize.Text); + + if(chkSequence.Checked.Value) + { + Metadata.Sequence = new SequenceType + { + MediaTitle = txtDiscTitle.Text, + MediaSequence = (uint)spSequence.Value, + TotalMedia = (uint)spTotalMedia.Value + }; + if(spSide.Value > 0) + { + Metadata.Sequence.SideSpecified = true; + Metadata.Sequence.Side = (byte)spSide.Value; + } + + if(spLayer.Value > 0) + { + Metadata.Sequence.LayerSpecified = true; + Metadata.Sequence.Layer = (byte)spLayer.Value; + } + } + + if(lstLayers.Count > 0) + Metadata.Layers = new LayersType + { + type = cmbLayerType.SelectedValue, + typeSpecified = true, + Sectors = lstLayers.ToArray() + }; + + Metadata.Checksums = checksums; + Metadata.Xbox = xbox; + + if(lstRingCodes.Count > 0) Metadata.RingCode = lstRingCodes.ToArray(); + + if(lstMasteringSIDs.Count > 0) Metadata.MasteringSID = lstMasteringSIDs.ToArray(); + + if(lstToolstamps.Count > 0) Metadata.Toolstamp = lstToolstamps.ToArray(); + + if(lstMouldSIDs.Count > 0) Metadata.MouldSID = lstMouldSIDs.ToArray(); + + if(lstMouldTexts.Count > 0) Metadata.MouldText = lstMouldTexts.ToArray(); + + if(!string.IsNullOrWhiteSpace(txtDiscType.Text)) Metadata.DiscType = txtDiscType.Text; + if(!string.IsNullOrWhiteSpace(txtDiscSubtype.Text)) Metadata.DiscSubType = txtDiscSubtype.Text; + if(!string.IsNullOrWhiteSpace(txtWriteOffset.Text)) + { + Metadata.Offset = int.Parse(txtWriteOffset.Text); + Metadata.OffsetSpecified = true; + } + + Metadata.Tracks = !string.IsNullOrWhiteSpace(txtMediaTracks.Text) + ? new[] {uint.Parse(txtMediaTracks.Text)} + : new[] {(uint)1}; + + Metadata.Sessions = + !string.IsNullOrWhiteSpace(txtMediaSessions.Text) ? uint.Parse(txtMediaSessions.Text) : 1; + + if(!string.IsNullOrWhiteSpace(txtCopyProtection.Text)) Metadata.CopyProtection = txtCopyProtection.Text; + + if(chkDimensions.Checked.Value) + { + Metadata.Dimensions = new DimensionsType(); + if(chkRound.Checked.Value) + { + Metadata.Dimensions.DiameterSpecified = true; + Metadata.Dimensions.Diameter = spDiameter.Value; + } + else + { + Metadata.Dimensions.HeightSpecified = true; + Metadata.Dimensions.WidthSpecified = true; + Metadata.Dimensions.Height = spHeight.Value; + Metadata.Dimensions.Width = spWidth.Value; + } + + Metadata.Dimensions.Thickness = spThickness.Value; + } + + Metadata.Case = mediaCase; + Metadata.Scans = scans; + + if(lstPFI.Count == 1) Metadata.PFI = lstPFI[0]; + if(lstDMI.Count == 1) Metadata.DMI = lstDMI[0]; + if(lstCMI.Count == 1) Metadata.CMI = lstCMI[0]; + if(lstBCA.Count == 1) Metadata.BCA = lstBCA[0]; + if(lstATIP.Count == 1) Metadata.ATIP = lstATIP[0]; + if(lstADIP.Count == 1) Metadata.ADIP = lstADIP[0]; + if(lstPMA.Count == 1) Metadata.PMA = lstPMA[0]; + if(lstDDS.Count == 1) Metadata.DDS = lstDDS[0]; + if(lstSAI.Count == 1) Metadata.SAI = lstSAI[0]; + if(lstLastRMD.Count == 1) Metadata.LastRMD = lstLastRMD[0]; + if(lstPRI.Count == 1) Metadata.PRI = lstPRI[0]; + if(lstMediaID.Count == 1) Metadata.MediaID = lstMediaID[0]; + if(lstPFIR.Count == 1) Metadata.PFIR = lstPFIR[0]; + if(lstDCB.Count == 1) Metadata.DCB = lstDCB[0]; + if(lstDI.Count == 1) Metadata.DI = lstDI[0]; + if(lstPAC.Count == 1) Metadata.PAC = lstPAC[0]; + if(lstTOC.Count == 1) Metadata.TOC = lstTOC[0]; + if(lstCDText.Count == 1) Metadata.LeadInCdText = lstCDText[0]; + + if(lstLeadIns.Count == 1) Metadata.LeadIn = lstLeadIns.ToArray(); + if(lstLeadOuts.Count == 1) Metadata.LeadOut = lstLeadOuts.ToArray(); + + if(!string.IsNullOrWhiteSpace(txtPS3Key.Text) && !string.IsNullOrWhiteSpace(txtPS3Serial.Text)) + Metadata.PS3Encryption = new PS3EncryptionType {Key = txtPS3Key.Text, Serial = txtPS3Serial.Text}; + + Metadata.Track = lstTracks.ToArray(); + + if(chkDumpHardware.Checked.Value && lstDumpHw.Count >= 1) Metadata.DumpHardwareArray = lstDumpHw.ToArray(); + + Modified = true; + Close(); + } + + protected void OnBtnCancelClicked(object sender, EventArgs e) + { + Close(); + } + + protected void OnBtnCancelPartitionClicked(object sender, EventArgs e) + { + btnCancelPartition.Visible = false; + btnApplyPartition.Visible = false; + btnRemovePartition.Visible = true; + btnEditPartition.Visible = true; + btnAddPartition.Visible = true; + stkPartitionFields1.Visible = false; + stkPartitionFields2.Visible = false; + frmFilesystems.Visible = false; + } + + #region XAML UI elements + #pragma warning disable 0649 + TextBox txtImage; + TextBox txtFormat; + TextBox txtOffset; + TextBox txtSize; + TextBox txtWriteOffset; + TextBox txtMediaTracks; + TextBox txtMediaSessions; + TextBox txtCopyProtection; + TextBox txtDiscType; + TextBox txtDiscSubtype; + CheckBox chkSequence; + Label lblDiscTitle; + TextBox txtDiscTitle; + Label lblSequence; + NumericUpDown spSequence; + Label lblTotalMedia; + NumericUpDown spTotalMedia; + Label lblSide; + NumericUpDown spSide; + Label lblLayer; + NumericUpDown spLayer; + CheckBox chkDimensions; + CheckBox chkRound; + StackLayout stkDiameter; + NumericUpDown spDiameter; + StackLayout stkHeight; + NumericUpDown spHeight; + StackLayout stkWidth; + NumericUpDown spWidth; + StackLayout stkThickness; + NumericUpDown spThickness; + CheckBox chkLayers; + StackLayout stkLayers; + EnumDropDown cmbLayerType; + GridView treeLayers; + NumericUpDown spNewLayer; + TextBox txtLayerSize; + GridView treeRingCodes; + NumericUpDown spRingCodeLayer; + TextBox txtRingCode; + GridView treeMasteringSIDs; + NumericUpDown spMasteringSIDLayer; + TextBox txtMasteringSID; + GridView treeToolstamps; + NumericUpDown spToolstampLayer; + TextBox txtToolstamp; + GridView treeMouldSIDs; + NumericUpDown spMouldSIDLayer; + TextBox txtMouldSID; + GridView treeMouldTexts; + NumericUpDown spMouldTextLayer; + TextBox txtMouldText; + GroupBox frmTOC; + GridView treeTOC; + GroupBox frmCDText; + GridView treeCDText; + GroupBox frmATIP; + GridView treeATIP; + GroupBox frmPMA; + GridView treePMA; + GroupBox frmLeadIns; + GridView treeLeadIn; + GroupBox frmLeadOuts; + GridView treeLeadOut; + GroupBox frmPFI; + GridView treePFI; + GroupBox frmDMI; + GridView treeDMI; + GroupBox frmCMI; + GridView treeCMI; + GroupBox frmBCA; + GridView treeBCA; + GroupBox frmDCB; + GridView treeDCB; + GroupBox frmPRI; + GridView treePRI; + GroupBox frmMediaID; + GridView treeMediaID; + GroupBox frmPFIR; + GridView treePFIR; + GroupBox frmLastRMD; + GridView treeLastRMD; + GroupBox frmADIP; + GridView treeADIP; + GroupBox frmDDS; + GridView treeDDS; + GroupBox frmSAI; + GridView treeSAI; + GroupBox frmDI; + GridView treeDI; + GroupBox frmPAC; + GridView treePAC; + TextBox txtPS3Key; + TextBox txtPS3Serial; + GridView treeTracks; + TextBox txtTrackStart; + TextBox txtTrackEnd; + TextBox txtMSFStart; + TextBox txtMSFEnd; + TextBox txtTrackSequence; + TextBox txtSessionSequence; + ComboBox cmbTrackType; + TextBox txtBytesPerSector; + TextBox txtAcoustID; + GridView treePartitions; + Button btnCancelPartition; + Button btnRemovePartition; + Button btnEditPartition; + Button btnApplyPartition; + Button btnAddPartition; + NumericUpDown spPartitionSequence; + TextBox txtPartitionStart; + TextBox txtPartitionEnd; + TextBox txtPartitionType; + StackLayout stkPartitionFields1; + StackLayout stkPartitionFields2; + TextBox txtPartitionName; + TextBox txtPartitionDescription; + GroupBox frmFilesystems; + GridView treeFilesystems; + Button btnCancelTrack; + Button btnApplyTrack; + Button btnEditTrack; + CheckBox chkDumpHardware; + GridView treeDumpHardware; + Button btnCancelHardware; + Button btnRemoveHardware; + Button btnEditHardware; + Button btnApplyHardware; + Button btnAddHardware; + GroupBox frmHardware; + TextBox txtHWManufacturer; + TextBox txtHWModel; + TextBox txtHWRevision; + TextBox txtHWFirmware; + TextBox txtHWSerial; + GridView treeExtents; + NumericUpDown spExtentStart; + NumericUpDown spExtentEnd; + TextBox txtDumpName; + TextBox txtDumpVersion; + TextBox txtDumpOS; + GroupBox frmLayers; + GroupBox frmPartitions; + StackLayout stkTrackFields1; + StackLayout stkTrackFields2; + StackLayout stkTrackFields3; + #pragma warning restore 0649 + #endregion XAML UI elements + } +} \ No newline at end of file diff --git a/CICMMetadata/CICMMetadataEditor/LICENSE b/CICMMetadata/CICMMetadataEditor/LICENSE new file mode 100644 index 000000000..c70268510 --- /dev/null +++ b/CICMMetadata/CICMMetadataEditor/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2017-2018, © Natalia Portillo + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the + following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the name of the [ORGANIZATION] nor the names of its contributors may be used to endorse or promote + products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/CICMMetadata/README.md b/CICMMetadata/README.md new file mode 100644 index 000000000..69ec875d8 --- /dev/null +++ b/CICMMetadata/README.md @@ -0,0 +1,28 @@ +THIS FORMAT IS DEPRECATED +========================= +This format is deprecated in its place use [Aaru](https://www.aaru.app)'s metadata. + + +Canary Islands Computer Museum +============================== +Digital Asset Metadata Sidecar +============================== + +This repository contains a XML Schema defining a digital asset metadata sidecar. +The idea of this sidecar is to accompany any kind of digital asset that may be archived in a computer museum. + +Also the repository contains autogenerated C#, VisualBasic.NET and Java code. + +The sidecar schema is under public domain as long as any change you made is compatible and upstreamed, +or you change the root element type from CICMMetadata to anything else. +Besides that, you can use it anywhere. + +If you want to give due credit, this schema is created by Natalia Portillo. + +The schema is set-oriented, that is, each sidecar file should accompany a single set, that can contain one or +more of the following elements (or newer ones): +* Magazines +* Books +* User manuals, user guides, installation guides, instruction manuals +* Optical discs (CD and successors) +* Advertisements diff --git a/CICMMetadata/build.sh b/CICMMetadata/build.sh new file mode 100755 index 000000000..bd32004dc --- /dev/null +++ b/CICMMetadata/build.sh @@ -0,0 +1,26 @@ +#!/bin/bash +xsd=`which xsd` +xjc=`which xjc` +if [ -x "$xsd" ] +then + mkdir -p dotnet + echo Building C# code... + xsd cicm.xsd /classes /language:CS > /dev/null + if [ -e "cicm.cs" ] + then + mv cicm.cs dotnet/ + fi + echo Building VB.NET code... + xsd cicm.xsd /classes /language:VB > /dev/null + if [ -e "cicm.vb" ] + then + mv cicm.vb dotnet/ + fi +fi + +if [ -x "$xjc" ] +then + mkdir -p java + echo Building Java code... + xjc -d java cicm.xsd > /dev/null +fi \ No newline at end of file diff --git a/CICMMetadata/cicm.xml b/CICMMetadata/cicm.xml new file mode 100644 index 000000000..0f110bef3 --- /dev/null +++ b/CICMMetadata/cicm.xml @@ -0,0 +1,1773 @@ + + + string + + string + + string + + string + string + + string + + Donationware + + 2007-10-26 + + + + string + + + string + + string + + + + string + + + + + + + string + + + + string + + + string + + dmVycmFudHF1ZQ== + + string + + string + + 2008-11-15 + + 7 + + + + ypk + + + 7 + + string + + + string + + + string + + + + string + string + string + string + string + string + + + + string + string + string + + + + string + string + string + + + arw + + + + + + + + + string + + + + string + + + string + + ZmVyYW50 + + string + + string + string + + 2016-01-01 + + + + kru + + + 7 + + string + + string + + + string + + + + string + string + string + string + string + string + + + + string + string + string + + + + string + string + string + + + pon + + + + + + + + string + + + + + string + + + + + dgr + + + + + string + + + + + renesasrx + + + + + + string + + string + + + + + + + + cau + + 7 + + string + + + string + + + string + + + + string + string + string + string + string + string + + + + string + string + string + + + + string + string + string + + + mao + + + + + + + string + 11 + + + string + 7 + 7 + + 2 + + 1 + + + + + 11 + + + + string + + + string + + string + + string + + string + + string + + string + + string + string + string + + 3 + + 7 + 7 + + string + + + 1.051732E7 + + 1.051732E7 + + 1.051732E7 + 1.051732E7 + + + + compacplus + + + + frontfull + + string + + + string + + + + string + string + string + string + string + string + + + + string + string + string + + + + string + string + string + + + geo + + + + + + + right + + string + + + string + + + + string + string + string + string + string + string + + + + string + string + string + + + + string + string + string + + + sme + + + + + + + + + + + boxback + + string + + + string + + + + string + string + string + string + string + string + + + + string + string + string + + + + string + string + string + + + afr + + + + + + + down + + string + + + string + + + + string + string + string + string + string + string + + + + string + string + string + + + + string + string + string + + + jpr + + + + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + + string + 11 + + + string + + + + string + 11 + + + string + + + + + 7 + 7 + + string + 11 + + + string + + + + + + + string + string + + + string + + + string + 11 + + 7 + 7 + + + string + + string + 11 + 11 + + + + 3 + + + + true + true + true + false + + + string + dvd + 7 + + string + + + string + + + + string + 11 + + + string + + + + + + + 7 + + string + + string + 11 + 11 + + string + + + + string + + 2007-09-09T03:38:42 + + 2001-07-25T22:15:31 + + 2002-05-25T15:08:08 + 7 + 11 + + 11 + false + + string + + string + + 11 + false + + 2019-05-04T04:54:29 + + 2010-04-24T16:59:19+01:00 + + string + + string + + string + + string + + string + + + + + + + string + + + + + + + string + + + + + + + + + + + string + + + + + + + string + + + + + + + + + + + + + + + + + + string + string + string + string + string + + + + 11 + 11 + + + + string + string + string + + + + + + + string + string + string + 11 + + 11 + 1.051732E7 + + 1.5E2 + + + string + + + + + + + eng + + + + + + + + sit + + + + + + + + yid + + + + + + string + + string + PAL-K + 2015-12-11T05:11:19 + + + string + string + string + + + + 1.051732E7 + 1.051732E7 + + + + + + string + 11 + + + string + + + + + string + + + string + + string + string + + 7 + + 7 + + 7 + + string + + string + string + + string + + + + 1.051732E7 + + 1.051732E7 + + 1.051732E7 + 1.051732E7 + + + + + + boxspine + + string + + + string + + + + string + string + string + string + string + string + + + + string + string + string + + + + string + string + string + + + nso + + + + + + + back + + string + + + string + + + + string + string + string + string + string + string + + + + string + string + string + + + + string + string + string + + + ale + + + + + + + + + + string + string + string + string + string + + + + 11 + 11 + + + + string + string + string + + + + + + + string + 11 + + + string + + + + string + + 5 + + 5 + + string + + string + + string + + + string + + + + 5 + 5 + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + + + string + + string + string + + 7 + + 7 + + 7 + + string + + string + string + + string + + + + 1.051732E7 + + 1.051732E7 + + 1.051732E7 + 1.051732E7 + + + + + + frontfull + + string + + + string + + + + string + string + string + string + string + string + + + + string + string + string + + + + string + string + string + + + srp + + + + + + + right + + string + + + string + + + + string + string + string + string + string + string + + + + string + string + string + + + + string + string + string + + + lub + + + + + + + + + + string + string + string + string + string + + + + 11 + 11 + + + + string + string + string + + + + + + + string + 11 + + + string + + + + string + + 5 + + 5 + + string + + string + + string + + + string + + + + + string + 11 + + + string + + + + string + + + + string + 7 + 7 + + 2 + + 1 + + + string + + string + + string + + string + + string + + string + + string + 7 + 7 + 11 + + + + 7 + + + + + + string + 11 + 11 + 11 + 11 + + + string + + + + string + 11 + 11 + 11 + 11 + 11 + + + string + + + + + + + + + inner + + string + + + string + + + + string + string + string + string + string + string + + + + string + string + string + + + + string + string + string + + + wol + + + + + + + front + + string + + + string + + + + string + string + string + string + string + string + + + + string + string + string + + + + string + string + string + + + chy + + + + + + + + + string + 11 + + + string + + + + + + 5 + 5 + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + + + string + + string + string + + 7 + + 7 + + 7 + + string + + string + string + + string + + + + 1.051732E7 + + 1.051732E7 + + 1.051732E7 + 1.051732E7 + + + + + + external + + string + + + string + + + + string + string + string + string + string + string + + + + string + string + string + + + + string + string + string + + + fre + + + + + + + right + + string + + + string + + + + string + string + string + string + string + string + + + + string + string + string + + + + string + string + string + + + swa + + + + + + + + + + string + string + string + string + string + + + + 11 + 11 + + + + string + string + string + + + + + + + string + 11 + + + string + + + + string + + 5 + + 5 + + string + + string + + string + + + string + + + + + + string + 11 + + + string + + + + string + + 5 + + 5 + + string + + string + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + string + 11 + + + string + + + + + + 5 + 5 + + + string + 11 + + + string + + + + + + string + 11 + + + string + + + + + + + + + + + + 1.051732E7 + + + + string + string + + + \ No newline at end of file diff --git a/CICMMetadata/cicm.xsd b/CICMMetadata/cicm.xsd new file mode 100644 index 000000000..2fb36d7b3 --- /dev/null +++ b/CICMMetadata/cicm.xsd @@ -0,0 +1,3419 @@ + + + + + + + + File containing the scan + + + + + Checksum of scan file pointed above + + + + + Information about scanning + + + + + Information about any scan processing done + + + + + Information about OCR + + + + + + + + + Original case type: jewel, bigjewel, dvdcase, etc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + File containing track dump, and format, binary, yranib, or audio/video container + + + + + + + + + + + + CPU architectures this set is intended to be run on + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Starting sector + + + + + Ending sector + + + + + + + + + File containing border dump + + + + + Size of border dump + + + + + Checksums of border dump + + + + + + + + + + + + + + Track information + + + + + File containing track dump, and format, binary, yranib, or audio/video container + + + + + + Size of track dump in bytes + + + + + Track sequence information + + + + + Track start address in MM:SS:FF + + + + + Track end address in MM:SS:FF + + + + + Track start sector + + + + + Track end sector + + + + + Track indexes + + + + + Track indexes + + + + + ISRC + + + + + Track type: audio, mode0, mode1, mode2 + + + + + + + + + + + + + + + + + + + Bytes per sector: 2048, 2352, 2448, etc, etc (as stored in image, not in physical + format) + + + + + + AccoustID for audio tracks + + + + + Checksums of track dump + + + + + Track's subchannel information + + + + + Information about filesystems and partitions contained in that track + + + + + + + + + + Barcodes for this magazine + + + + + Cover of this magazine + + + + + Name of this magazine + + + + + Editorial of this magazine + + + + + Publication date of this magazine + + + + + Sequential number of this magazine + + + + + Languages this magazine is written in + + + + + Pages of this magazine, including cover and back + + + + + Page size of this magazine, standard or in WxH milimeters + + + + + Scan of this magazine + + + + + + + Information about a filesystem + + + + + Filesystem type + + + + + Filesystem creation date + + + + + Filesystem last modification date + + + + + Filesystem last backup date + + + + + Bytes per cluster + + + + + Clusters in filesystem + + + + + Files in filesystem + + + + + Bootable filesystem? + + + + + Filesystem serial number + + + + + Filesystem volume name + + + + + Free clusters in filesystem + + + + + Dirty/unclean filesystem + + + + + Filesystem expiration date + + + + + Filesystem effective date + + + + + System identifier filesystem applies to + + + + + Volume set identifier + + + + + Filesystem publisher identifier + + + + + Filesystem data preparer + + + + + Filesystem application preparer + + + + + Contents of filesystem + + + + + + + + + Scanned element: cover, back, inlay, etc + + + + + + + + + + + + + + + + + + Scanning information + + + + + + + + + Array of dumped extents + + + + + + + + + Drive manufacturer + + + + + Drive model + + + + + Drive revision + + + + + Drive firmware version + + + + + Drive serial number + + + + + Extents of sectors read with this drive + + + + + Software used to read with this drive + + + + + + + File + + + + + + + + + + + + Cover file + + + + + Cover file checksum + + + + + Base64 of JPEG thumbnail + + + + + + + + + Image file, or image description file, plus format (cue, toc, etc, etc) + + + + + + Image file size + + + + + Sequence information about this disc + + + + + Layering type and sizes + + + + + Checksum of image file pointed above + + + + + Manufacturer part no. or SKU + + + + + Manufacturer serial no., not to be confused with software registration serial + number + + + + + + Disc/side ring code + + + + + Disc/side mastering SID + + + + + Disc/side toolstamp + + + + + Disc/side mould SID + + + + + Disc/side mould text + + + + + Disc type (CD, GD, SACD, DDCD, DVD, HDDVD, BD) + + + + + Disc subtype (CD-ROM, CD-DA, CD+G, etc) + + + + + Offset between subchannel servo and data sectors servo, in bytes + + + + + + Tracks on this disc/side + + + + + Sessions on this disc/side + + + + + Copy protection, if applicable + + + + + Dimensions of the disc + + + + + Case where the disk came from factory + + + + + Disc scans + + + + + Physical Manufacturing Information (DVD and HD DVD) + + + + + Disc Manufacturing Information + + + + + Lead-In Copyright Management Information + + + + + Burst Cutting Area + + + + + Absolute Time In Pre-groove + + + + + ADdress In Pre-groove + + + + + PMA + + + + + Disc Definition Structure + + + + + Spare Area Information + + + + + Last RMD + + + + + Pre-Recorded Information + + + + + Media Identification + + + + + PFI for recordables + + + + + Disc Control Blocks + + + + + Disc Information + + + + + PAC + + + + + CD TOC + + + + + CD-Text in Lead-In + + + + + Data between first Lead-In/Border-In and first data track + + + + + Lead-In, Border-In, or equivalent + + + + + Lead-Out, Border-Out, or equivalent + + + + + XGD information + + + + + PS3 Encryption Key + + + + + Media catalogue number or MCN + + + + + Array of disc tracks + + + + + Array of drives used to dump disc + + + + + + + Software used for disc reading + + + + + Software name + + + + + Software version + + + + + Operating system name and version where the software was run + + + + + + + + + Partition sequence number, starting on 1 + + + + + + + + + + Partition name if supported by partition scheme + + + + + Partition type + + + + + Partition starting sector + + + + + Partition ending sector + + + + + Partition description if supported by partition scheme + + + + + Array of filesystems contained in the partition + + + + + + + Array of drives information + + + + + Drives information + + + + + + + + + + + + + + + + + + + + + + PS3 encryption key + + + + + PS3 encryption key + + + + + + + + + XGD unlocked PFI + + + + + XGD unlocked DMI + + + + + XGD security sectors + + + + + + + + + Xbox SS Request Version + + + + + Xbox SS Request Number + + + + + XGD Security Sectors + + + + + + + Dimensions of media + + + + + Diameter in milimeters for circular discs + + + + + Height in milimeters for non-circular disks + + + + + Width in milimeters for non-circular disks + + + + + Thickness in milimeters for non-circular disks + + + + + + + Information about scanning + + + + + Who scanned it? + + + + + Who built the scanner + + + + + Scanner model + + + + + Scanner serial number + + + + + Software used for scanning + + + + + Software version + + + + + + + + + Keywords + + + + + + + + + Operating systems this set is intended to be run on + + + + + + + Sequence information about a disc + + + + + + Sequence information about this media + + + + + Media title as printed in label + + + + + Total number of discs in this set + + + + + + + + + + Side of disc described by this field + + + + + + + + + + + On PTP layering, layer of disc described by this field, starting on 0 + + + + + + + + + + + + + + Sequence information about a track + + + + + + Track number + + + + + Session this track belongs to + + + + + + + + + + + + + + Barcodes from this book + + + + + Book cover + + + + + Book name + + + + + Book publisher + + + + + Book author + + + + + Book's publication date + + + + + Book language + + + + + Book pages + + + + + Magazine page size in WxH milimeters + + + + + Scan of the book + + + + + + + + + Partition + + + + + + + + + Layering type and sizes + + + + + + + + + + + + + + + Information about dumped structure + + + + + + File containing dump + + + + + Size of dump + + + + + Checksums of dump + + + + + + + + + Array of filesystems + + + + + + + + + Minimal supported operating system + + + + + + + + Digital Asset Metadata + + + + + Developer of the set + + + + + Publisher of the set + + + + + Author/writer of the set + + + + + Performer/narrator of the set + + + + + Name of the set + + + + + Version of the set if applicable + + + + + Kind of release: OEM, Bundle, Coverdisc, Retail, Demo + + + + + + + + + + + + + + + + + + + + + Date of release in YYYY-MM-DD + + + + + Barcodes for this release + + + + + Manufacturer part no. or SKU + + + + + Manufacturer serial no., not to be confused with software registration serial + number + + + + + + Keywords + + + + + Magazine on this set + + + + + Books on this set + + + + + Categories this set belongs to + + + + + Subcategories this set belongs to + + + + + Languages this set comes in + + + + + Systems this set is designed to run on, if it includes software + + + + + CPU architectures this set is designed to run on, if it includes software + + + + + + Required operating systems and versions this set runs on, if it includes + software + + + + + + User manual/guide, installation manual/guide and any applicable entity + + + + + + Optical discs this set contains + + + + + Advertisement + + + + + Linear media (flash, ram, rom, cartridges) + + + + + Dump of a PCI/PCI-X/PCIe configuration space and/or expansion ROM + + + + + + Dump of media that is block constructed (floppy, hard drive) or abstracted (most + memory cards, flash drives, SSDs) + + + + + + Dump of media that is stored as audio, like C64/Speccy/CPC cassettes. + + + + + + + + Barcodes for this release + + + + + + + + Information about any scan processing done + + + + + + Who processed it? + + + + + Software used for processing + + + + + Software version + + + + + + + + + + + + + + + + Category of the set + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Scanned element: up, down, label, data, etc + + + + + + + + + + + + + + + Scan of disk part + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Subcategory of the set + + + + + + + User manual or user guide accompanying this set. Can be more than one. + + + + + + Language of the user manual + + + + + Pages of the user manual + + + + + Paper size in standard name or in WxH milimeters + + + + + User manual scanning + + + + + + + Checksum of file element + + + + + + + + Start and end of XGD's security sectors + + + + + + Start of XGD's security sectors + + + + + End of XGD's security sectors + + + + + + + + + Who did the OCR + + + + + Using what software + + + + + And the software version + + + + + OCR applied for which languages + + + + + + + + + Languages included in the set, ISO 3-letter code + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Track's subchannel information + + + + + File containing track's subchannel dump and format, packed, rw_raw + + + + + + Size of subchannel dump + + + + + Checksum of subchannel dump + + + + + + + + + Case scans + + + + + Disc scans + + + + + + + + + Track languages + + + + + + Track number in media container + + + + + + + + + + Track's AccoustID + + + + + Track's codec + + + + + Audio channels + + + + + Audio sampling rate + + + + + Mean bitrate, or constant bitrate, in bits per second + + + + + + + + + Track languages + + + + + + Track number in media container + + + + + + + + + + Track's codec + + + + + Horizontal resolution in pixels + + + + + Vertical resolution in pixels + + + + + Mean bitrate, or constant bitrate, in bits per second + + + + + + Is this video track in 3D? + + + + + + + + Track languages + + + + + + Track number in media container + + + + + + + + + + Track's codec + + + + + + + + Approximate latitude of recording + + + + + Approximate longitude of recording + + + + + + + + + Name of the television channel this recording was broadcasted, if applicable + + + + + + Platform that broadcasted the television channel, if applicable + + + + + Format of the source of this recording + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Date and time of broadcast + + + + + Software used to capture, process, convert, the recording + + + + + Approximate coordinates where the recording was done + + + + + + + + + Manufactured of the advertised product + + + + + Advertised product + + + + + File containing advertising + + + + + Size of file + + + + + Total video frames + + + + + Duration in seconds + + + + + Mean framerate + + + + + Checksums of advertisement + + + + + Audio tracks of advertisement + + + + + Video tracks of advertisement + + + + + Subtitle tracks of advertisement + + + + + If advertisement has been capture from a television/radio broadcast, here is the + capture information + + + + + + + + Describes a dump of a linear media, that is, a media that is read byte-by-byte like for + example, a ROM chip, a game cartridge, a PCMCIA SRAM card, etc... + + + + + + Image file, or image description file, plus format (cue, toc, etc, etc) + + + + + + Image file size + + + + + Checksums of image file + + + + + If image file contains several deinterleaved dumps, here are the checkums of the + interleaved dump + + + + + + Manufacturer part no. or SKU + + + + + Manufacturer serial no., not to be confused with software registration serial + number + + + + + + Title as it is labeled on media + + + + + Sequence of media + + + + + How many bytes must be read in image file for each byte in media + + + + + + How many bytes must be skipped in image file for each byte in media + + + + + + Media manufacturer + + + + + Media model + + + + + Media packaging (DIP, PCMCIA, Cartridge, etc) + + + + + Media interface + + + + + Dimensions of media + + + + + Scan of media + + + + + Array of hardware used to dump media + + + + + Present if media is a PCMCIA Linear Flash or SRAM card, to contain PCMCIA specific + information + + + + + + Copy protection, if applicable + + + + + + + Contains PCMCIA card information + + + + + Contains the PCMCIA Card Information Structure dump. + + + + + Contains the PCMCIA version standard compliance + + + + + Contains the PCMCIA manufacturer ID + + + + + Contains the PCMCIA card ID + + + + + Contains the PCMCIA manufacturer string + + + + + Contains the PCMCIA product name string + + + + + Contains additional PCMCIA information strings + + + + + + + Contains PCI/PCI-X/PCIe card information + + + + + Contains PCI Vendor ID + + + + + + + + + + + Contains PCI Device ID + + + + + + + + + + + Binary dump of the PCI configuration space + + + + + Binary dump of the PCI expansion rom + + + + + + + + + File containing SCSI Extended Vendor Page Descriptor dump + + + + + Size of SCSI Extended Vendor Page Descriptor dump + + + + + Checksums of SCSI Extended Vendor Page Descriptor dump + + + + + + EVPD page + + + + + + + + + + + + Contains SCSI device information + + + + + Contains SCSI INQUIRY result dump + + + + + Contains SCSI EVPD dumps + + + + + Contains SCSI MODE SENSE(6) dump + + + + + Contains SCSI MODE SENSE(10) dump + + + + + Contains SCSI LOG SENSE dump + + + + + + + Contains USB device information + + + + + Contains USB Vendor ID + + + + + + + + + + + Contains USB Product ID + + + + + + + + + + + Binary dump of the USB descriptors + + + + + + + Contains SecureDigital device information + + + + + Contains SD Card Identification Data + + + + + Contains SD Card Status Data + + + + + Contains SD Card Register + + + + + Contains SD Operation Conditions Register + + + + + + + Contains MultiMediaCard device information + + + + + Contains MultiMediaCard Card Identification Data + + + + + Contains MultiMediaCard Card Status Data + + + + + Contains MultiMediaCard extended CSD + + + + + Contains MultiMediaCard Operation Conditions Register + + + + + + + Contains ATA/ATAPI device information + + + + + Contains ATA/ATAPI IDENTIFY binary dump + + + + + + + Information about track in non-abstracted block based media + + + + + File containing track dump, and format + + + + + Size of track dump in bytes + + + + + Head (from 0) where this track resides + + + + + Cylinder where this track resides + + + + + Track start sector + + + + + Track end sector + + + + + Sectors in track. Not necessarily EndSector-StartSector, as there can be hidden + sectors + + + + + + Bytes per sector, physical undecoded tag-less + + + + + Checksums of track dump + + + + + Track format (IBM FM, IBM MFM, Amiga MFM, Apple GCR, etc) + + + + + + + Describes a dump of a block (sector) layered media + + + + + Image file, or image description file, plus format (cue, toc, etc, etc) + + + + + + Image file size + + + + + Checksums of image file + + + + + Checksums of media + + + + + Media sequence information + + + + + Media manufacturer (for fixed AND removable media) + + + + + Media model (for fixed AND removable media) + + + + + Media serial number (for fixed and, if applicable, removable media) + + + + + + Media firmware version, for fixed media only + + + + + Media physical interface, for fixed media only + + + + + Manufacturer part no. or SKU + + + + + Manufacturer serial no., not to be confused with software registration serial + number + + + + + + Physical block size in bytes + + + + + Logical block size in bytes + + + + + User accessible logical blocks + + + + + List size for variable blocks + + + + + Presents information specific about a digital tape + + + + + Media scans + + + + + If media responds to native ATA/ATAPI commands, information here + + + + + + If media is PCI/PCI-X/PCIe attached, information here + + + + + If media is PCMCIA attached, information here + + + + + If media is SecureDigital, information here + + + + + If media is MultiMediaCard, information here + + + + + If media conforms to SCSI specifications, information here + + + + + If media is USB attached, information here + + + + + Medium Auxiliary Memory + + + + + Real physical heads + + + + + Real physical cylinders + + + + + Sectors per track, if constant, if not, this field is ommited and separate tracks + must be indicated + + + + + + Tracks for block media that allow separate cylinder/head addressing, like + floppies. It can be ommitted for media that strictly follows a standard (no copy protection + either). + + + + + + Copy protection, if applicable + + + + + Dimensions of the media + + + + + Information about filesystems and partitions contained in this media + + + + + + Array of hardware used to dump media, if removable + + + + + Disk type (Floppy, Twiggy, Hard Disk) + + + + + Disk subtype + + + + + + + Information about "blocks" in audio based media + + + + + File containing block dump, and format + + + + + Size of block dump in bytes + + + + + AccoustID of block + + + + + Checksums of block dump + + + + + Block format/encoding + + + + + + + Describes a dump of a media that is stored in an audio device (like a ZX Spectrum + cassette) + + + + + + Image file, or image description file, plus format (cue, toc, etc, etc) + + + + + + Image file size + + + + + Checksums of image file + + + + + Media sequence information + + + + + Manufacturer part no. or SKU + + + + + Manufacturer serial no., not to be confused with software registration serial + number + + + + + + Media manufacturer (if known) + + + + + Media model (if known) + + + + + AccoustID of media in audio form + + + + + Blocks on audio media that uses separate blocks + + + + + Copy protection, if applicable + + + + + Dimensions of the media + + + + + Scan of media + + + + + Array of hardware used to dump media, if removable + + + + + + + + + + + + + + + + + + + + + + + + Partition information + + + + + File containing partition dump, and format, binary, yranib, or audio/video + container + + + + + + Size of partition dump in bytes + + + + + Partition sequence + + + + + Partition start block + + + + + Partition end block + + + + + Checksums of track dump + + + + + + + + + + Tape file information + + + + + File containing file dump, and format, binary, yranib, or audio/video container + + + + + + Size of file in bytes + + + + + File sequence + + + + + Size of blocks in this file + + + + + File start block + + + + + File end block + + + + + Checksums of track dump + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CICMMetadata/dotnet/cicm.cs b/CICMMetadata/dotnet/cicm.cs new file mode 100644 index 000000000..10dd7dbc0 --- /dev/null +++ b/CICMMetadata/dotnet/cicm.cs @@ -0,0 +1,9090 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +// +//This source code was auto-generated by MonoXSD +// +namespace Schemas { + + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlRootAttribute("CICMMetadata", Namespace="", IsNullable=false)] + public partial class CICMMetadataType { + + private string[] developerField; + + private string[] publisherField; + + private string[] authorField; + + private string[] performerField; + + private string nameField; + + private string versionField; + + private CICMMetadataTypeReleaseType releaseTypeField; + + private bool releaseTypeFieldSpecified; + + private System.DateTime releaseDateField; + + private bool releaseDateFieldSpecified; + + private BarcodeType[] barcodesField; + + private string partNumberField; + + private string serialNumberField; + + private string[] keywordsField; + + private MagazineType[] magazineField; + + private BookType[] bookField; + + private string[] categoriesField; + + private string[] subcategoriesField; + + private LanguagesTypeLanguage[] languagesField; + + private string[] systemsField; + + private ArchitecturesTypeArchitecture[] architecturesField; + + private RequiredOperatingSystemType[] requiredOperatingSystemsField; + + private UserManualType[] userManualField; + + private OpticalDiscType[] opticalDiscField; + + private AdvertisementType[] advertisementField; + + private LinearMediaType[] linearMediaField; + + private PCIType[] pCICardField; + + private BlockMediaType[] blockMediaField; + + private AudioMediaType[] audioMediaField; + + /// + [System.Xml.Serialization.XmlElementAttribute("Developer")] + public string[] Developer { + get { + return this.developerField; + } + set { + this.developerField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Publisher")] + public string[] Publisher { + get { + return this.publisherField; + } + set { + this.publisherField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Author")] + public string[] Author { + get { + return this.authorField; + } + set { + this.authorField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Performer")] + public string[] Performer { + get { + return this.performerField; + } + set { + this.performerField = value; + } + } + + /// + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + public string Version { + get { + return this.versionField; + } + set { + this.versionField = value; + } + } + + /// + public CICMMetadataTypeReleaseType ReleaseType { + get { + return this.releaseTypeField; + } + set { + this.releaseTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool ReleaseTypeSpecified { + get { + return this.releaseTypeFieldSpecified; + } + set { + this.releaseTypeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType="date")] + public System.DateTime ReleaseDate { + get { + return this.releaseDateField; + } + set { + this.releaseDateField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool ReleaseDateSpecified { + get { + return this.releaseDateFieldSpecified; + } + set { + this.releaseDateFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Barcode", IsNullable=false)] + public BarcodeType[] Barcodes { + get { + return this.barcodesField; + } + set { + this.barcodesField = value; + } + } + + /// + public string PartNumber { + get { + return this.partNumberField; + } + set { + this.partNumberField = value; + } + } + + /// + public string SerialNumber { + get { + return this.serialNumberField; + } + set { + this.serialNumberField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Keyword", IsNullable=false)] + public string[] Keywords { + get { + return this.keywordsField; + } + set { + this.keywordsField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Magazine")] + public MagazineType[] Magazine { + get { + return this.magazineField; + } + set { + this.magazineField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Book")] + public BookType[] Book { + get { + return this.bookField; + } + set { + this.bookField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Category", IsNullable=false)] + public string[] Categories { + get { + return this.categoriesField; + } + set { + this.categoriesField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Subcategory", IsNullable=false)] + public string[] Subcategories { + get { + return this.subcategoriesField; + } + set { + this.subcategoriesField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Language", IsNullable=false)] + public LanguagesTypeLanguage[] Languages { + get { + return this.languagesField; + } + set { + this.languagesField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("System", IsNullable=false)] + public string[] Systems { + get { + return this.systemsField; + } + set { + this.systemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Architecture", IsNullable=false)] + public ArchitecturesTypeArchitecture[] Architectures { + get { + return this.architecturesField; + } + set { + this.architecturesField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("RequiredOperatingSystem", IsNullable=false)] + public RequiredOperatingSystemType[] RequiredOperatingSystems { + get { + return this.requiredOperatingSystemsField; + } + set { + this.requiredOperatingSystemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("UserManual")] + public UserManualType[] UserManual { + get { + return this.userManualField; + } + set { + this.userManualField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("OpticalDisc")] + public OpticalDiscType[] OpticalDisc { + get { + return this.opticalDiscField; + } + set { + this.opticalDiscField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Advertisement")] + public AdvertisementType[] Advertisement { + get { + return this.advertisementField; + } + set { + this.advertisementField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("LinearMedia")] + public LinearMediaType[] LinearMedia { + get { + return this.linearMediaField; + } + set { + this.linearMediaField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("PCICard")] + public PCIType[] PCICard { + get { + return this.pCICardField; + } + set { + this.pCICardField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("BlockMedia")] + public BlockMediaType[] BlockMedia { + get { + return this.blockMediaField; + } + set { + this.blockMediaField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("AudioMedia")] + public AudioMediaType[] AudioMedia { + get { + return this.audioMediaField; + } + set { + this.audioMediaField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum CICMMetadataTypeReleaseType { + + /// + Retail, + + /// + Bundle, + + /// + Coverdisc, + + /// + Subscription, + + /// + Demo, + + /// + OEM, + + /// + Shareware, + + /// + FOSS, + + /// + Adware, + + /// + Donationware, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Digital download")] + Digitaldownload, + + /// + SaaS, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class BarcodeType { + + private BarcodeTypeType typeField; + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public BarcodeTypeType type { + get { + return this.typeField; + } + set { + this.typeField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value { + get { + return this.valueField; + } + set { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum BarcodeTypeType { + + /// + aztec, + + /// + codabar, + + /// + code11, + + /// + code128, + + /// + code39, + + /// + code93, + + /// + cpcbinary, + + /// + ezcode, + + /// + fim, + + /// + itf, + + /// + itf14, + + /// + ean13, + + /// + ean8, + + /// + maxicode, + + /// + isbn, + + /// + isrc, + + /// + msi, + + /// + tof, + + /// + shotcode, + + /// + rm4scc, + + /// + qr, + + /// + ean5, + + /// + ean2, + + /// + [System.Xml.Serialization.XmlEnumAttribute("qr")] + qr1, + + /// + postnet, + + /// + postbar, + + /// + plessey, + + /// + pharmacode, + + /// + pdf417, + + /// + patchcode, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class AudioBlockType { + + private ImageType imageField; + + private ulong sizeField; + + private string accoustIDField; + + private ChecksumType[] checksumsField; + + private string formatField; + + /// + public ImageType Image { + get { + return this.imageField; + } + set { + this.imageField = value; + } + } + + /// + public ulong Size { + get { + return this.sizeField; + } + set { + this.sizeField = value; + } + } + + /// + public string AccoustID { + get { + return this.accoustIDField; + } + set { + this.accoustIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] Checksums { + get { + return this.checksumsField; + } + set { + this.checksumsField = value; + } + } + + /// + public string Format { + get { + return this.formatField; + } + set { + this.formatField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class ImageType { + + private string formatField; + + private ulong offsetField; + + private bool offsetFieldSpecified; + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string format { + get { + return this.formatField; + } + set { + this.formatField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ulong offset { + get { + return this.offsetField; + } + set { + this.offsetField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool offsetSpecified { + get { + return this.offsetFieldSpecified; + } + set { + this.offsetFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value { + get { + return this.valueField; + } + set { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class ChecksumType { + + private ChecksumTypeType typeField; + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ChecksumTypeType type { + get { + return this.typeField; + } + set { + this.typeField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value { + get { + return this.valueField; + } + set { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum ChecksumTypeType { + + /// + fletcher16, + + /// + fletcher32, + + /// + adler32, + + /// + crc16, + + /// + crc16ccitt, + + /// + crc32, + + /// + crc64, + + /// + md4, + + /// + md5, + + /// + dm6, + + /// + ripemd128, + + /// + ripemd160, + + /// + ripemed320, + + /// + sha1, + + /// + sha224, + + /// + sha256, + + /// + sha384, + + /// + sha512, + + /// + sha3, + + /// + skein, + + /// + snefru, + + /// + blake256, + + /// + blake512, + + /// + tiger, + + /// + whirlpool, + + /// + spamsum, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class AudioMediaType { + + private ImageType imageField; + + private ulong sizeField; + + private ChecksumType[] checksumsField; + + private SequenceType sequenceField; + + private string partNumberField; + + private string serialNumberField; + + private string manufacturerField; + + private string modelField; + + private string accoustIDField; + + private AudioBlockType[] blockField; + + private string copyProtectionField; + + private DimensionsType dimensionsField; + + private ScansType scansField; + + private DumpHardwareType[] dumpHardwareArrayField; + + /// + public ImageType Image { + get { + return this.imageField; + } + set { + this.imageField = value; + } + } + + /// + public ulong Size { + get { + return this.sizeField; + } + set { + this.sizeField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] Checksums { + get { + return this.checksumsField; + } + set { + this.checksumsField = value; + } + } + + /// + public SequenceType Sequence { + get { + return this.sequenceField; + } + set { + this.sequenceField = value; + } + } + + /// + public string PartNumber { + get { + return this.partNumberField; + } + set { + this.partNumberField = value; + } + } + + /// + public string SerialNumber { + get { + return this.serialNumberField; + } + set { + this.serialNumberField = value; + } + } + + /// + public string Manufacturer { + get { + return this.manufacturerField; + } + set { + this.manufacturerField = value; + } + } + + /// + public string Model { + get { + return this.modelField; + } + set { + this.modelField = value; + } + } + + /// + public string AccoustID { + get { + return this.accoustIDField; + } + set { + this.accoustIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Block")] + public AudioBlockType[] Block { + get { + return this.blockField; + } + set { + this.blockField = value; + } + } + + /// + public string CopyProtection { + get { + return this.copyProtectionField; + } + set { + this.copyProtectionField = value; + } + } + + /// + public DimensionsType Dimensions { + get { + return this.dimensionsField; + } + set { + this.dimensionsField = value; + } + } + + /// + public ScansType Scans { + get { + return this.scansField; + } + set { + this.scansField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("DumpHardware", IsNullable=false)] + public DumpHardwareType[] DumpHardwareArray { + get { + return this.dumpHardwareArrayField; + } + set { + this.dumpHardwareArrayField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class SequenceType { + + private string mediaTitleField; + + private uint mediaSequenceField; + + private uint totalMediaField; + + private byte sideField; + + private bool sideFieldSpecified; + + private byte layerField; + + private bool layerFieldSpecified; + + /// + public string MediaTitle { + get { + return this.mediaTitleField; + } + set { + this.mediaTitleField = value; + } + } + + /// + public uint MediaSequence { + get { + return this.mediaSequenceField; + } + set { + this.mediaSequenceField = value; + } + } + + /// + public uint TotalMedia { + get { + return this.totalMediaField; + } + set { + this.totalMediaField = value; + } + } + + /// + public byte Side { + get { + return this.sideField; + } + set { + this.sideField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool SideSpecified { + get { + return this.sideFieldSpecified; + } + set { + this.sideFieldSpecified = value; + } + } + + /// + public byte Layer { + get { + return this.layerField; + } + set { + this.layerField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool LayerSpecified { + get { + return this.layerFieldSpecified; + } + set { + this.layerFieldSpecified = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class DimensionsType { + + private double diameterField; + + private bool diameterFieldSpecified; + + private double heightField; + + private bool heightFieldSpecified; + + private double widthField; + + private bool widthFieldSpecified; + + private double thicknessField; + + /// + public double Diameter { + get { + return this.diameterField; + } + set { + this.diameterField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool DiameterSpecified { + get { + return this.diameterFieldSpecified; + } + set { + this.diameterFieldSpecified = value; + } + } + + /// + public double Height { + get { + return this.heightField; + } + set { + this.heightField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool HeightSpecified { + get { + return this.heightFieldSpecified; + } + set { + this.heightFieldSpecified = value; + } + } + + /// + public double Width { + get { + return this.widthField; + } + set { + this.widthField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool WidthSpecified { + get { + return this.widthFieldSpecified; + } + set { + this.widthFieldSpecified = value; + } + } + + /// + public double Thickness { + get { + return this.thicknessField; + } + set { + this.thicknessField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class ScansType { + + private CaseScanType caseScanField; + + private MediaScanType scanField; + + /// + public CaseScanType CaseScan { + get { + return this.caseScanField; + } + set { + this.caseScanField = value; + } + } + + /// + public MediaScanType Scan { + get { + return this.scanField; + } + set { + this.scanField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class CaseScanType { + + private CaseScanTypeCaseScanElement caseScanElementField; + + private ScanType scanField; + + /// + public CaseScanTypeCaseScanElement CaseScanElement { + get { + return this.caseScanElementField; + } + set { + this.caseScanElementField = value; + } + } + + /// + public ScanType Scan { + get { + return this.scanField; + } + set { + this.scanField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum CaseScanTypeCaseScanElement { + + /// + sleeve, + + /// + inner, + + /// + inlay, + + /// + frontback, + + /// + frontfull, + + /// + boxfront, + + /// + boxback, + + /// + boxspine, + + /// + external, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class ScanType { + + private FileType fileField; + + private ChecksumType[] checksumsField; + + private ScannerType[] scannerField; + + private ScanProcessingType[] scanProcessingField; + + private OCRType[] oCRField; + + /// + public FileType File { + get { + return this.fileField; + } + set { + this.fileField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] Checksums { + get { + return this.checksumsField; + } + set { + this.checksumsField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Scanner")] + public ScannerType[] Scanner { + get { + return this.scannerField; + } + set { + this.scannerField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("ScanProcessing")] + public ScanProcessingType[] ScanProcessing { + get { + return this.scanProcessingField; + } + set { + this.scanProcessingField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("OCR")] + public OCRType[] OCR { + get { + return this.oCRField; + } + set { + this.oCRField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class FileType { + + private string formatField; + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string format { + get { + return this.formatField; + } + set { + this.formatField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value { + get { + return this.valueField; + } + set { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class ScannerType { + + private string authorField; + + private string manufacturerField; + + private string modelField; + + private string serialField; + + private string softwareField; + + private string softwareVersionField; + + /// + public string Author { + get { + return this.authorField; + } + set { + this.authorField = value; + } + } + + /// + public string Manufacturer { + get { + return this.manufacturerField; + } + set { + this.manufacturerField = value; + } + } + + /// + public string Model { + get { + return this.modelField; + } + set { + this.modelField = value; + } + } + + /// + public string Serial { + get { + return this.serialField; + } + set { + this.serialField = value; + } + } + + /// + public string Software { + get { + return this.softwareField; + } + set { + this.softwareField = value; + } + } + + /// + public string SoftwareVersion { + get { + return this.softwareVersionField; + } + set { + this.softwareVersionField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class ScanProcessingType { + + private string authorField; + + private string softwareField; + + private string softwareVersionField; + + /// + public string Author { + get { + return this.authorField; + } + set { + this.authorField = value; + } + } + + /// + public string Software { + get { + return this.softwareField; + } + set { + this.softwareField = value; + } + } + + /// + public string SoftwareVersion { + get { + return this.softwareVersionField; + } + set { + this.softwareVersionField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class OCRType { + + private string authorField; + + private string softwareField; + + private string softwareVersionField; + + private LanguagesTypeLanguage[] languageField; + + /// + public string Author { + get { + return this.authorField; + } + set { + this.authorField = value; + } + } + + /// + public string Software { + get { + return this.softwareField; + } + set { + this.softwareField = value; + } + } + + /// + public string SoftwareVersion { + get { + return this.softwareVersionField; + } + set { + this.softwareVersionField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Language", IsNullable=false)] + public LanguagesTypeLanguage[] Language { + get { + return this.languageField; + } + set { + this.languageField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum LanguagesTypeLanguage { + + /// + aar, + + /// + abk, + + /// + ace, + + /// + ach, + + /// + ada, + + /// + ady, + + /// + afa, + + /// + afh, + + /// + afr, + + /// + ain, + + /// + aka, + + /// + akk, + + /// + alb, + + /// + ale, + + /// + alg, + + /// + alt, + + /// + amh, + + /// + ang, + + /// + anp, + + /// + apa, + + /// + ara, + + /// + arc, + + /// + arg, + + /// + arm, + + /// + arn, + + /// + arp, + + /// + art, + + /// + arw, + + /// + asm, + + /// + ast, + + /// + ath, + + /// + aus, + + /// + ava, + + /// + ave, + + /// + awa, + + /// + aym, + + /// + aze, + + /// + bad, + + /// + bai, + + /// + bak, + + /// + bal, + + /// + bam, + + /// + ban, + + /// + baq, + + /// + bas, + + /// + bat, + + /// + bej, + + /// + bel, + + /// + bem, + + /// + ben, + + /// + ber, + + /// + bho, + + /// + bih, + + /// + bik, + + /// + bin, + + /// + bis, + + /// + bla, + + /// + bnt, + + /// + bos, + + /// + bra, + + /// + bre, + + /// + btk, + + /// + bua, + + /// + bug, + + /// + bul, + + /// + bur, + + /// + byn, + + /// + cad, + + /// + cai, + + /// + car, + + /// + cat, + + /// + cau, + + /// + ceb, + + /// + cel, + + /// + cha, + + /// + chb, + + /// + che, + + /// + chg, + + /// + chi, + + /// + chk, + + /// + chm, + + /// + chn, + + /// + cho, + + /// + chp, + + /// + chr, + + /// + chu, + + /// + chv, + + /// + chy, + + /// + cmc, + + /// + cop, + + /// + cor, + + /// + cos, + + /// + cpe, + + /// + cpf, + + /// + cpp, + + /// + cre, + + /// + crh, + + /// + crp, + + /// + csb, + + /// + cus, + + /// + cze, + + /// + dak, + + /// + dan, + + /// + dar, + + /// + day, + + /// + del, + + /// + den, + + /// + dgr, + + /// + din, + + /// + div, + + /// + doi, + + /// + dra, + + /// + dsb, + + /// + dua, + + /// + dum, + + /// + dut, + + /// + dyu, + + /// + dzo, + + /// + efi, + + /// + egy, + + /// + eka, + + /// + elx, + + /// + eng, + + /// + enm, + + /// + epo, + + /// + est, + + /// + ewe, + + /// + ewo, + + /// + fan, + + /// + fao, + + /// + fat, + + /// + fij, + + /// + fil, + + /// + fin, + + /// + fiu, + + /// + fon, + + /// + fre, + + /// + frm, + + /// + fro, + + /// + frr, + + /// + frs, + + /// + fry, + + /// + ful, + + /// + fur, + + /// + gaa, + + /// + gay, + + /// + gba, + + /// + gem, + + /// + geo, + + /// + ger, + + /// + gez, + + /// + gil, + + /// + gla, + + /// + gle, + + /// + glg, + + /// + glv, + + /// + gmh, + + /// + goh, + + /// + gon, + + /// + gor, + + /// + got, + + /// + grb, + + /// + grc, + + /// + gre, + + /// + grn, + + /// + gsw, + + /// + guj, + + /// + gwi, + + /// + hai, + + /// + hat, + + /// + hau, + + /// + haw, + + /// + heb, + + /// + her, + + /// + hil, + + /// + him, + + /// + hin, + + /// + hit, + + /// + hmn, + + /// + hmo, + + /// + hrv, + + /// + hsb, + + /// + hun, + + /// + hup, + + /// + iba, + + /// + ibo, + + /// + ice, + + /// + ido, + + /// + iii, + + /// + ijo, + + /// + iku, + + /// + ile, + + /// + ilo, + + /// + ina, + + /// + inc, + + /// + ind, + + /// + ine, + + /// + inh, + + /// + ipk, + + /// + ira, + + /// + iro, + + /// + ita, + + /// + jav, + + /// + jbo, + + /// + jpn, + + /// + jpr, + + /// + jrb, + + /// + kaa, + + /// + kab, + + /// + kac, + + /// + kal, + + /// + kam, + + /// + kan, + + /// + kar, + + /// + kas, + + /// + kau, + + /// + kaw, + + /// + kaz, + + /// + kbd, + + /// + kha, + + /// + khi, + + /// + khm, + + /// + kho, + + /// + kik, + + /// + kin, + + /// + kir, + + /// + kmb, + + /// + kok, + + /// + kom, + + /// + kon, + + /// + kor, + + /// + kos, + + /// + kpe, + + /// + krc, + + /// + krl, + + /// + kro, + + /// + kru, + + /// + kua, + + /// + kum, + + /// + kur, + + /// + kut, + + /// + lad, + + /// + lah, + + /// + lam, + + /// + lao, + + /// + lat, + + /// + lav, + + /// + lez, + + /// + lim, + + /// + lin, + + /// + lit, + + /// + lol, + + /// + loz, + + /// + ltz, + + /// + lua, + + /// + lub, + + /// + lug, + + /// + lui, + + /// + lun, + + /// + luo, + + /// + lus, + + /// + mac, + + /// + mad, + + /// + mag, + + /// + mah, + + /// + mai, + + /// + mak, + + /// + mal, + + /// + man, + + /// + mao, + + /// + map, + + /// + mar, + + /// + mas, + + /// + may, + + /// + mdf, + + /// + mdr, + + /// + men, + + /// + mga, + + /// + mic, + + /// + min, + + /// + mis, + + /// + mkh, + + /// + mlg, + + /// + mlt, + + /// + mnc, + + /// + mni, + + /// + mno, + + /// + moh, + + /// + mon, + + /// + mos, + + /// + mul, + + /// + mun, + + /// + mus, + + /// + mwl, + + /// + mwr, + + /// + myn, + + /// + myv, + + /// + nah, + + /// + nai, + + /// + nap, + + /// + nau, + + /// + nav, + + /// + nbl, + + /// + nde, + + /// + ndo, + + /// + nds, + + /// + nep, + + /// + @new, + + /// + nia, + + /// + nic, + + /// + niu, + + /// + nno, + + /// + nob, + + /// + nog, + + /// + non, + + /// + nor, + + /// + nqo, + + /// + nso, + + /// + nub, + + /// + nwc, + + /// + nya, + + /// + nym, + + /// + nyn, + + /// + nyo, + + /// + nzi, + + /// + oci, + + /// + oji, + + /// + ori, + + /// + orm, + + /// + osa, + + /// + oss, + + /// + ota, + + /// + oto, + + /// + paa, + + /// + pag, + + /// + pal, + + /// + pam, + + /// + pan, + + /// + pap, + + /// + pau, + + /// + peo, + + /// + per, + + /// + phi, + + /// + phn, + + /// + pli, + + /// + pol, + + /// + pon, + + /// + por, + + /// + pra, + + /// + pro, + + /// + pus, + + /// + [System.Xml.Serialization.XmlEnumAttribute("qaa-qtz")] + qaaqtz, + + /// + que, + + /// + raj, + + /// + rap, + + /// + rar, + + /// + roa, + + /// + roh, + + /// + rom, + + /// + rum, + + /// + run, + + /// + rup, + + /// + rus, + + /// + sad, + + /// + sag, + + /// + sah, + + /// + sai, + + /// + sal, + + /// + sam, + + /// + san, + + /// + sas, + + /// + sat, + + /// + scn, + + /// + sco, + + /// + sel, + + /// + sem, + + /// + sga, + + /// + sgn, + + /// + shn, + + /// + sid, + + /// + sin, + + /// + sio, + + /// + sit, + + /// + sla, + + /// + slo, + + /// + slv, + + /// + sma, + + /// + sme, + + /// + smi, + + /// + smj, + + /// + smn, + + /// + smo, + + /// + sms, + + /// + sna, + + /// + snd, + + /// + snk, + + /// + sog, + + /// + som, + + /// + son, + + /// + sot, + + /// + spa, + + /// + srd, + + /// + srn, + + /// + srp, + + /// + srr, + + /// + ssa, + + /// + ssw, + + /// + suk, + + /// + sun, + + /// + sus, + + /// + sux, + + /// + swa, + + /// + swe, + + /// + syc, + + /// + syr, + + /// + tah, + + /// + tai, + + /// + tam, + + /// + tat, + + /// + tel, + + /// + tem, + + /// + ter, + + /// + tet, + + /// + tgk, + + /// + tgl, + + /// + tha, + + /// + tib, + + /// + tig, + + /// + tir, + + /// + tiv, + + /// + tkl, + + /// + tlh, + + /// + tli, + + /// + tmh, + + /// + tog, + + /// + ton, + + /// + tpi, + + /// + tsi, + + /// + tsn, + + /// + tso, + + /// + tuk, + + /// + tum, + + /// + tup, + + /// + tur, + + /// + tut, + + /// + tvl, + + /// + twi, + + /// + tyv, + + /// + udm, + + /// + uga, + + /// + uig, + + /// + ukr, + + /// + umb, + + /// + und, + + /// + urd, + + /// + uzb, + + /// + vai, + + /// + ven, + + /// + vie, + + /// + vol, + + /// + vot, + + /// + wak, + + /// + wal, + + /// + war, + + /// + was, + + /// + wel, + + /// + wen, + + /// + wln, + + /// + wol, + + /// + xal, + + /// + xho, + + /// + yao, + + /// + yap, + + /// + yid, + + /// + yor, + + /// + ypk, + + /// + zap, + + /// + zbl, + + /// + zen, + + /// + zgh, + + /// + zha, + + /// + znd, + + /// + zul, + + /// + zun, + + /// + zxx, + + /// + zza, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class MediaScanType { + + private MediaScanTypeMediaScanElement mediaScanElementField; + + private ScanType scanField; + + /// + public MediaScanTypeMediaScanElement MediaScanElement { + get { + return this.mediaScanElementField; + } + set { + this.mediaScanElementField = value; + } + } + + /// + public ScanType Scan { + get { + return this.scanField; + } + set { + this.scanField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum MediaScanTypeMediaScanElement { + + /// + up, + + /// + down, + + /// + front, + + /// + back, + + /// + left, + + /// + right, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class DumpHardwareType { + + private string manufacturerField; + + private string modelField; + + private string revisionField; + + private string firmwareField; + + private string serialField; + + private ExtentType[] extentsField; + + private SoftwareType softwareField; + + /// + public string Manufacturer { + get { + return this.manufacturerField; + } + set { + this.manufacturerField = value; + } + } + + /// + public string Model { + get { + return this.modelField; + } + set { + this.modelField = value; + } + } + + /// + public string Revision { + get { + return this.revisionField; + } + set { + this.revisionField = value; + } + } + + /// + public string Firmware { + get { + return this.firmwareField; + } + set { + this.firmwareField = value; + } + } + + /// + public string Serial { + get { + return this.serialField; + } + set { + this.serialField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Extent", IsNullable=false)] + public ExtentType[] Extents { + get { + return this.extentsField; + } + set { + this.extentsField = value; + } + } + + /// + public SoftwareType Software { + get { + return this.softwareField; + } + set { + this.softwareField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class ExtentType { + + private ulong startField; + + private ulong endField; + + /// + public ulong Start { + get { + return this.startField; + } + set { + this.startField = value; + } + } + + /// + public ulong End { + get { + return this.endField; + } + set { + this.endField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class SoftwareType { + + private string nameField; + + private string versionField; + + private string operatingSystemField; + + /// + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + public string Version { + get { + return this.versionField; + } + set { + this.versionField = value; + } + } + + /// + public string OperatingSystem { + get { + return this.operatingSystemField; + } + set { + this.operatingSystemField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class BlockTrackType { + + private ImageType imageField; + + private ulong sizeField; + + private ushort headField; + + private uint cylinderField; + + private ulong startSectorField; + + private ulong endSectorField; + + private ulong sectorsField; + + private uint bytesPerSectorField; + + private ChecksumType[] checksumsField; + + private string formatField; + + /// + public ImageType Image { + get { + return this.imageField; + } + set { + this.imageField = value; + } + } + + /// + public ulong Size { + get { + return this.sizeField; + } + set { + this.sizeField = value; + } + } + + /// + public ushort Head { + get { + return this.headField; + } + set { + this.headField = value; + } + } + + /// + public uint Cylinder { + get { + return this.cylinderField; + } + set { + this.cylinderField = value; + } + } + + /// + public ulong StartSector { + get { + return this.startSectorField; + } + set { + this.startSectorField = value; + } + } + + /// + public ulong EndSector { + get { + return this.endSectorField; + } + set { + this.endSectorField = value; + } + } + + /// + public ulong Sectors { + get { + return this.sectorsField; + } + set { + this.sectorsField = value; + } + } + + /// + public uint BytesPerSector { + get { + return this.bytesPerSectorField; + } + set { + this.bytesPerSectorField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] Checksums { + get { + return this.checksumsField; + } + set { + this.checksumsField = value; + } + } + + /// + public string Format { + get { + return this.formatField; + } + set { + this.formatField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class USBType { + + private ushort vendorIDField; + + private ushort productIDField; + + private DumpType descriptorsField; + + /// + public ushort VendorID { + get { + return this.vendorIDField; + } + set { + this.vendorIDField = value; + } + } + + /// + public ushort ProductID { + get { + return this.productIDField; + } + set { + this.productIDField = value; + } + } + + /// + public DumpType Descriptors { + get { + return this.descriptorsField; + } + set { + this.descriptorsField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class DumpType { + + private string imageField; + + private ulong sizeField; + + private ChecksumType[] checksumsField; + + /// + public string Image { + get { + return this.imageField; + } + set { + this.imageField = value; + } + } + + /// + public ulong Size { + get { + return this.sizeField; + } + set { + this.sizeField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] Checksums { + get { + return this.checksumsField; + } + set { + this.checksumsField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class EVPDType { + + private string imageField; + + private ulong sizeField; + + private ChecksumType[] checksumsField; + + private byte pageField; + + private bool pageFieldSpecified; + + /// + public string Image { + get { + return this.imageField; + } + set { + this.imageField = value; + } + } + + /// + public ulong Size { + get { + return this.sizeField; + } + set { + this.sizeField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] Checksums { + get { + return this.checksumsField; + } + set { + this.checksumsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public byte page { + get { + return this.pageField; + } + set { + this.pageField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool pageSpecified { + get { + return this.pageFieldSpecified; + } + set { + this.pageFieldSpecified = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class SCSIType { + + private DumpType inquiryField; + + private EVPDType[] eVPDField; + + private DumpType modeSenseField; + + private DumpType modeSense10Field; + + private DumpType logSenseField; + + /// + public DumpType Inquiry { + get { + return this.inquiryField; + } + set { + this.inquiryField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("EVPD")] + public EVPDType[] EVPD { + get { + return this.eVPDField; + } + set { + this.eVPDField = value; + } + } + + /// + public DumpType ModeSense { + get { + return this.modeSenseField; + } + set { + this.modeSenseField = value; + } + } + + /// + public DumpType ModeSense10 { + get { + return this.modeSense10Field; + } + set { + this.modeSense10Field = value; + } + } + + /// + public DumpType LogSense { + get { + return this.logSenseField; + } + set { + this.logSenseField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class MultiMediaCardType { + + private DumpType cIDField; + + private DumpType cSDField; + + private DumpType extendedCSDField; + + private DumpType oCRField; + + /// + public DumpType CID { + get { + return this.cIDField; + } + set { + this.cIDField = value; + } + } + + /// + public DumpType CSD { + get { + return this.cSDField; + } + set { + this.cSDField = value; + } + } + + /// + public DumpType ExtendedCSD { + get { + return this.extendedCSDField; + } + set { + this.extendedCSDField = value; + } + } + + /// + public DumpType OCR { + get { + return this.oCRField; + } + set { + this.oCRField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class SecureDigitalType { + + private DumpType cIDField; + + private DumpType cSDField; + + private DumpType sCRField; + + private DumpType oCRField; + + /// + public DumpType CID { + get { + return this.cIDField; + } + set { + this.cIDField = value; + } + } + + /// + public DumpType CSD { + get { + return this.cSDField; + } + set { + this.cSDField = value; + } + } + + /// + public DumpType SCR { + get { + return this.sCRField; + } + set { + this.sCRField = value; + } + } + + /// + public DumpType OCR { + get { + return this.oCRField; + } + set { + this.oCRField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class ATAType { + + private DumpType identifyField; + + /// + public DumpType Identify { + get { + return this.identifyField; + } + set { + this.identifyField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class TapeFileType { + + private ImageType imageField; + + private ulong sizeField; + + private ulong sequenceField; + + private ulong blockSizeField; + + private ulong startBlockField; + + private ulong endBlockField; + + private ChecksumType[] checksumsField; + + /// + public ImageType Image { + get { + return this.imageField; + } + set { + this.imageField = value; + } + } + + /// + public ulong Size { + get { + return this.sizeField; + } + set { + this.sizeField = value; + } + } + + /// + public ulong Sequence { + get { + return this.sequenceField; + } + set { + this.sequenceField = value; + } + } + + /// + public ulong BlockSize { + get { + return this.blockSizeField; + } + set { + this.blockSizeField = value; + } + } + + /// + public ulong StartBlock { + get { + return this.startBlockField; + } + set { + this.startBlockField = value; + } + } + + /// + public ulong EndBlock { + get { + return this.endBlockField; + } + set { + this.endBlockField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] Checksums { + get { + return this.checksumsField; + } + set { + this.checksumsField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class TapePartitionType { + + private ImageType imageField; + + private ulong sizeField; + + private ulong sequenceField; + + private ulong startBlockField; + + private ulong endBlockField; + + private ChecksumType[] checksumsField; + + private TapeFileType[] fileField; + + /// + public ImageType Image { + get { + return this.imageField; + } + set { + this.imageField = value; + } + } + + /// + public ulong Size { + get { + return this.sizeField; + } + set { + this.sizeField = value; + } + } + + /// + public ulong Sequence { + get { + return this.sequenceField; + } + set { + this.sequenceField = value; + } + } + + /// + public ulong StartBlock { + get { + return this.startBlockField; + } + set { + this.startBlockField = value; + } + } + + /// + public ulong EndBlock { + get { + return this.endBlockField; + } + set { + this.endBlockField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] Checksums { + get { + return this.checksumsField; + } + set { + this.checksumsField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("File")] + public TapeFileType[] File { + get { + return this.fileField; + } + set { + this.fileField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class BlockSizeType { + + private uint startingBlockField; + + private uint valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public uint startingBlock { + get { + return this.startingBlockField; + } + set { + this.startingBlockField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public uint Value { + get { + return this.valueField; + } + set { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class BlockMediaType { + + private ImageType imageField; + + private ulong sizeField; + + private ChecksumType[] checksumsField; + + private ChecksumType[] contentChecksumsField; + + private SequenceType sequenceField; + + private string manufacturerField; + + private string modelField; + + private string serialField; + + private string firmwareField; + + private string interfaceField; + + private string partNumberField; + + private string serialNumberField; + + private uint physicalBlockSizeField; + + private uint logicalBlockSizeField; + + private ulong logicalBlocksField; + + private BlockSizeType[] variableBlockSizeField; + + private TapePartitionType[] tapeInformationField; + + private ScansType scansField; + + private ATAType aTAField; + + private PCIType pCIField; + + private PCMCIAType pCMCIAField; + + private SecureDigitalType secureDigitalField; + + private MultiMediaCardType multiMediaCardField; + + private SCSIType sCSIField; + + private USBType uSBField; + + private DumpType mAMField; + + private ushort headsField; + + private bool headsFieldSpecified; + + private uint cylindersField; + + private bool cylindersFieldSpecified; + + private ulong sectorsPerTrackField; + + private bool sectorsPerTrackFieldSpecified; + + private BlockTrackType[] trackField; + + private string copyProtectionField; + + private DimensionsType dimensionsField; + + private PartitionType[] fileSystemInformationField; + + private DumpHardwareType[] dumpHardwareArrayField; + + private string diskTypeField; + + private string diskSubTypeField; + + /// + public ImageType Image { + get { + return this.imageField; + } + set { + this.imageField = value; + } + } + + /// + public ulong Size { + get { + return this.sizeField; + } + set { + this.sizeField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] Checksums { + get { + return this.checksumsField; + } + set { + this.checksumsField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] ContentChecksums { + get { + return this.contentChecksumsField; + } + set { + this.contentChecksumsField = value; + } + } + + /// + public SequenceType Sequence { + get { + return this.sequenceField; + } + set { + this.sequenceField = value; + } + } + + /// + public string Manufacturer { + get { + return this.manufacturerField; + } + set { + this.manufacturerField = value; + } + } + + /// + public string Model { + get { + return this.modelField; + } + set { + this.modelField = value; + } + } + + /// + public string Serial { + get { + return this.serialField; + } + set { + this.serialField = value; + } + } + + /// + public string Firmware { + get { + return this.firmwareField; + } + set { + this.firmwareField = value; + } + } + + /// + public string Interface { + get { + return this.interfaceField; + } + set { + this.interfaceField = value; + } + } + + /// + public string PartNumber { + get { + return this.partNumberField; + } + set { + this.partNumberField = value; + } + } + + /// + public string SerialNumber { + get { + return this.serialNumberField; + } + set { + this.serialNumberField = value; + } + } + + /// + public uint PhysicalBlockSize { + get { + return this.physicalBlockSizeField; + } + set { + this.physicalBlockSizeField = value; + } + } + + /// + public uint LogicalBlockSize { + get { + return this.logicalBlockSizeField; + } + set { + this.logicalBlockSizeField = value; + } + } + + /// + public ulong LogicalBlocks { + get { + return this.logicalBlocksField; + } + set { + this.logicalBlocksField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("BlockSize", IsNullable=false)] + public BlockSizeType[] VariableBlockSize { + get { + return this.variableBlockSizeField; + } + set { + this.variableBlockSizeField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Partition", IsNullable=false)] + public TapePartitionType[] TapeInformation { + get { + return this.tapeInformationField; + } + set { + this.tapeInformationField = value; + } + } + + /// + public ScansType Scans { + get { + return this.scansField; + } + set { + this.scansField = value; + } + } + + /// + public ATAType ATA { + get { + return this.aTAField; + } + set { + this.aTAField = value; + } + } + + /// + public PCIType PCI { + get { + return this.pCIField; + } + set { + this.pCIField = value; + } + } + + /// + public PCMCIAType PCMCIA { + get { + return this.pCMCIAField; + } + set { + this.pCMCIAField = value; + } + } + + /// + public SecureDigitalType SecureDigital { + get { + return this.secureDigitalField; + } + set { + this.secureDigitalField = value; + } + } + + /// + public MultiMediaCardType MultiMediaCard { + get { + return this.multiMediaCardField; + } + set { + this.multiMediaCardField = value; + } + } + + /// + public SCSIType SCSI { + get { + return this.sCSIField; + } + set { + this.sCSIField = value; + } + } + + /// + public USBType USB { + get { + return this.uSBField; + } + set { + this.uSBField = value; + } + } + + /// + public DumpType MAM { + get { + return this.mAMField; + } + set { + this.mAMField = value; + } + } + + /// + public ushort Heads { + get { + return this.headsField; + } + set { + this.headsField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool HeadsSpecified { + get { + return this.headsFieldSpecified; + } + set { + this.headsFieldSpecified = value; + } + } + + /// + public uint Cylinders { + get { + return this.cylindersField; + } + set { + this.cylindersField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool CylindersSpecified { + get { + return this.cylindersFieldSpecified; + } + set { + this.cylindersFieldSpecified = value; + } + } + + /// + public ulong SectorsPerTrack { + get { + return this.sectorsPerTrackField; + } + set { + this.sectorsPerTrackField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool SectorsPerTrackSpecified { + get { + return this.sectorsPerTrackFieldSpecified; + } + set { + this.sectorsPerTrackFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Track")] + public BlockTrackType[] Track { + get { + return this.trackField; + } + set { + this.trackField = value; + } + } + + /// + public string CopyProtection { + get { + return this.copyProtectionField; + } + set { + this.copyProtectionField = value; + } + } + + /// + public DimensionsType Dimensions { + get { + return this.dimensionsField; + } + set { + this.dimensionsField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Partition", IsNullable=false)] + public PartitionType[] FileSystemInformation { + get { + return this.fileSystemInformationField; + } + set { + this.fileSystemInformationField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("DumpHardware", IsNullable=false)] + public DumpHardwareType[] DumpHardwareArray { + get { + return this.dumpHardwareArrayField; + } + set { + this.dumpHardwareArrayField = value; + } + } + + /// + public string DiskType { + get { + return this.diskTypeField; + } + set { + this.diskTypeField = value; + } + } + + /// + public string DiskSubType { + get { + return this.diskSubTypeField; + } + set { + this.diskSubTypeField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class PCIType { + + private ushort vendorIDField; + + private ushort deviceIDField; + + private DumpType configurationField; + + private LinearMediaType expansionROMField; + + /// + public ushort VendorID { + get { + return this.vendorIDField; + } + set { + this.vendorIDField = value; + } + } + + /// + public ushort DeviceID { + get { + return this.deviceIDField; + } + set { + this.deviceIDField = value; + } + } + + /// + public DumpType Configuration { + get { + return this.configurationField; + } + set { + this.configurationField = value; + } + } + + /// + public LinearMediaType ExpansionROM { + get { + return this.expansionROMField; + } + set { + this.expansionROMField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class LinearMediaType { + + private ImageType imageField; + + private ulong sizeField; + + private ChecksumType[] imageChecksumsField; + + private ChecksumType[] checksumsField; + + private string partNumberField; + + private string serialNumberField; + + private string titleField; + + private uint sequenceField; + + private bool sequenceFieldSpecified; + + private uint imageInterleaveField; + + private bool imageInterleaveFieldSpecified; + + private uint interleaveField; + + private bool interleaveFieldSpecified; + + private string manufacturerField; + + private string modelField; + + private string packageField; + + private string interfaceField; + + private DimensionsType dimensionsField; + + private ScansType scansField; + + private DumpHardwareType[] dumpHardwareArrayField; + + private PCMCIAType pCMCIAField; + + private string copyProtectionField; + + /// + public ImageType Image { + get { + return this.imageField; + } + set { + this.imageField = value; + } + } + + /// + public ulong Size { + get { + return this.sizeField; + } + set { + this.sizeField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] ImageChecksums { + get { + return this.imageChecksumsField; + } + set { + this.imageChecksumsField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] Checksums { + get { + return this.checksumsField; + } + set { + this.checksumsField = value; + } + } + + /// + public string PartNumber { + get { + return this.partNumberField; + } + set { + this.partNumberField = value; + } + } + + /// + public string SerialNumber { + get { + return this.serialNumberField; + } + set { + this.serialNumberField = value; + } + } + + /// + public string Title { + get { + return this.titleField; + } + set { + this.titleField = value; + } + } + + /// + public uint Sequence { + get { + return this.sequenceField; + } + set { + this.sequenceField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool SequenceSpecified { + get { + return this.sequenceFieldSpecified; + } + set { + this.sequenceFieldSpecified = value; + } + } + + /// + public uint ImageInterleave { + get { + return this.imageInterleaveField; + } + set { + this.imageInterleaveField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool ImageInterleaveSpecified { + get { + return this.imageInterleaveFieldSpecified; + } + set { + this.imageInterleaveFieldSpecified = value; + } + } + + /// + public uint Interleave { + get { + return this.interleaveField; + } + set { + this.interleaveField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool InterleaveSpecified { + get { + return this.interleaveFieldSpecified; + } + set { + this.interleaveFieldSpecified = value; + } + } + + /// + public string Manufacturer { + get { + return this.manufacturerField; + } + set { + this.manufacturerField = value; + } + } + + /// + public string Model { + get { + return this.modelField; + } + set { + this.modelField = value; + } + } + + /// + public string Package { + get { + return this.packageField; + } + set { + this.packageField = value; + } + } + + /// + public string Interface { + get { + return this.interfaceField; + } + set { + this.interfaceField = value; + } + } + + /// + public DimensionsType Dimensions { + get { + return this.dimensionsField; + } + set { + this.dimensionsField = value; + } + } + + /// + public ScansType Scans { + get { + return this.scansField; + } + set { + this.scansField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("DumpHardware", IsNullable=false)] + public DumpHardwareType[] DumpHardwareArray { + get { + return this.dumpHardwareArrayField; + } + set { + this.dumpHardwareArrayField = value; + } + } + + /// + public PCMCIAType PCMCIA { + get { + return this.pCMCIAField; + } + set { + this.pCMCIAField = value; + } + } + + /// + public string CopyProtection { + get { + return this.copyProtectionField; + } + set { + this.copyProtectionField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class PCMCIAType { + + private DumpType cISField; + + private string complianceField; + + private ushort manufacturerCodeField; + + private bool manufacturerCodeFieldSpecified; + + private ushort cardCodeField; + + private bool cardCodeFieldSpecified; + + private string manufacturerField; + + private string productNameField; + + private string[] additionalInformationField; + + /// + public DumpType CIS { + get { + return this.cISField; + } + set { + this.cISField = value; + } + } + + /// + public string Compliance { + get { + return this.complianceField; + } + set { + this.complianceField = value; + } + } + + /// + public ushort ManufacturerCode { + get { + return this.manufacturerCodeField; + } + set { + this.manufacturerCodeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool ManufacturerCodeSpecified { + get { + return this.manufacturerCodeFieldSpecified; + } + set { + this.manufacturerCodeFieldSpecified = value; + } + } + + /// + public ushort CardCode { + get { + return this.cardCodeField; + } + set { + this.cardCodeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool CardCodeSpecified { + get { + return this.cardCodeFieldSpecified; + } + set { + this.cardCodeFieldSpecified = value; + } + } + + /// + public string Manufacturer { + get { + return this.manufacturerField; + } + set { + this.manufacturerField = value; + } + } + + /// + public string ProductName { + get { + return this.productNameField; + } + set { + this.productNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("AdditionalInformation")] + public string[] AdditionalInformation { + get { + return this.additionalInformationField; + } + set { + this.additionalInformationField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class PartitionType { + + private uint sequenceField; + + private string nameField; + + private string typeField; + + private ulong startSectorField; + + private ulong endSectorField; + + private string descriptionField; + + private FileSystemType[] fileSystemsField; + + /// + public uint Sequence { + get { + return this.sequenceField; + } + set { + this.sequenceField = value; + } + } + + /// + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + public string Type { + get { + return this.typeField; + } + set { + this.typeField = value; + } + } + + /// + public ulong StartSector { + get { + return this.startSectorField; + } + set { + this.startSectorField = value; + } + } + + /// + public ulong EndSector { + get { + return this.endSectorField; + } + set { + this.endSectorField = value; + } + } + + /// + public string Description { + get { + return this.descriptionField; + } + set { + this.descriptionField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("FileSystem", IsNullable=false)] + public FileSystemType[] FileSystems { + get { + return this.fileSystemsField; + } + set { + this.fileSystemsField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class FileSystemType { + + private string typeField; + + private System.DateTime creationDateField; + + private bool creationDateFieldSpecified; + + private System.DateTime modificationDateField; + + private bool modificationDateFieldSpecified; + + private System.DateTime backupDateField; + + private bool backupDateFieldSpecified; + + private uint clusterSizeField; + + private ulong clustersField; + + private ulong filesField; + + private bool filesFieldSpecified; + + private bool bootableField; + + private string volumeSerialField; + + private string volumeNameField; + + private ulong freeClustersField; + + private bool freeClustersFieldSpecified; + + private bool dirtyField; + + private System.DateTime expirationDateField; + + private bool expirationDateFieldSpecified; + + private System.DateTime effectiveDateField; + + private bool effectiveDateFieldSpecified; + + private string systemIdentifierField; + + private string volumeSetIdentifierField; + + private string publisherIdentifierField; + + private string dataPreparerIdentifierField; + + private string applicationIdentifierField; + + private FilesystemContentsType contentsField; + + /// + public string Type { + get { + return this.typeField; + } + set { + this.typeField = value; + } + } + + /// + public System.DateTime CreationDate { + get { + return this.creationDateField; + } + set { + this.creationDateField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool CreationDateSpecified { + get { + return this.creationDateFieldSpecified; + } + set { + this.creationDateFieldSpecified = value; + } + } + + /// + public System.DateTime ModificationDate { + get { + return this.modificationDateField; + } + set { + this.modificationDateField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool ModificationDateSpecified { + get { + return this.modificationDateFieldSpecified; + } + set { + this.modificationDateFieldSpecified = value; + } + } + + /// + public System.DateTime BackupDate { + get { + return this.backupDateField; + } + set { + this.backupDateField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool BackupDateSpecified { + get { + return this.backupDateFieldSpecified; + } + set { + this.backupDateFieldSpecified = value; + } + } + + /// + public uint ClusterSize { + get { + return this.clusterSizeField; + } + set { + this.clusterSizeField = value; + } + } + + /// + public ulong Clusters { + get { + return this.clustersField; + } + set { + this.clustersField = value; + } + } + + /// + public ulong Files { + get { + return this.filesField; + } + set { + this.filesField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool FilesSpecified { + get { + return this.filesFieldSpecified; + } + set { + this.filesFieldSpecified = value; + } + } + + /// + public bool Bootable { + get { + return this.bootableField; + } + set { + this.bootableField = value; + } + } + + /// + public string VolumeSerial { + get { + return this.volumeSerialField; + } + set { + this.volumeSerialField = value; + } + } + + /// + public string VolumeName { + get { + return this.volumeNameField; + } + set { + this.volumeNameField = value; + } + } + + /// + public ulong FreeClusters { + get { + return this.freeClustersField; + } + set { + this.freeClustersField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool FreeClustersSpecified { + get { + return this.freeClustersFieldSpecified; + } + set { + this.freeClustersFieldSpecified = value; + } + } + + /// + public bool Dirty { + get { + return this.dirtyField; + } + set { + this.dirtyField = value; + } + } + + /// + public System.DateTime ExpirationDate { + get { + return this.expirationDateField; + } + set { + this.expirationDateField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool ExpirationDateSpecified { + get { + return this.expirationDateFieldSpecified; + } + set { + this.expirationDateFieldSpecified = value; + } + } + + /// + public System.DateTime EffectiveDate { + get { + return this.effectiveDateField; + } + set { + this.effectiveDateField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool EffectiveDateSpecified { + get { + return this.effectiveDateFieldSpecified; + } + set { + this.effectiveDateFieldSpecified = value; + } + } + + /// + public string SystemIdentifier { + get { + return this.systemIdentifierField; + } + set { + this.systemIdentifierField = value; + } + } + + /// + public string VolumeSetIdentifier { + get { + return this.volumeSetIdentifierField; + } + set { + this.volumeSetIdentifierField = value; + } + } + + /// + public string PublisherIdentifier { + get { + return this.publisherIdentifierField; + } + set { + this.publisherIdentifierField = value; + } + } + + /// + public string DataPreparerIdentifier { + get { + return this.dataPreparerIdentifierField; + } + set { + this.dataPreparerIdentifierField = value; + } + } + + /// + public string ApplicationIdentifier { + get { + return this.applicationIdentifierField; + } + set { + this.applicationIdentifierField = value; + } + } + + /// + public FilesystemContentsType Contents { + get { + return this.contentsField; + } + set { + this.contentsField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class FilesystemContentsType { + + private ContentsFileType[] fileField; + + private DirectoryType[] directoryField; + + private string namespaceField; + + /// + [System.Xml.Serialization.XmlElementAttribute("File")] + public ContentsFileType[] File { + get { + return this.fileField; + } + set { + this.fileField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Directory")] + public DirectoryType[] Directory { + get { + return this.directoryField; + } + set { + this.directoryField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string @namespace { + get { + return this.namespaceField; + } + set { + this.namespaceField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class ContentsFileType { + + private ChecksumType[] checksumsField; + + private ExtendedAttributeType[] extendedAttributesField; + + private string nameField; + + private System.DateTime creationTimeField; + + private bool creationTimeFieldSpecified; + + private System.DateTime accessTimeField; + + private bool accessTimeFieldSpecified; + + private System.DateTime statusChangeTimeField; + + private bool statusChangeTimeFieldSpecified; + + private System.DateTime backupTimeField; + + private bool backupTimeFieldSpecified; + + private System.DateTime lastWriteTimeField; + + private bool lastWriteTimeFieldSpecified; + + private ulong attributesField; + + private uint posixModeField; + + private bool posixModeFieldSpecified; + + private ulong deviceNumberField; + + private bool deviceNumberFieldSpecified; + + private ulong posixGroupIdField; + + private bool posixGroupIdFieldSpecified; + + private ulong inodeField; + + private ulong linksField; + + private ulong posixUserIdField; + + private bool posixUserIdFieldSpecified; + + private ulong lengthField; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] Checksums { + get { + return this.checksumsField; + } + set { + this.checksumsField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("ExtendedAttribute", IsNullable=false)] + public ExtendedAttributeType[] ExtendedAttributes { + get { + return this.extendedAttributesField; + } + set { + this.extendedAttributesField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public System.DateTime creationTime { + get { + return this.creationTimeField; + } + set { + this.creationTimeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool creationTimeSpecified { + get { + return this.creationTimeFieldSpecified; + } + set { + this.creationTimeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public System.DateTime accessTime { + get { + return this.accessTimeField; + } + set { + this.accessTimeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool accessTimeSpecified { + get { + return this.accessTimeFieldSpecified; + } + set { + this.accessTimeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public System.DateTime statusChangeTime { + get { + return this.statusChangeTimeField; + } + set { + this.statusChangeTimeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool statusChangeTimeSpecified { + get { + return this.statusChangeTimeFieldSpecified; + } + set { + this.statusChangeTimeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public System.DateTime backupTime { + get { + return this.backupTimeField; + } + set { + this.backupTimeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool backupTimeSpecified { + get { + return this.backupTimeFieldSpecified; + } + set { + this.backupTimeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public System.DateTime lastWriteTime { + get { + return this.lastWriteTimeField; + } + set { + this.lastWriteTimeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool lastWriteTimeSpecified { + get { + return this.lastWriteTimeFieldSpecified; + } + set { + this.lastWriteTimeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ulong attributes { + get { + return this.attributesField; + } + set { + this.attributesField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public uint posixMode { + get { + return this.posixModeField; + } + set { + this.posixModeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool posixModeSpecified { + get { + return this.posixModeFieldSpecified; + } + set { + this.posixModeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ulong deviceNumber { + get { + return this.deviceNumberField; + } + set { + this.deviceNumberField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool deviceNumberSpecified { + get { + return this.deviceNumberFieldSpecified; + } + set { + this.deviceNumberFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ulong posixGroupId { + get { + return this.posixGroupIdField; + } + set { + this.posixGroupIdField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool posixGroupIdSpecified { + get { + return this.posixGroupIdFieldSpecified; + } + set { + this.posixGroupIdFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ulong inode { + get { + return this.inodeField; + } + set { + this.inodeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ulong links { + get { + return this.linksField; + } + set { + this.linksField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ulong posixUserId { + get { + return this.posixUserIdField; + } + set { + this.posixUserIdField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool posixUserIdSpecified { + get { + return this.posixUserIdFieldSpecified; + } + set { + this.posixUserIdFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ulong length { + get { + return this.lengthField; + } + set { + this.lengthField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class ExtendedAttributeType { + + private ChecksumType[] checksumsField; + + private string nameField; + + private ulong lengthField; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] Checksums { + get { + return this.checksumsField; + } + set { + this.checksumsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ulong length { + get { + return this.lengthField; + } + set { + this.lengthField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class DirectoryType { + + private ContentsFileType[] fileField; + + private DirectoryType[] directoryField; + + private string nameField; + + private System.DateTime creationTimeField; + + private bool creationTimeFieldSpecified; + + private System.DateTime accessTimeField; + + private bool accessTimeFieldSpecified; + + private System.DateTime statusChangeTimeField; + + private bool statusChangeTimeFieldSpecified; + + private System.DateTime backupTimeField; + + private bool backupTimeFieldSpecified; + + private System.DateTime lastWriteTimeField; + + private bool lastWriteTimeFieldSpecified; + + private ulong attributesField; + + private uint posixModeField; + + private bool posixModeFieldSpecified; + + private ulong deviceNumberField; + + private bool deviceNumberFieldSpecified; + + private ulong posixGroupIdField; + + private bool posixGroupIdFieldSpecified; + + private ulong inodeField; + + private bool inodeFieldSpecified; + + private ulong linksField; + + private bool linksFieldSpecified; + + private ulong posixUserIdField; + + private bool posixUserIdFieldSpecified; + + /// + [System.Xml.Serialization.XmlElementAttribute("File")] + public ContentsFileType[] File { + get { + return this.fileField; + } + set { + this.fileField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Directory")] + public DirectoryType[] Directory { + get { + return this.directoryField; + } + set { + this.directoryField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public System.DateTime creationTime { + get { + return this.creationTimeField; + } + set { + this.creationTimeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool creationTimeSpecified { + get { + return this.creationTimeFieldSpecified; + } + set { + this.creationTimeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public System.DateTime accessTime { + get { + return this.accessTimeField; + } + set { + this.accessTimeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool accessTimeSpecified { + get { + return this.accessTimeFieldSpecified; + } + set { + this.accessTimeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public System.DateTime statusChangeTime { + get { + return this.statusChangeTimeField; + } + set { + this.statusChangeTimeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool statusChangeTimeSpecified { + get { + return this.statusChangeTimeFieldSpecified; + } + set { + this.statusChangeTimeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public System.DateTime backupTime { + get { + return this.backupTimeField; + } + set { + this.backupTimeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool backupTimeSpecified { + get { + return this.backupTimeFieldSpecified; + } + set { + this.backupTimeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public System.DateTime lastWriteTime { + get { + return this.lastWriteTimeField; + } + set { + this.lastWriteTimeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool lastWriteTimeSpecified { + get { + return this.lastWriteTimeFieldSpecified; + } + set { + this.lastWriteTimeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ulong attributes { + get { + return this.attributesField; + } + set { + this.attributesField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public uint posixMode { + get { + return this.posixModeField; + } + set { + this.posixModeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool posixModeSpecified { + get { + return this.posixModeFieldSpecified; + } + set { + this.posixModeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ulong deviceNumber { + get { + return this.deviceNumberField; + } + set { + this.deviceNumberField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool deviceNumberSpecified { + get { + return this.deviceNumberFieldSpecified; + } + set { + this.deviceNumberFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ulong posixGroupId { + get { + return this.posixGroupIdField; + } + set { + this.posixGroupIdField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool posixGroupIdSpecified { + get { + return this.posixGroupIdFieldSpecified; + } + set { + this.posixGroupIdFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ulong inode { + get { + return this.inodeField; + } + set { + this.inodeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool inodeSpecified { + get { + return this.inodeFieldSpecified; + } + set { + this.inodeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ulong links { + get { + return this.linksField; + } + set { + this.linksField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool linksSpecified { + get { + return this.linksFieldSpecified; + } + set { + this.linksFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ulong posixUserId { + get { + return this.posixUserIdField; + } + set { + this.posixUserIdField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool posixUserIdSpecified { + get { + return this.posixUserIdFieldSpecified; + } + set { + this.posixUserIdFieldSpecified = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class CoordinatesType { + + private double latitudeField; + + private double longitudeField; + + /// + public double Latitude { + get { + return this.latitudeField; + } + set { + this.latitudeField = value; + } + } + + /// + public double Longitude { + get { + return this.longitudeField; + } + set { + this.longitudeField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class RecordingType { + + private string broadcasterField; + + private string broadcastPlatformField; + + private RecordingTypeSourceFormat sourceFormatField; + + private System.DateTime timestampField; + + private SoftwareType[] softwareField; + + private CoordinatesType coordinatesField; + + /// + public string Broadcaster { + get { + return this.broadcasterField; + } + set { + this.broadcasterField = value; + } + } + + /// + public string BroadcastPlatform { + get { + return this.broadcastPlatformField; + } + set { + this.broadcastPlatformField = value; + } + } + + /// + public RecordingTypeSourceFormat SourceFormat { + get { + return this.sourceFormatField; + } + set { + this.sourceFormatField = value; + } + } + + /// + public System.DateTime Timestamp { + get { + return this.timestampField; + } + set { + this.timestampField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Software")] + public SoftwareType[] Software { + get { + return this.softwareField; + } + set { + this.softwareField = value; + } + } + + /// + public CoordinatesType Coordinates { + get { + return this.coordinatesField; + } + set { + this.coordinatesField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum RecordingTypeSourceFormat { + + /// + [System.Xml.Serialization.XmlEnumAttribute("ITU-A")] + ITUA, + + /// + [System.Xml.Serialization.XmlEnumAttribute("ITU-B")] + ITUB, + + /// + [System.Xml.Serialization.XmlEnumAttribute("ITU-C")] + ITUC, + + /// + [System.Xml.Serialization.XmlEnumAttribute("ITU-D")] + ITUD, + + /// + [System.Xml.Serialization.XmlEnumAttribute("ITU-E")] + ITUE, + + /// + [System.Xml.Serialization.XmlEnumAttribute("ITU-F")] + ITUF, + + /// + [System.Xml.Serialization.XmlEnumAttribute("ITU-G")] + ITUG, + + /// + [System.Xml.Serialization.XmlEnumAttribute("ITU-H")] + ITUH, + + /// + [System.Xml.Serialization.XmlEnumAttribute("ITU-I")] + ITUI, + + /// + [System.Xml.Serialization.XmlEnumAttribute("ITU-J")] + ITUJ, + + /// + [System.Xml.Serialization.XmlEnumAttribute("ITU-K")] + ITUK, + + /// + [System.Xml.Serialization.XmlEnumAttribute("ITU-L")] + ITUL, + + /// + [System.Xml.Serialization.XmlEnumAttribute("ITU-M")] + ITUM, + + /// + [System.Xml.Serialization.XmlEnumAttribute("ITU-N")] + ITUN, + + /// + [System.Xml.Serialization.XmlEnumAttribute("PAL-B")] + PALB, + + /// + [System.Xml.Serialization.XmlEnumAttribute("SECAM-B")] + SECAMB, + + /// + [System.Xml.Serialization.XmlEnumAttribute("PAL-D")] + PALD, + + /// + [System.Xml.Serialization.XmlEnumAttribute("SECAM-D")] + SECAMD, + + /// + [System.Xml.Serialization.XmlEnumAttribute("PAL-G")] + PALG, + + /// + [System.Xml.Serialization.XmlEnumAttribute("SECAM-G")] + SECAMG, + + /// + [System.Xml.Serialization.XmlEnumAttribute("PAL-H")] + PALH, + + /// + [System.Xml.Serialization.XmlEnumAttribute("PAL-I")] + PALI, + + /// + [System.Xml.Serialization.XmlEnumAttribute("PAL-K")] + PALK, + + /// + [System.Xml.Serialization.XmlEnumAttribute("SECAM-K")] + SECAMK, + + /// + [System.Xml.Serialization.XmlEnumAttribute("NTSC-M")] + NTSCM, + + /// + [System.Xml.Serialization.XmlEnumAttribute("PAL-N")] + PALN, + + /// + [System.Xml.Serialization.XmlEnumAttribute("PAL-M")] + PALM, + + /// + [System.Xml.Serialization.XmlEnumAttribute("SECAM-M")] + SECAMM, + + /// + MUSE, + + /// + PALplus, + + /// + FM, + + /// + AM, + + /// + COFDM, + + /// + [System.Xml.Serialization.XmlEnumAttribute("CAM-D")] + CAMD, + + /// + DAB, + + /// + [System.Xml.Serialization.XmlEnumAttribute("DAB+")] + DAB1, + + /// + DRM, + + /// + [System.Xml.Serialization.XmlEnumAttribute("DRM+")] + DRM1, + + /// + FMeXtra, + + /// + ATSC, + + /// + ATSC2, + + /// + ATSC3, + + /// + [System.Xml.Serialization.XmlEnumAttribute("ATSC-M/H")] + ATSCMH, + + /// + [System.Xml.Serialization.XmlEnumAttribute("DVB-T")] + DVBT, + + /// + [System.Xml.Serialization.XmlEnumAttribute("DVB-T2")] + DVBT2, + + /// + [System.Xml.Serialization.XmlEnumAttribute("DVB-S")] + DVBS, + + /// + [System.Xml.Serialization.XmlEnumAttribute("DVB-S2")] + DVBS2, + + /// + [System.Xml.Serialization.XmlEnumAttribute("DVB-S2X")] + DVBS2X, + + /// + [System.Xml.Serialization.XmlEnumAttribute("DVB-C")] + DVBC, + + /// + [System.Xml.Serialization.XmlEnumAttribute("DVB-C2")] + DVBC2, + + /// + [System.Xml.Serialization.XmlEnumAttribute("DVB-H")] + DVBH, + + /// + [System.Xml.Serialization.XmlEnumAttribute("DVB-NGH")] + DVBNGH, + + /// + [System.Xml.Serialization.XmlEnumAttribute("DVB-SH")] + DVBSH, + + /// + [System.Xml.Serialization.XmlEnumAttribute("ISDB-T")] + ISDBT, + + /// + [System.Xml.Serialization.XmlEnumAttribute("ISDB-Tb")] + ISDBTb, + + /// + [System.Xml.Serialization.XmlEnumAttribute("ISDB-S")] + ISDBS, + + /// + [System.Xml.Serialization.XmlEnumAttribute("ISDB-C")] + ISDBC, + + /// + [System.Xml.Serialization.XmlEnumAttribute("1seg")] + Item1seg, + + /// + DTMB, + + /// + CCMB, + + /// + [System.Xml.Serialization.XmlEnumAttribute("T-DMB")] + TDMB, + + /// + [System.Xml.Serialization.XmlEnumAttribute("S-DMB")] + SDMB, + + /// + IPTV, + + /// + [System.Xml.Serialization.XmlEnumAttribute("DVB-MT")] + DVBMT, + + /// + [System.Xml.Serialization.XmlEnumAttribute("DVB-MC")] + DVBMC, + + /// + [System.Xml.Serialization.XmlEnumAttribute("DVB-MS")] + DVBMS, + + /// + ADR, + + /// + SDR, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class SubtitleTracksType { + + private LanguagesTypeLanguage[] languagesField; + + private uint trackNumberField; + + private string codecField; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Language", IsNullable=false)] + public LanguagesTypeLanguage[] Languages { + get { + return this.languagesField; + } + set { + this.languagesField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public uint TrackNumber { + get { + return this.trackNumberField; + } + set { + this.trackNumberField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Codec { + get { + return this.codecField; + } + set { + this.codecField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class VideoTracksType { + + private LanguagesTypeLanguage[] languagesField; + + private uint trackNumberField; + + private string codecField; + + private uint horizontalField; + + private uint verticalField; + + private long meanBitrateField; + + private bool threeDField; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Language", IsNullable=false)] + public LanguagesTypeLanguage[] Languages { + get { + return this.languagesField; + } + set { + this.languagesField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public uint TrackNumber { + get { + return this.trackNumberField; + } + set { + this.trackNumberField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Codec { + get { + return this.codecField; + } + set { + this.codecField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public uint Horizontal { + get { + return this.horizontalField; + } + set { + this.horizontalField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public uint Vertical { + get { + return this.verticalField; + } + set { + this.verticalField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public long MeanBitrate { + get { + return this.meanBitrateField; + } + set { + this.meanBitrateField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public bool ThreeD { + get { + return this.threeDField; + } + set { + this.threeDField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class AudioTracksType { + + private LanguagesTypeLanguage[] languagesField; + + private uint trackNumberField; + + private string accoustIDField; + + private string codecField; + + private uint channelsField; + + private double sampleRateField; + + private long meanBitrateField; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Language", IsNullable=false)] + public LanguagesTypeLanguage[] Languages { + get { + return this.languagesField; + } + set { + this.languagesField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public uint TrackNumber { + get { + return this.trackNumberField; + } + set { + this.trackNumberField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string AccoustID { + get { + return this.accoustIDField; + } + set { + this.accoustIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Codec { + get { + return this.codecField; + } + set { + this.codecField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public uint Channels { + get { + return this.channelsField; + } + set { + this.channelsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public double SampleRate { + get { + return this.sampleRateField; + } + set { + this.sampleRateField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public long MeanBitrate { + get { + return this.meanBitrateField; + } + set { + this.meanBitrateField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class AdvertisementType { + + private string manufacturerField; + + private string productField; + + private FileType fileField; + + private ulong fileSizeField; + + private ulong framesField; + + private bool framesFieldSpecified; + + private double durationField; + + private float meanFrameRateField; + + private bool meanFrameRateFieldSpecified; + + private ChecksumType[] checksumsField; + + private AudioTracksType[] audioTrackField; + + private VideoTracksType[] videoTrackField; + + private SubtitleTracksType[] subtitleTrackField; + + private RecordingType recordingField; + + /// + public string Manufacturer { + get { + return this.manufacturerField; + } + set { + this.manufacturerField = value; + } + } + + /// + public string Product { + get { + return this.productField; + } + set { + this.productField = value; + } + } + + /// + public FileType File { + get { + return this.fileField; + } + set { + this.fileField = value; + } + } + + /// + public ulong FileSize { + get { + return this.fileSizeField; + } + set { + this.fileSizeField = value; + } + } + + /// + public ulong Frames { + get { + return this.framesField; + } + set { + this.framesField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool FramesSpecified { + get { + return this.framesFieldSpecified; + } + set { + this.framesFieldSpecified = value; + } + } + + /// + public double Duration { + get { + return this.durationField; + } + set { + this.durationField = value; + } + } + + /// + public float MeanFrameRate { + get { + return this.meanFrameRateField; + } + set { + this.meanFrameRateField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool MeanFrameRateSpecified { + get { + return this.meanFrameRateFieldSpecified; + } + set { + this.meanFrameRateFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] Checksums { + get { + return this.checksumsField; + } + set { + this.checksumsField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("AudioTrack")] + public AudioTracksType[] AudioTrack { + get { + return this.audioTrackField; + } + set { + this.audioTrackField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("VideoTrack")] + public VideoTracksType[] VideoTrack { + get { + return this.videoTrackField; + } + set { + this.videoTrackField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("SubtitleTrack")] + public SubtitleTracksType[] SubtitleTrack { + get { + return this.subtitleTrackField; + } + set { + this.subtitleTrackField = value; + } + } + + /// + public RecordingType Recording { + get { + return this.recordingField; + } + set { + this.recordingField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class SubChannelType { + + private ImageType imageField; + + private ulong sizeField; + + private ChecksumType[] checksumsField; + + /// + public ImageType Image { + get { + return this.imageField; + } + set { + this.imageField = value; + } + } + + /// + public ulong Size { + get { + return this.sizeField; + } + set { + this.sizeField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] Checksums { + get { + return this.checksumsField; + } + set { + this.checksumsField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class TrackFlagsType { + + private bool quadraphonicField; + + private bool dataField; + + private bool copyPermittedField; + + private bool preEmphasisField; + + /// + public bool Quadraphonic { + get { + return this.quadraphonicField; + } + set { + this.quadraphonicField = value; + } + } + + /// + public bool Data { + get { + return this.dataField; + } + set { + this.dataField = value; + } + } + + /// + public bool CopyPermitted { + get { + return this.copyPermittedField; + } + set { + this.copyPermittedField = value; + } + } + + /// + public bool PreEmphasis { + get { + return this.preEmphasisField; + } + set { + this.preEmphasisField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class TrackIndexType { + + private ushort indexField; + + private int valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ushort index { + get { + return this.indexField; + } + set { + this.indexField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public int Value { + get { + return this.valueField; + } + set { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class TrackSequenceType { + + private uint trackNumberField; + + private uint sessionField; + + /// + public uint TrackNumber { + get { + return this.trackNumberField; + } + set { + this.trackNumberField = value; + } + } + + /// + public uint Session { + get { + return this.sessionField; + } + set { + this.sessionField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class TrackType { + + private ImageType imageField; + + private ulong sizeField; + + private TrackSequenceType sequenceField; + + private string startMSFField; + + private string endMSFField; + + private ulong startSectorField; + + private ulong endSectorField; + + private TrackIndexType[] indexesField; + + private TrackFlagsType flagsField; + + private string iSRCField; + + private TrackTypeTrackType trackType1Field; + + private uint bytesPerSectorField; + + private string accoustIDField; + + private ChecksumType[] checksumsField; + + private SubChannelType subChannelField; + + private PartitionType[] fileSystemInformationField; + + /// + public ImageType Image { + get { + return this.imageField; + } + set { + this.imageField = value; + } + } + + /// + public ulong Size { + get { + return this.sizeField; + } + set { + this.sizeField = value; + } + } + + /// + public TrackSequenceType Sequence { + get { + return this.sequenceField; + } + set { + this.sequenceField = value; + } + } + + /// + public string StartMSF { + get { + return this.startMSFField; + } + set { + this.startMSFField = value; + } + } + + /// + public string EndMSF { + get { + return this.endMSFField; + } + set { + this.endMSFField = value; + } + } + + /// + public ulong StartSector { + get { + return this.startSectorField; + } + set { + this.startSectorField = value; + } + } + + /// + public ulong EndSector { + get { + return this.endSectorField; + } + set { + this.endSectorField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Index", IsNullable=false)] + public TrackIndexType[] Indexes { + get { + return this.indexesField; + } + set { + this.indexesField = value; + } + } + + /// + public TrackFlagsType Flags { + get { + return this.flagsField; + } + set { + this.flagsField = value; + } + } + + /// + public string ISRC { + get { + return this.iSRCField; + } + set { + this.iSRCField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("TrackType")] + public TrackTypeTrackType TrackType1 { + get { + return this.trackType1Field; + } + set { + this.trackType1Field = value; + } + } + + /// + public uint BytesPerSector { + get { + return this.bytesPerSectorField; + } + set { + this.bytesPerSectorField = value; + } + } + + /// + public string AccoustID { + get { + return this.accoustIDField; + } + set { + this.accoustIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] Checksums { + get { + return this.checksumsField; + } + set { + this.checksumsField = value; + } + } + + /// + public SubChannelType SubChannel { + get { + return this.subChannelField; + } + set { + this.subChannelField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Partition", IsNullable=false)] + public PartitionType[] FileSystemInformation { + get { + return this.fileSystemInformationField; + } + set { + this.fileSystemInformationField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum TrackTypeTrackType { + + /// + audio, + + /// + mode0, + + /// + mode1, + + /// + mode2, + + /// + m2f1, + + /// + m2f2, + + /// + dvd, + + /// + hddvd, + + /// + bluray, + + /// + ddcd, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class PS3EncryptionType { + + private string keyField; + + private string serialField; + + /// + public string Key { + get { + return this.keyField; + } + set { + this.keyField = value; + } + } + + /// + public string Serial { + get { + return this.serialField; + } + set { + this.serialField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class XboxSecuritySectorsType { + + private uint requestVersionField; + + private uint requestNumberField; + + private DumpType securitySectorsField; + + /// + public uint RequestVersion { + get { + return this.requestVersionField; + } + set { + this.requestVersionField = value; + } + } + + /// + public uint RequestNumber { + get { + return this.requestNumberField; + } + set { + this.requestNumberField = value; + } + } + + /// + public DumpType SecuritySectors { + get { + return this.securitySectorsField; + } + set { + this.securitySectorsField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class XboxType { + + private DumpType pFIField; + + private DumpType dMIField; + + private XboxSecuritySectorsType[] securitySectorsField; + + /// + public DumpType PFI { + get { + return this.pFIField; + } + set { + this.pFIField = value; + } + } + + /// + public DumpType DMI { + get { + return this.dMIField; + } + set { + this.dMIField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("SecuritySectors")] + public XboxSecuritySectorsType[] SecuritySectors { + get { + return this.securitySectorsField; + } + set { + this.securitySectorsField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class BorderType { + + private string imageField; + + private ulong sizeField; + + private ChecksumType[] checksumsField; + + private uint sessionField; + + private bool sessionFieldSpecified; + + /// + public string Image { + get { + return this.imageField; + } + set { + this.imageField = value; + } + } + + /// + public ulong Size { + get { + return this.sizeField; + } + set { + this.sizeField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] Checksums { + get { + return this.checksumsField; + } + set { + this.checksumsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public uint session { + get { + return this.sessionField; + } + set { + this.sessionField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool sessionSpecified { + get { + return this.sessionFieldSpecified; + } + set { + this.sessionFieldSpecified = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class CaseType { + + private CaseTypeCaseType caseType1Field; + + private ScansType scansField; + + /// + [System.Xml.Serialization.XmlElementAttribute("CaseType")] + public CaseTypeCaseType CaseType1 { + get { + return this.caseType1Field; + } + set { + this.caseType1Field = value; + } + } + + /// + public ScansType Scans { + get { + return this.scansField; + } + set { + this.scansField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum CaseTypeCaseType { + + /// + jewel, + + /// + bigjewel, + + /// + slimjewel, + + /// + sleeve, + + /// + qpack, + + /// + digisleeve, + + /// + discboxslider, + + /// + compacplus, + + /// + keepcase, + + /// + snapcase, + + /// + softcase, + + /// + ecopack, + + /// + liftlock, + + /// + spindle, + + /// + ps2case, + + /// + ps3case, + + /// + bluraykeepcase, + + /// + pscase, + + /// + dccase, + + /// + saturncase, + + /// + xboxcase, + + /// + xbox360case, + + /// + xboxonecase, + + /// + saturnbigcase, + + /// + gccase, + + /// + wiicase, + + /// + unknown, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class LayeredTextType { + + private uint layerField; + + private bool layerFieldSpecified; + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public uint layer { + get { + return this.layerField; + } + set { + this.layerField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool layerSpecified { + get { + return this.layerFieldSpecified; + } + set { + this.layerFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value { + get { + return this.valueField; + } + set { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class SectorsType { + + private uint layerField; + + private bool layerFieldSpecified; + + private ulong valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public uint layer { + get { + return this.layerField; + } + set { + this.layerField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool layerSpecified { + get { + return this.layerFieldSpecified; + } + set { + this.layerFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public ulong Value { + get { + return this.valueField; + } + set { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class LayersType { + + private SectorsType[] sectorsField; + + private LayersTypeType typeField; + + private bool typeFieldSpecified; + + /// + [System.Xml.Serialization.XmlElementAttribute("Sectors")] + public SectorsType[] Sectors { + get { + return this.sectorsField; + } + set { + this.sectorsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public LayersTypeType type { + get { + return this.typeField; + } + set { + this.typeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool typeSpecified { + get { + return this.typeFieldSpecified; + } + set { + this.typeFieldSpecified = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum LayersTypeType { + + /// + PTP, + + /// + OTP, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class OpticalDiscType { + + private ImageType imageField; + + private ulong sizeField; + + private SequenceType sequenceField; + + private LayersType layersField; + + private ChecksumType[] checksumsField; + + private string partNumberField; + + private string serialNumberField; + + private LayeredTextType[] ringCodeField; + + private LayeredTextType[] masteringSIDField; + + private LayeredTextType[] toolstampField; + + private LayeredTextType[] mouldSIDField; + + private LayeredTextType[] mouldTextField; + + private string discTypeField; + + private string discSubTypeField; + + private int offsetField; + + private bool offsetFieldSpecified; + + private uint[] tracksField; + + private uint sessionsField; + + private string copyProtectionField; + + private DimensionsType dimensionsField; + + private CaseType caseField; + + private ScansType scansField; + + private DumpType pFIField; + + private DumpType dMIField; + + private DumpType cMIField; + + private DumpType bCAField; + + private DumpType aTIPField; + + private DumpType aDIPField; + + private DumpType pMAField; + + private DumpType dDSField; + + private DumpType sAIField; + + private DumpType lastRMDField; + + private DumpType pRIField; + + private DumpType mediaIDField; + + private DumpType pFIRField; + + private DumpType dCBField; + + private DumpType diField; + + private DumpType pACField; + + private DumpType tOCField; + + private DumpType leadInCdTextField; + + private BorderType[] firstTrackPregrapField; + + private BorderType[] leadInField; + + private BorderType[] leadOutField; + + private XboxType xboxField; + + private PS3EncryptionType pS3EncryptionField; + + private string mediaCatalogueNumberField; + + private TrackType[] trackField; + + private DumpHardwareType[] dumpHardwareArrayField; + + /// + public ImageType Image { + get { + return this.imageField; + } + set { + this.imageField = value; + } + } + + /// + public ulong Size { + get { + return this.sizeField; + } + set { + this.sizeField = value; + } + } + + /// + public SequenceType Sequence { + get { + return this.sequenceField; + } + set { + this.sequenceField = value; + } + } + + /// + public LayersType Layers { + get { + return this.layersField; + } + set { + this.layersField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] Checksums { + get { + return this.checksumsField; + } + set { + this.checksumsField = value; + } + } + + /// + public string PartNumber { + get { + return this.partNumberField; + } + set { + this.partNumberField = value; + } + } + + /// + public string SerialNumber { + get { + return this.serialNumberField; + } + set { + this.serialNumberField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("RingCode")] + public LayeredTextType[] RingCode { + get { + return this.ringCodeField; + } + set { + this.ringCodeField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("MasteringSID")] + public LayeredTextType[] MasteringSID { + get { + return this.masteringSIDField; + } + set { + this.masteringSIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Toolstamp")] + public LayeredTextType[] Toolstamp { + get { + return this.toolstampField; + } + set { + this.toolstampField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("MouldSID")] + public LayeredTextType[] MouldSID { + get { + return this.mouldSIDField; + } + set { + this.mouldSIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("MouldText")] + public LayeredTextType[] MouldText { + get { + return this.mouldTextField; + } + set { + this.mouldTextField = value; + } + } + + /// + public string DiscType { + get { + return this.discTypeField; + } + set { + this.discTypeField = value; + } + } + + /// + public string DiscSubType { + get { + return this.discSubTypeField; + } + set { + this.discSubTypeField = value; + } + } + + /// + public int Offset { + get { + return this.offsetField; + } + set { + this.offsetField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool OffsetSpecified { + get { + return this.offsetFieldSpecified; + } + set { + this.offsetFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Tracks")] + public uint[] Tracks { + get { + return this.tracksField; + } + set { + this.tracksField = value; + } + } + + /// + public uint Sessions { + get { + return this.sessionsField; + } + set { + this.sessionsField = value; + } + } + + /// + public string CopyProtection { + get { + return this.copyProtectionField; + } + set { + this.copyProtectionField = value; + } + } + + /// + public DimensionsType Dimensions { + get { + return this.dimensionsField; + } + set { + this.dimensionsField = value; + } + } + + /// + public CaseType Case { + get { + return this.caseField; + } + set { + this.caseField = value; + } + } + + /// + public ScansType Scans { + get { + return this.scansField; + } + set { + this.scansField = value; + } + } + + /// + public DumpType PFI { + get { + return this.pFIField; + } + set { + this.pFIField = value; + } + } + + /// + public DumpType DMI { + get { + return this.dMIField; + } + set { + this.dMIField = value; + } + } + + /// + public DumpType CMI { + get { + return this.cMIField; + } + set { + this.cMIField = value; + } + } + + /// + public DumpType BCA { + get { + return this.bCAField; + } + set { + this.bCAField = value; + } + } + + /// + public DumpType ATIP { + get { + return this.aTIPField; + } + set { + this.aTIPField = value; + } + } + + /// + public DumpType ADIP { + get { + return this.aDIPField; + } + set { + this.aDIPField = value; + } + } + + /// + public DumpType PMA { + get { + return this.pMAField; + } + set { + this.pMAField = value; + } + } + + /// + public DumpType DDS { + get { + return this.dDSField; + } + set { + this.dDSField = value; + } + } + + /// + public DumpType SAI { + get { + return this.sAIField; + } + set { + this.sAIField = value; + } + } + + /// + public DumpType LastRMD { + get { + return this.lastRMDField; + } + set { + this.lastRMDField = value; + } + } + + /// + public DumpType PRI { + get { + return this.pRIField; + } + set { + this.pRIField = value; + } + } + + /// + public DumpType MediaID { + get { + return this.mediaIDField; + } + set { + this.mediaIDField = value; + } + } + + /// + public DumpType PFIR { + get { + return this.pFIRField; + } + set { + this.pFIRField = value; + } + } + + /// + public DumpType DCB { + get { + return this.dCBField; + } + set { + this.dCBField = value; + } + } + + /// + public DumpType DI { + get { + return this.diField; + } + set { + this.diField = value; + } + } + + /// + public DumpType PAC { + get { + return this.pACField; + } + set { + this.pACField = value; + } + } + + /// + public DumpType TOC { + get { + return this.tOCField; + } + set { + this.tOCField = value; + } + } + + /// + public DumpType LeadInCdText { + get { + return this.leadInCdTextField; + } + set { + this.leadInCdTextField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("FirstTrackPregrap")] + public BorderType[] FirstTrackPregrap { + get { + return this.firstTrackPregrapField; + } + set { + this.firstTrackPregrapField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("LeadIn")] + public BorderType[] LeadIn { + get { + return this.leadInField; + } + set { + this.leadInField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("LeadOut")] + public BorderType[] LeadOut { + get { + return this.leadOutField; + } + set { + this.leadOutField = value; + } + } + + /// + public XboxType Xbox { + get { + return this.xboxField; + } + set { + this.xboxField = value; + } + } + + /// + public PS3EncryptionType PS3Encryption { + get { + return this.pS3EncryptionField; + } + set { + this.pS3EncryptionField = value; + } + } + + /// + public string MediaCatalogueNumber { + get { + return this.mediaCatalogueNumberField; + } + set { + this.mediaCatalogueNumberField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Track")] + public TrackType[] Track { + get { + return this.trackField; + } + set { + this.trackField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("DumpHardware", IsNullable=false)] + public DumpHardwareType[] DumpHardwareArray { + get { + return this.dumpHardwareArrayField; + } + set { + this.dumpHardwareArrayField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class UserManualType { + + private LanguagesTypeLanguage[] languageField; + + private uint pagesField; + + private string pageSizeField; + + private ScanType scanField; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Language", IsNullable=false)] + public LanguagesTypeLanguage[] Language { + get { + return this.languageField; + } + set { + this.languageField = value; + } + } + + /// + public uint Pages { + get { + return this.pagesField; + } + set { + this.pagesField = value; + } + } + + /// + public string PageSize { + get { + return this.pageSizeField; + } + set { + this.pageSizeField = value; + } + } + + /// + public ScanType Scan { + get { + return this.scanField; + } + set { + this.scanField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class RequiredOperatingSystemType { + + private string nameField; + + private string[] versionField; + + /// + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Version")] + public string[] Version { + get { + return this.versionField; + } + set { + this.versionField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class BookType { + + private BarcodeType[] barcodesField; + + private CoverType coverField; + + private string nameField; + + private string editorialField; + + private string authorField; + + private System.DateTime publicationDateField; + + private bool publicationDateFieldSpecified; + + private LanguagesTypeLanguage[] languageField; + + private uint pagesField; + + private bool pagesFieldSpecified; + + private string pageSizeField; + + private ScanType scanField; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Barcode", IsNullable=false)] + public BarcodeType[] Barcodes { + get { + return this.barcodesField; + } + set { + this.barcodesField = value; + } + } + + /// + public CoverType Cover { + get { + return this.coverField; + } + set { + this.coverField = value; + } + } + + /// + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + public string Editorial { + get { + return this.editorialField; + } + set { + this.editorialField = value; + } + } + + /// + public string Author { + get { + return this.authorField; + } + set { + this.authorField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType="date")] + public System.DateTime PublicationDate { + get { + return this.publicationDateField; + } + set { + this.publicationDateField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool PublicationDateSpecified { + get { + return this.publicationDateFieldSpecified; + } + set { + this.publicationDateFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Language", IsNullable=false)] + public LanguagesTypeLanguage[] Language { + get { + return this.languageField; + } + set { + this.languageField = value; + } + } + + /// + public uint Pages { + get { + return this.pagesField; + } + set { + this.pagesField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool PagesSpecified { + get { + return this.pagesFieldSpecified; + } + set { + this.pagesFieldSpecified = value; + } + } + + /// + public string PageSize { + get { + return this.pageSizeField; + } + set { + this.pageSizeField = value; + } + } + + /// + public ScanType Scan { + get { + return this.scanField; + } + set { + this.scanField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class CoverType { + + private FileType fileField; + + private ChecksumType[] checksumsField; + + private byte[] thumbnailField; + + /// + public FileType File { + get { + return this.fileField; + } + set { + this.fileField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Checksum", IsNullable=false)] + public ChecksumType[] Checksums { + get { + return this.checksumsField; + } + set { + this.checksumsField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType="base64Binary")] + public byte[] Thumbnail { + get { + return this.thumbnailField; + } + set { + this.thumbnailField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class MagazineType { + + private BarcodeType[] barcodesField; + + private CoverType coverField; + + private string nameField; + + private string editorialField; + + private System.DateTime publicationDateField; + + private bool publicationDateFieldSpecified; + + private uint numberField; + + private bool numberFieldSpecified; + + private LanguagesTypeLanguage[] languageField; + + private uint pagesField; + + private bool pagesFieldSpecified; + + private string pageSizeField; + + private ScanType scanField; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Barcode", IsNullable=false)] + public BarcodeType[] Barcodes { + get { + return this.barcodesField; + } + set { + this.barcodesField = value; + } + } + + /// + public CoverType Cover { + get { + return this.coverField; + } + set { + this.coverField = value; + } + } + + /// + public string Name { + get { + return this.nameField; + } + set { + this.nameField = value; + } + } + + /// + public string Editorial { + get { + return this.editorialField; + } + set { + this.editorialField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType="date")] + public System.DateTime PublicationDate { + get { + return this.publicationDateField; + } + set { + this.publicationDateField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool PublicationDateSpecified { + get { + return this.publicationDateFieldSpecified; + } + set { + this.publicationDateFieldSpecified = value; + } + } + + /// + public uint Number { + get { + return this.numberField; + } + set { + this.numberField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool NumberSpecified { + get { + return this.numberFieldSpecified; + } + set { + this.numberFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Language", IsNullable=false)] + public LanguagesTypeLanguage[] Language { + get { + return this.languageField; + } + set { + this.languageField = value; + } + } + + /// + public uint Pages { + get { + return this.pagesField; + } + set { + this.pagesField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool PagesSpecified { + get { + return this.pagesFieldSpecified; + } + set { + this.pagesFieldSpecified = value; + } + } + + /// + public string PageSize { + get { + return this.pageSizeField; + } + set { + this.pageSizeField = value; + } + } + + /// + public ScanType Scan { + get { + return this.scanField; + } + set { + this.scanField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "0.0.0.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)] + public enum ArchitecturesTypeArchitecture { + + /// + [System.Xml.Serialization.XmlEnumAttribute("4004")] + Item4004, + + /// + [System.Xml.Serialization.XmlEnumAttribute("4040")] + Item4040, + + /// + [System.Xml.Serialization.XmlEnumAttribute("6502")] + Item6502, + + /// + [System.Xml.Serialization.XmlEnumAttribute("65816")] + Item65816, + + /// + [System.Xml.Serialization.XmlEnumAttribute("8008")] + Item8008, + + /// + [System.Xml.Serialization.XmlEnumAttribute("8051")] + Item8051, + + /// + [System.Xml.Serialization.XmlEnumAttribute("8080")] + Item8080, + + /// + [System.Xml.Serialization.XmlEnumAttribute("8085")] + Item8085, + + /// + aarch64, + + /// + am29000, + + /// + amd64, + + /// + apx432, + + /// + arm, + + /// + avr, + + /// + avr32, + + /// + axp, + + /// + clipper, + + /// + cray, + + /// + esa390, + + /// + hobbit, + + /// + i86, + + /// + i860, + + /// + i960, + + /// + ia32, + + /// + ia64, + + /// + m56k, + + /// + m6800, + + /// + m6801, + + /// + m6805, + + /// + m6809, + + /// + m68k, + + /// + m88k, + + /// + mcs41, + + /// + mcs48, + + /// + mips32, + + /// + mips64, + + /// + msp430, + + /// + nios2, + + /// + openrisc, + + /// + parisc, + + /// + pdp1, + + /// + pdp10, + + /// + pdp11, + + /// + pdp7, + + /// + pdp8, + + /// + pic, + + /// + power, + + /// + ppc, + + /// + ppc64, + + /// + prism, + + /// + renesasrx, + + /// + riscv, + + /// + s360, + + /// + s370, + + /// + sh, + + /// + sh1, + + /// + sh2, + + /// + sh3, + + /// + sh4, + + /// + sh5, + + /// + sh64, + + /// + sparc, + + /// + sparc64, + + /// + transputer, + + /// + vax, + + /// + we32000, + + /// + x32, + + /// + z80, + + /// + z800, + + /// + z8000, + + /// + z80000, + + /// + zarch, + } +} diff --git a/CICMMetadata/dotnet/cicm.vb b/CICMMetadata/dotnet/cicm.vb new file mode 100644 index 000000000..ea33ddb09 --- /dev/null +++ b/CICMMetadata/dotnet/cicm.vb @@ -0,0 +1,9093 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict Off +Option Explicit On + + +' +'This source code was auto-generated by MonoXSD +' +Namespace Schemas + + ''' + _ + Partial Public Class CICMMetadataType + + Private developerField() As String + + Private publisherField() As String + + Private authorField() As String + + Private performerField() As String + + Private nameField As String + + Private versionField As String + + Private releaseTypeField As CICMMetadataTypeReleaseType + + Private releaseTypeFieldSpecified As Boolean + + Private releaseDateField As Date + + Private releaseDateFieldSpecified As Boolean + + Private barcodesField() As BarcodeType + + Private partNumberField As String + + Private serialNumberField As String + + Private keywordsField() As String + + Private magazineField() As MagazineType + + Private bookField() As BookType + + Private categoriesField() As String + + Private subcategoriesField() As String + + Private languagesField() As LanguagesTypeLanguage + + Private systemsField() As String + + Private architecturesField() As ArchitecturesTypeArchitecture + + Private requiredOperatingSystemsField() As RequiredOperatingSystemType + + Private userManualField() As UserManualType + + Private opticalDiscField() As OpticalDiscType + + Private advertisementField() As AdvertisementType + + Private linearMediaField() As LinearMediaType + + Private pCICardField() As PCIType + + Private blockMediaField() As BlockMediaType + + Private audioMediaField() As AudioMediaType + + ''' + _ + Public Property Developer() As String() + Get + Return Me.developerField + End Get + Set + Me.developerField = value + End Set + End Property + + ''' + _ + Public Property Publisher() As String() + Get + Return Me.publisherField + End Get + Set + Me.publisherField = value + End Set + End Property + + ''' + _ + Public Property Author() As String() + Get + Return Me.authorField + End Get + Set + Me.authorField = value + End Set + End Property + + ''' + _ + Public Property Performer() As String() + Get + Return Me.performerField + End Get + Set + Me.performerField = value + End Set + End Property + + ''' + Public Property Name() As String + Get + Return Me.nameField + End Get + Set + Me.nameField = value + End Set + End Property + + ''' + Public Property Version() As String + Get + Return Me.versionField + End Get + Set + Me.versionField = value + End Set + End Property + + ''' + Public Property ReleaseType() As CICMMetadataTypeReleaseType + Get + Return Me.releaseTypeField + End Get + Set + Me.releaseTypeField = value + End Set + End Property + + ''' + _ + Public Property ReleaseTypeSpecified() As Boolean + Get + Return Me.releaseTypeFieldSpecified + End Get + Set + Me.releaseTypeFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property ReleaseDate() As Date + Get + Return Me.releaseDateField + End Get + Set + Me.releaseDateField = value + End Set + End Property + + ''' + _ + Public Property ReleaseDateSpecified() As Boolean + Get + Return Me.releaseDateFieldSpecified + End Get + Set + Me.releaseDateFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property Barcodes() As BarcodeType() + Get + Return Me.barcodesField + End Get + Set + Me.barcodesField = value + End Set + End Property + + ''' + Public Property PartNumber() As String + Get + Return Me.partNumberField + End Get + Set + Me.partNumberField = value + End Set + End Property + + ''' + Public Property SerialNumber() As String + Get + Return Me.serialNumberField + End Get + Set + Me.serialNumberField = value + End Set + End Property + + ''' + _ + Public Property Keywords() As String() + Get + Return Me.keywordsField + End Get + Set + Me.keywordsField = value + End Set + End Property + + ''' + _ + Public Property Magazine() As MagazineType() + Get + Return Me.magazineField + End Get + Set + Me.magazineField = value + End Set + End Property + + ''' + _ + Public Property Book() As BookType() + Get + Return Me.bookField + End Get + Set + Me.bookField = value + End Set + End Property + + ''' + _ + Public Property Categories() As String() + Get + Return Me.categoriesField + End Get + Set + Me.categoriesField = value + End Set + End Property + + ''' + _ + Public Property Subcategories() As String() + Get + Return Me.subcategoriesField + End Get + Set + Me.subcategoriesField = value + End Set + End Property + + ''' + _ + Public Property Languages() As LanguagesTypeLanguage() + Get + Return Me.languagesField + End Get + Set + Me.languagesField = value + End Set + End Property + + ''' + _ + Public Property Systems() As String() + Get + Return Me.systemsField + End Get + Set + Me.systemsField = value + End Set + End Property + + ''' + _ + Public Property Architectures() As ArchitecturesTypeArchitecture() + Get + Return Me.architecturesField + End Get + Set + Me.architecturesField = value + End Set + End Property + + ''' + _ + Public Property RequiredOperatingSystems() As RequiredOperatingSystemType() + Get + Return Me.requiredOperatingSystemsField + End Get + Set + Me.requiredOperatingSystemsField = value + End Set + End Property + + ''' + _ + Public Property UserManual() As UserManualType() + Get + Return Me.userManualField + End Get + Set + Me.userManualField = value + End Set + End Property + + ''' + _ + Public Property OpticalDisc() As OpticalDiscType() + Get + Return Me.opticalDiscField + End Get + Set + Me.opticalDiscField = value + End Set + End Property + + ''' + _ + Public Property Advertisement() As AdvertisementType() + Get + Return Me.advertisementField + End Get + Set + Me.advertisementField = value + End Set + End Property + + ''' + _ + Public Property LinearMedia() As LinearMediaType() + Get + Return Me.linearMediaField + End Get + Set + Me.linearMediaField = value + End Set + End Property + + ''' + _ + Public Property PCICard() As PCIType() + Get + Return Me.pCICardField + End Get + Set + Me.pCICardField = value + End Set + End Property + + ''' + _ + Public Property BlockMedia() As BlockMediaType() + Get + Return Me.blockMediaField + End Get + Set + Me.blockMediaField = value + End Set + End Property + + ''' + _ + Public Property AudioMedia() As AudioMediaType() + Get + Return Me.audioMediaField + End Get + Set + Me.audioMediaField = value + End Set + End Property + End Class + + ''' + _ + Public Enum CICMMetadataTypeReleaseType + + ''' + Retail + + ''' + Bundle + + ''' + Coverdisc + + ''' + Subscription + + ''' + Demo + + ''' + OEM + + ''' + Shareware + + ''' + FOSS + + ''' + Adware + + ''' + Donationware + + ''' + _ + Digitaldownload + + ''' + SaaS + End Enum + + ''' + _ + Partial Public Class BarcodeType + + Private typeField As BarcodeTypeType + + Private valueField As String + + ''' + _ + Public Property type() As BarcodeTypeType + Get + Return Me.typeField + End Get + Set + Me.typeField = value + End Set + End Property + + ''' + _ + Public Property Value() As String + Get + Return Me.valueField + End Get + Set + Me.valueField = value + End Set + End Property + End Class + + ''' + _ + Public Enum BarcodeTypeType + + ''' + aztec + + ''' + codabar + + ''' + code11 + + ''' + code128 + + ''' + code39 + + ''' + code93 + + ''' + cpcbinary + + ''' + ezcode + + ''' + fim + + ''' + itf + + ''' + itf14 + + ''' + ean13 + + ''' + ean8 + + ''' + maxicode + + ''' + isbn + + ''' + isrc + + ''' + msi + + ''' + tof + + ''' + shotcode + + ''' + rm4scc + + ''' + qr + + ''' + ean5 + + ''' + ean2 + + ''' + _ + qr1 + + ''' + postnet + + ''' + postbar + + ''' + plessey + + ''' + pharmacode + + ''' + pdf417 + + ''' + patchcode + End Enum + + ''' + _ + Partial Public Class AudioBlockType + + Private imageField As ImageType + + Private sizeField As ULong + + Private accoustIDField As String + + Private checksumsField() As ChecksumType + + Private formatField As String + + ''' + Public Property Image() As ImageType + Get + Return Me.imageField + End Get + Set + Me.imageField = value + End Set + End Property + + ''' + Public Property Size() As ULong + Get + Return Me.sizeField + End Get + Set + Me.sizeField = value + End Set + End Property + + ''' + Public Property AccoustID() As String + Get + Return Me.accoustIDField + End Get + Set + Me.accoustIDField = value + End Set + End Property + + ''' + _ + Public Property Checksums() As ChecksumType() + Get + Return Me.checksumsField + End Get + Set + Me.checksumsField = value + End Set + End Property + + ''' + Public Property Format() As String + Get + Return Me.formatField + End Get + Set + Me.formatField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class ImageType + + Private formatField As String + + Private offsetField As ULong + + Private offsetFieldSpecified As Boolean + + Private valueField As String + + ''' + _ + Public Property format() As String + Get + Return Me.formatField + End Get + Set + Me.formatField = value + End Set + End Property + + ''' + _ + Public Property offset() As ULong + Get + Return Me.offsetField + End Get + Set + Me.offsetField = value + End Set + End Property + + ''' + _ + Public Property offsetSpecified() As Boolean + Get + Return Me.offsetFieldSpecified + End Get + Set + Me.offsetFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property Value() As String + Get + Return Me.valueField + End Get + Set + Me.valueField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class ChecksumType + + Private typeField As ChecksumTypeType + + Private valueField As String + + ''' + _ + Public Property type() As ChecksumTypeType + Get + Return Me.typeField + End Get + Set + Me.typeField = value + End Set + End Property + + ''' + _ + Public Property Value() As String + Get + Return Me.valueField + End Get + Set + Me.valueField = value + End Set + End Property + End Class + + ''' + _ + Public Enum ChecksumTypeType + + ''' + fletcher16 + + ''' + fletcher32 + + ''' + adler32 + + ''' + crc16 + + ''' + crc16ccitt + + ''' + crc32 + + ''' + crc64 + + ''' + md4 + + ''' + md5 + + ''' + dm6 + + ''' + ripemd128 + + ''' + ripemd160 + + ''' + ripemed320 + + ''' + sha1 + + ''' + sha224 + + ''' + sha256 + + ''' + sha384 + + ''' + sha512 + + ''' + sha3 + + ''' + skein + + ''' + snefru + + ''' + blake256 + + ''' + blake512 + + ''' + tiger + + ''' + whirlpool + + ''' + spamsum + End Enum + + ''' + _ + Partial Public Class AudioMediaType + + Private imageField As ImageType + + Private sizeField As ULong + + Private checksumsField() As ChecksumType + + Private sequenceField As SequenceType + + Private partNumberField As String + + Private serialNumberField As String + + Private manufacturerField As String + + Private modelField As String + + Private accoustIDField As String + + Private blockField() As AudioBlockType + + Private copyProtectionField As String + + Private dimensionsField As DimensionsType + + Private scansField As ScansType + + Private dumpHardwareArrayField() As DumpHardwareType + + ''' + Public Property Image() As ImageType + Get + Return Me.imageField + End Get + Set + Me.imageField = value + End Set + End Property + + ''' + Public Property Size() As ULong + Get + Return Me.sizeField + End Get + Set + Me.sizeField = value + End Set + End Property + + ''' + _ + Public Property Checksums() As ChecksumType() + Get + Return Me.checksumsField + End Get + Set + Me.checksumsField = value + End Set + End Property + + ''' + Public Property Sequence() As SequenceType + Get + Return Me.sequenceField + End Get + Set + Me.sequenceField = value + End Set + End Property + + ''' + Public Property PartNumber() As String + Get + Return Me.partNumberField + End Get + Set + Me.partNumberField = value + End Set + End Property + + ''' + Public Property SerialNumber() As String + Get + Return Me.serialNumberField + End Get + Set + Me.serialNumberField = value + End Set + End Property + + ''' + Public Property Manufacturer() As String + Get + Return Me.manufacturerField + End Get + Set + Me.manufacturerField = value + End Set + End Property + + ''' + Public Property Model() As String + Get + Return Me.modelField + End Get + Set + Me.modelField = value + End Set + End Property + + ''' + Public Property AccoustID() As String + Get + Return Me.accoustIDField + End Get + Set + Me.accoustIDField = value + End Set + End Property + + ''' + _ + Public Property Block() As AudioBlockType() + Get + Return Me.blockField + End Get + Set + Me.blockField = value + End Set + End Property + + ''' + Public Property CopyProtection() As String + Get + Return Me.copyProtectionField + End Get + Set + Me.copyProtectionField = value + End Set + End Property + + ''' + Public Property Dimensions() As DimensionsType + Get + Return Me.dimensionsField + End Get + Set + Me.dimensionsField = value + End Set + End Property + + ''' + Public Property Scans() As ScansType + Get + Return Me.scansField + End Get + Set + Me.scansField = value + End Set + End Property + + ''' + _ + Public Property DumpHardwareArray() As DumpHardwareType() + Get + Return Me.dumpHardwareArrayField + End Get + Set + Me.dumpHardwareArrayField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class SequenceType + + Private mediaTitleField As String + + Private mediaSequenceField As UInteger + + Private totalMediaField As UInteger + + Private sideField As Byte + + Private sideFieldSpecified As Boolean + + Private layerField As Byte + + Private layerFieldSpecified As Boolean + + ''' + Public Property MediaTitle() As String + Get + Return Me.mediaTitleField + End Get + Set + Me.mediaTitleField = value + End Set + End Property + + ''' + Public Property MediaSequence() As UInteger + Get + Return Me.mediaSequenceField + End Get + Set + Me.mediaSequenceField = value + End Set + End Property + + ''' + Public Property TotalMedia() As UInteger + Get + Return Me.totalMediaField + End Get + Set + Me.totalMediaField = value + End Set + End Property + + ''' + Public Property Side() As Byte + Get + Return Me.sideField + End Get + Set + Me.sideField = value + End Set + End Property + + ''' + _ + Public Property SideSpecified() As Boolean + Get + Return Me.sideFieldSpecified + End Get + Set + Me.sideFieldSpecified = value + End Set + End Property + + ''' + Public Property Layer() As Byte + Get + Return Me.layerField + End Get + Set + Me.layerField = value + End Set + End Property + + ''' + _ + Public Property LayerSpecified() As Boolean + Get + Return Me.layerFieldSpecified + End Get + Set + Me.layerFieldSpecified = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class DimensionsType + + Private diameterField As Double + + Private diameterFieldSpecified As Boolean + + Private heightField As Double + + Private heightFieldSpecified As Boolean + + Private widthField As Double + + Private widthFieldSpecified As Boolean + + Private thicknessField As Double + + ''' + Public Property Diameter() As Double + Get + Return Me.diameterField + End Get + Set + Me.diameterField = value + End Set + End Property + + ''' + _ + Public Property DiameterSpecified() As Boolean + Get + Return Me.diameterFieldSpecified + End Get + Set + Me.diameterFieldSpecified = value + End Set + End Property + + ''' + Public Property Height() As Double + Get + Return Me.heightField + End Get + Set + Me.heightField = value + End Set + End Property + + ''' + _ + Public Property HeightSpecified() As Boolean + Get + Return Me.heightFieldSpecified + End Get + Set + Me.heightFieldSpecified = value + End Set + End Property + + ''' + Public Property Width() As Double + Get + Return Me.widthField + End Get + Set + Me.widthField = value + End Set + End Property + + ''' + _ + Public Property WidthSpecified() As Boolean + Get + Return Me.widthFieldSpecified + End Get + Set + Me.widthFieldSpecified = value + End Set + End Property + + ''' + Public Property Thickness() As Double + Get + Return Me.thicknessField + End Get + Set + Me.thicknessField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class ScansType + + Private caseScanField As CaseScanType + + Private scanField As MediaScanType + + ''' + Public Property CaseScan() As CaseScanType + Get + Return Me.caseScanField + End Get + Set + Me.caseScanField = value + End Set + End Property + + ''' + Public Property Scan() As MediaScanType + Get + Return Me.scanField + End Get + Set + Me.scanField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class CaseScanType + + Private caseScanElementField As CaseScanTypeCaseScanElement + + Private scanField As ScanType + + ''' + Public Property CaseScanElement() As CaseScanTypeCaseScanElement + Get + Return Me.caseScanElementField + End Get + Set + Me.caseScanElementField = value + End Set + End Property + + ''' + Public Property Scan() As ScanType + Get + Return Me.scanField + End Get + Set + Me.scanField = value + End Set + End Property + End Class + + ''' + _ + Public Enum CaseScanTypeCaseScanElement + + ''' + sleeve + + ''' + inner + + ''' + inlay + + ''' + frontback + + ''' + frontfull + + ''' + boxfront + + ''' + boxback + + ''' + boxspine + + ''' + external + End Enum + + ''' + _ + Partial Public Class ScanType + + Private fileField As FileType + + Private checksumsField() As ChecksumType + + Private scannerField() As ScannerType + + Private scanProcessingField() As ScanProcessingType + + Private oCRField() As OCRType + + ''' + Public Property File() As FileType + Get + Return Me.fileField + End Get + Set + Me.fileField = value + End Set + End Property + + ''' + _ + Public Property Checksums() As ChecksumType() + Get + Return Me.checksumsField + End Get + Set + Me.checksumsField = value + End Set + End Property + + ''' + _ + Public Property Scanner() As ScannerType() + Get + Return Me.scannerField + End Get + Set + Me.scannerField = value + End Set + End Property + + ''' + _ + Public Property ScanProcessing() As ScanProcessingType() + Get + Return Me.scanProcessingField + End Get + Set + Me.scanProcessingField = value + End Set + End Property + + ''' + _ + Public Property OCR() As OCRType() + Get + Return Me.oCRField + End Get + Set + Me.oCRField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class FileType + + Private formatField As String + + Private valueField As String + + ''' + _ + Public Property format() As String + Get + Return Me.formatField + End Get + Set + Me.formatField = value + End Set + End Property + + ''' + _ + Public Property Value() As String + Get + Return Me.valueField + End Get + Set + Me.valueField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class ScannerType + + Private authorField As String + + Private manufacturerField As String + + Private modelField As String + + Private serialField As String + + Private softwareField As String + + Private softwareVersionField As String + + ''' + Public Property Author() As String + Get + Return Me.authorField + End Get + Set + Me.authorField = value + End Set + End Property + + ''' + Public Property Manufacturer() As String + Get + Return Me.manufacturerField + End Get + Set + Me.manufacturerField = value + End Set + End Property + + ''' + Public Property Model() As String + Get + Return Me.modelField + End Get + Set + Me.modelField = value + End Set + End Property + + ''' + Public Property Serial() As String + Get + Return Me.serialField + End Get + Set + Me.serialField = value + End Set + End Property + + ''' + Public Property Software() As String + Get + Return Me.softwareField + End Get + Set + Me.softwareField = value + End Set + End Property + + ''' + Public Property SoftwareVersion() As String + Get + Return Me.softwareVersionField + End Get + Set + Me.softwareVersionField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class ScanProcessingType + + Private authorField As String + + Private softwareField As String + + Private softwareVersionField As String + + ''' + Public Property Author() As String + Get + Return Me.authorField + End Get + Set + Me.authorField = value + End Set + End Property + + ''' + Public Property Software() As String + Get + Return Me.softwareField + End Get + Set + Me.softwareField = value + End Set + End Property + + ''' + Public Property SoftwareVersion() As String + Get + Return Me.softwareVersionField + End Get + Set + Me.softwareVersionField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class OCRType + + Private authorField As String + + Private softwareField As String + + Private softwareVersionField As String + + Private languageField() As LanguagesTypeLanguage + + ''' + Public Property Author() As String + Get + Return Me.authorField + End Get + Set + Me.authorField = value + End Set + End Property + + ''' + Public Property Software() As String + Get + Return Me.softwareField + End Get + Set + Me.softwareField = value + End Set + End Property + + ''' + Public Property SoftwareVersion() As String + Get + Return Me.softwareVersionField + End Get + Set + Me.softwareVersionField = value + End Set + End Property + + ''' + _ + Public Property Language() As LanguagesTypeLanguage() + Get + Return Me.languageField + End Get + Set + Me.languageField = value + End Set + End Property + End Class + + ''' + _ + Public Enum LanguagesTypeLanguage + + ''' + aar + + ''' + abk + + ''' + ace + + ''' + ach + + ''' + ada + + ''' + ady + + ''' + afa + + ''' + afh + + ''' + afr + + ''' + ain + + ''' + aka + + ''' + akk + + ''' + alb + + ''' + ale + + ''' + alg + + ''' + alt + + ''' + amh + + ''' + ang + + ''' + anp + + ''' + apa + + ''' + ara + + ''' + arc + + ''' + arg + + ''' + arm + + ''' + arn + + ''' + arp + + ''' + art + + ''' + arw + + ''' + asm + + ''' + ast + + ''' + ath + + ''' + aus + + ''' + ava + + ''' + ave + + ''' + awa + + ''' + aym + + ''' + aze + + ''' + bad + + ''' + bai + + ''' + bak + + ''' + bal + + ''' + bam + + ''' + ban + + ''' + baq + + ''' + bas + + ''' + bat + + ''' + bej + + ''' + bel + + ''' + bem + + ''' + ben + + ''' + ber + + ''' + bho + + ''' + bih + + ''' + bik + + ''' + bin + + ''' + bis + + ''' + bla + + ''' + bnt + + ''' + bos + + ''' + bra + + ''' + bre + + ''' + btk + + ''' + bua + + ''' + bug + + ''' + bul + + ''' + bur + + ''' + byn + + ''' + cad + + ''' + cai + + ''' + car + + ''' + cat + + ''' + cau + + ''' + ceb + + ''' + cel + + ''' + cha + + ''' + chb + + ''' + che + + ''' + chg + + ''' + chi + + ''' + chk + + ''' + chm + + ''' + chn + + ''' + cho + + ''' + chp + + ''' + chr + + ''' + chu + + ''' + chv + + ''' + chy + + ''' + cmc + + ''' + cop + + ''' + cor + + ''' + cos + + ''' + cpe + + ''' + cpf + + ''' + cpp + + ''' + cre + + ''' + crh + + ''' + crp + + ''' + csb + + ''' + cus + + ''' + cze + + ''' + dak + + ''' + dan + + ''' + dar + + ''' + day + + ''' + del + + ''' + den + + ''' + dgr + + ''' + din + + ''' + div + + ''' + doi + + ''' + dra + + ''' + dsb + + ''' + dua + + ''' + dum + + ''' + dut + + ''' + dyu + + ''' + dzo + + ''' + efi + + ''' + egy + + ''' + eka + + ''' + elx + + ''' + eng + + ''' + enm + + ''' + epo + + ''' + est + + ''' + ewe + + ''' + ewo + + ''' + fan + + ''' + fao + + ''' + fat + + ''' + fij + + ''' + fil + + ''' + fin + + ''' + fiu + + ''' + fon + + ''' + fre + + ''' + frm + + ''' + fro + + ''' + frr + + ''' + frs + + ''' + fry + + ''' + ful + + ''' + fur + + ''' + gaa + + ''' + gay + + ''' + gba + + ''' + gem + + ''' + geo + + ''' + ger + + ''' + gez + + ''' + gil + + ''' + gla + + ''' + gle + + ''' + glg + + ''' + glv + + ''' + gmh + + ''' + goh + + ''' + gon + + ''' + gor + + ''' + got + + ''' + grb + + ''' + grc + + ''' + gre + + ''' + grn + + ''' + gsw + + ''' + guj + + ''' + gwi + + ''' + hai + + ''' + hat + + ''' + hau + + ''' + haw + + ''' + heb + + ''' + her + + ''' + hil + + ''' + him + + ''' + hin + + ''' + hit + + ''' + hmn + + ''' + hmo + + ''' + hrv + + ''' + hsb + + ''' + hun + + ''' + hup + + ''' + iba + + ''' + ibo + + ''' + ice + + ''' + ido + + ''' + iii + + ''' + ijo + + ''' + iku + + ''' + ile + + ''' + ilo + + ''' + ina + + ''' + inc + + ''' + ind + + ''' + ine + + ''' + inh + + ''' + ipk + + ''' + ira + + ''' + iro + + ''' + ita + + ''' + jav + + ''' + jbo + + ''' + jpn + + ''' + jpr + + ''' + jrb + + ''' + kaa + + ''' + kab + + ''' + kac + + ''' + kal + + ''' + kam + + ''' + kan + + ''' + kar + + ''' + kas + + ''' + kau + + ''' + kaw + + ''' + kaz + + ''' + kbd + + ''' + kha + + ''' + khi + + ''' + khm + + ''' + kho + + ''' + kik + + ''' + kin + + ''' + kir + + ''' + kmb + + ''' + kok + + ''' + kom + + ''' + kon + + ''' + kor + + ''' + kos + + ''' + kpe + + ''' + krc + + ''' + krl + + ''' + kro + + ''' + kru + + ''' + kua + + ''' + kum + + ''' + kur + + ''' + kut + + ''' + lad + + ''' + lah + + ''' + lam + + ''' + lao + + ''' + lat + + ''' + lav + + ''' + lez + + ''' + lim + + ''' + lin + + ''' + lit + + ''' + lol + + ''' + loz + + ''' + ltz + + ''' + lua + + ''' + lub + + ''' + lug + + ''' + lui + + ''' + lun + + ''' + luo + + ''' + lus + + ''' + mac + + ''' + mad + + ''' + mag + + ''' + mah + + ''' + mai + + ''' + mak + + ''' + mal + + ''' + man + + ''' + mao + + ''' + map + + ''' + mar + + ''' + mas + + ''' + may + + ''' + mdf + + ''' + mdr + + ''' + men + + ''' + mga + + ''' + mic + + ''' + min + + ''' + mis + + ''' + mkh + + ''' + mlg + + ''' + mlt + + ''' + mnc + + ''' + mni + + ''' + mno + + ''' + moh + + ''' + mon + + ''' + mos + + ''' + mul + + ''' + mun + + ''' + mus + + ''' + mwl + + ''' + mwr + + ''' + myn + + ''' + myv + + ''' + nah + + ''' + nai + + ''' + nap + + ''' + nau + + ''' + nav + + ''' + nbl + + ''' + nde + + ''' + ndo + + ''' + nds + + ''' + nep + + ''' + [new] + + ''' + nia + + ''' + nic + + ''' + niu + + ''' + nno + + ''' + nob + + ''' + nog + + ''' + non + + ''' + nor + + ''' + nqo + + ''' + nso + + ''' + nub + + ''' + nwc + + ''' + nya + + ''' + nym + + ''' + nyn + + ''' + nyo + + ''' + nzi + + ''' + oci + + ''' + oji + + ''' + ori + + ''' + orm + + ''' + osa + + ''' + oss + + ''' + ota + + ''' + oto + + ''' + paa + + ''' + pag + + ''' + pal + + ''' + pam + + ''' + pan + + ''' + pap + + ''' + pau + + ''' + peo + + ''' + per + + ''' + phi + + ''' + phn + + ''' + pli + + ''' + pol + + ''' + pon + + ''' + por + + ''' + pra + + ''' + pro + + ''' + pus + + ''' + _ + qaaqtz + + ''' + que + + ''' + raj + + ''' + rap + + ''' + rar + + ''' + roa + + ''' + roh + + ''' + rom + + ''' + rum + + ''' + run + + ''' + rup + + ''' + rus + + ''' + sad + + ''' + sag + + ''' + sah + + ''' + sai + + ''' + sal + + ''' + sam + + ''' + san + + ''' + sas + + ''' + sat + + ''' + scn + + ''' + sco + + ''' + sel + + ''' + sem + + ''' + sga + + ''' + sgn + + ''' + shn + + ''' + sid + + ''' + sin + + ''' + sio + + ''' + sit + + ''' + sla + + ''' + slo + + ''' + slv + + ''' + sma + + ''' + sme + + ''' + smi + + ''' + smj + + ''' + smn + + ''' + smo + + ''' + sms + + ''' + sna + + ''' + snd + + ''' + snk + + ''' + sog + + ''' + som + + ''' + son + + ''' + sot + + ''' + spa + + ''' + srd + + ''' + srn + + ''' + srp + + ''' + srr + + ''' + ssa + + ''' + ssw + + ''' + suk + + ''' + sun + + ''' + sus + + ''' + sux + + ''' + swa + + ''' + swe + + ''' + syc + + ''' + syr + + ''' + tah + + ''' + tai + + ''' + tam + + ''' + tat + + ''' + tel + + ''' + tem + + ''' + ter + + ''' + tet + + ''' + tgk + + ''' + tgl + + ''' + tha + + ''' + tib + + ''' + tig + + ''' + tir + + ''' + tiv + + ''' + tkl + + ''' + tlh + + ''' + tli + + ''' + tmh + + ''' + tog + + ''' + ton + + ''' + tpi + + ''' + tsi + + ''' + tsn + + ''' + tso + + ''' + tuk + + ''' + tum + + ''' + tup + + ''' + tur + + ''' + tut + + ''' + tvl + + ''' + twi + + ''' + tyv + + ''' + udm + + ''' + uga + + ''' + uig + + ''' + ukr + + ''' + umb + + ''' + und + + ''' + urd + + ''' + uzb + + ''' + vai + + ''' + ven + + ''' + vie + + ''' + vol + + ''' + vot + + ''' + wak + + ''' + wal + + ''' + war + + ''' + was + + ''' + wel + + ''' + wen + + ''' + wln + + ''' + wol + + ''' + xal + + ''' + xho + + ''' + yao + + ''' + yap + + ''' + yid + + ''' + yor + + ''' + ypk + + ''' + zap + + ''' + zbl + + ''' + zen + + ''' + zgh + + ''' + zha + + ''' + znd + + ''' + zul + + ''' + zun + + ''' + zxx + + ''' + zza + End Enum + + ''' + _ + Partial Public Class MediaScanType + + Private mediaScanElementField As MediaScanTypeMediaScanElement + + Private scanField As ScanType + + ''' + Public Property MediaScanElement() As MediaScanTypeMediaScanElement + Get + Return Me.mediaScanElementField + End Get + Set + Me.mediaScanElementField = value + End Set + End Property + + ''' + Public Property Scan() As ScanType + Get + Return Me.scanField + End Get + Set + Me.scanField = value + End Set + End Property + End Class + + ''' + _ + Public Enum MediaScanTypeMediaScanElement + + ''' + up + + ''' + down + + ''' + front + + ''' + back + + ''' + left + + ''' + right + End Enum + + ''' + _ + Partial Public Class DumpHardwareType + + Private manufacturerField As String + + Private modelField As String + + Private revisionField As String + + Private firmwareField As String + + Private serialField As String + + Private extentsField() As ExtentType + + Private softwareField As SoftwareType + + ''' + Public Property Manufacturer() As String + Get + Return Me.manufacturerField + End Get + Set + Me.manufacturerField = value + End Set + End Property + + ''' + Public Property Model() As String + Get + Return Me.modelField + End Get + Set + Me.modelField = value + End Set + End Property + + ''' + Public Property Revision() As String + Get + Return Me.revisionField + End Get + Set + Me.revisionField = value + End Set + End Property + + ''' + Public Property Firmware() As String + Get + Return Me.firmwareField + End Get + Set + Me.firmwareField = value + End Set + End Property + + ''' + Public Property Serial() As String + Get + Return Me.serialField + End Get + Set + Me.serialField = value + End Set + End Property + + ''' + _ + Public Property Extents() As ExtentType() + Get + Return Me.extentsField + End Get + Set + Me.extentsField = value + End Set + End Property + + ''' + Public Property Software() As SoftwareType + Get + Return Me.softwareField + End Get + Set + Me.softwareField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class ExtentType + + Private startField As ULong + + Private endField As ULong + + ''' + Public Property Start() As ULong + Get + Return Me.startField + End Get + Set + Me.startField = value + End Set + End Property + + ''' + Public Property [End]() As ULong + Get + Return Me.endField + End Get + Set + Me.endField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class SoftwareType + + Private nameField As String + + Private versionField As String + + Private operatingSystemField As String + + ''' + Public Property Name() As String + Get + Return Me.nameField + End Get + Set + Me.nameField = value + End Set + End Property + + ''' + Public Property Version() As String + Get + Return Me.versionField + End Get + Set + Me.versionField = value + End Set + End Property + + ''' + Public Property OperatingSystem() As String + Get + Return Me.operatingSystemField + End Get + Set + Me.operatingSystemField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class BlockTrackType + + Private imageField As ImageType + + Private sizeField As ULong + + Private headField As UShort + + Private cylinderField As UInteger + + Private startSectorField As ULong + + Private endSectorField As ULong + + Private sectorsField As ULong + + Private bytesPerSectorField As UInteger + + Private checksumsField() As ChecksumType + + Private formatField As String + + ''' + Public Property Image() As ImageType + Get + Return Me.imageField + End Get + Set + Me.imageField = value + End Set + End Property + + ''' + Public Property Size() As ULong + Get + Return Me.sizeField + End Get + Set + Me.sizeField = value + End Set + End Property + + ''' + Public Property Head() As UShort + Get + Return Me.headField + End Get + Set + Me.headField = value + End Set + End Property + + ''' + Public Property Cylinder() As UInteger + Get + Return Me.cylinderField + End Get + Set + Me.cylinderField = value + End Set + End Property + + ''' + Public Property StartSector() As ULong + Get + Return Me.startSectorField + End Get + Set + Me.startSectorField = value + End Set + End Property + + ''' + Public Property EndSector() As ULong + Get + Return Me.endSectorField + End Get + Set + Me.endSectorField = value + End Set + End Property + + ''' + Public Property Sectors() As ULong + Get + Return Me.sectorsField + End Get + Set + Me.sectorsField = value + End Set + End Property + + ''' + Public Property BytesPerSector() As UInteger + Get + Return Me.bytesPerSectorField + End Get + Set + Me.bytesPerSectorField = value + End Set + End Property + + ''' + _ + Public Property Checksums() As ChecksumType() + Get + Return Me.checksumsField + End Get + Set + Me.checksumsField = value + End Set + End Property + + ''' + Public Property Format() As String + Get + Return Me.formatField + End Get + Set + Me.formatField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class USBType + + Private vendorIDField As UShort + + Private productIDField As UShort + + Private descriptorsField As DumpType + + ''' + Public Property VendorID() As UShort + Get + Return Me.vendorIDField + End Get + Set + Me.vendorIDField = value + End Set + End Property + + ''' + Public Property ProductID() As UShort + Get + Return Me.productIDField + End Get + Set + Me.productIDField = value + End Set + End Property + + ''' + Public Property Descriptors() As DumpType + Get + Return Me.descriptorsField + End Get + Set + Me.descriptorsField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class DumpType + + Private imageField As String + + Private sizeField As ULong + + Private checksumsField() As ChecksumType + + ''' + Public Property Image() As String + Get + Return Me.imageField + End Get + Set + Me.imageField = value + End Set + End Property + + ''' + Public Property Size() As ULong + Get + Return Me.sizeField + End Get + Set + Me.sizeField = value + End Set + End Property + + ''' + _ + Public Property Checksums() As ChecksumType() + Get + Return Me.checksumsField + End Get + Set + Me.checksumsField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class EVPDType + + Private imageField As String + + Private sizeField As ULong + + Private checksumsField() As ChecksumType + + Private pageField As Byte + + Private pageFieldSpecified As Boolean + + ''' + Public Property Image() As String + Get + Return Me.imageField + End Get + Set + Me.imageField = value + End Set + End Property + + ''' + Public Property Size() As ULong + Get + Return Me.sizeField + End Get + Set + Me.sizeField = value + End Set + End Property + + ''' + _ + Public Property Checksums() As ChecksumType() + Get + Return Me.checksumsField + End Get + Set + Me.checksumsField = value + End Set + End Property + + ''' + _ + Public Property page() As Byte + Get + Return Me.pageField + End Get + Set + Me.pageField = value + End Set + End Property + + ''' + _ + Public Property pageSpecified() As Boolean + Get + Return Me.pageFieldSpecified + End Get + Set + Me.pageFieldSpecified = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class SCSIType + + Private inquiryField As DumpType + + Private eVPDField() As EVPDType + + Private modeSenseField As DumpType + + Private modeSense10Field As DumpType + + Private logSenseField As DumpType + + ''' + Public Property Inquiry() As DumpType + Get + Return Me.inquiryField + End Get + Set + Me.inquiryField = value + End Set + End Property + + ''' + _ + Public Property EVPD() As EVPDType() + Get + Return Me.eVPDField + End Get + Set + Me.eVPDField = value + End Set + End Property + + ''' + Public Property ModeSense() As DumpType + Get + Return Me.modeSenseField + End Get + Set + Me.modeSenseField = value + End Set + End Property + + ''' + Public Property ModeSense10() As DumpType + Get + Return Me.modeSense10Field + End Get + Set + Me.modeSense10Field = value + End Set + End Property + + ''' + Public Property LogSense() As DumpType + Get + Return Me.logSenseField + End Get + Set + Me.logSenseField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class MultiMediaCardType + + Private cIDField As DumpType + + Private cSDField As DumpType + + Private extendedCSDField As DumpType + + Private oCRField As DumpType + + ''' + Public Property CID() As DumpType + Get + Return Me.cIDField + End Get + Set + Me.cIDField = value + End Set + End Property + + ''' + Public Property CSD() As DumpType + Get + Return Me.cSDField + End Get + Set + Me.cSDField = value + End Set + End Property + + ''' + Public Property ExtendedCSD() As DumpType + Get + Return Me.extendedCSDField + End Get + Set + Me.extendedCSDField = value + End Set + End Property + + ''' + Public Property OCR() As DumpType + Get + Return Me.oCRField + End Get + Set + Me.oCRField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class SecureDigitalType + + Private cIDField As DumpType + + Private cSDField As DumpType + + Private sCRField As DumpType + + Private oCRField As DumpType + + ''' + Public Property CID() As DumpType + Get + Return Me.cIDField + End Get + Set + Me.cIDField = value + End Set + End Property + + ''' + Public Property CSD() As DumpType + Get + Return Me.cSDField + End Get + Set + Me.cSDField = value + End Set + End Property + + ''' + Public Property SCR() As DumpType + Get + Return Me.sCRField + End Get + Set + Me.sCRField = value + End Set + End Property + + ''' + Public Property OCR() As DumpType + Get + Return Me.oCRField + End Get + Set + Me.oCRField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class ATAType + + Private identifyField As DumpType + + ''' + Public Property Identify() As DumpType + Get + Return Me.identifyField + End Get + Set + Me.identifyField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class TapeFileType + + Private imageField As ImageType + + Private sizeField As ULong + + Private sequenceField As ULong + + Private blockSizeField As ULong + + Private startBlockField As ULong + + Private endBlockField As ULong + + Private checksumsField() As ChecksumType + + ''' + Public Property Image() As ImageType + Get + Return Me.imageField + End Get + Set + Me.imageField = value + End Set + End Property + + ''' + Public Property Size() As ULong + Get + Return Me.sizeField + End Get + Set + Me.sizeField = value + End Set + End Property + + ''' + Public Property Sequence() As ULong + Get + Return Me.sequenceField + End Get + Set + Me.sequenceField = value + End Set + End Property + + ''' + Public Property BlockSize() As ULong + Get + Return Me.blockSizeField + End Get + Set + Me.blockSizeField = value + End Set + End Property + + ''' + Public Property StartBlock() As ULong + Get + Return Me.startBlockField + End Get + Set + Me.startBlockField = value + End Set + End Property + + ''' + Public Property EndBlock() As ULong + Get + Return Me.endBlockField + End Get + Set + Me.endBlockField = value + End Set + End Property + + ''' + _ + Public Property Checksums() As ChecksumType() + Get + Return Me.checksumsField + End Get + Set + Me.checksumsField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class TapePartitionType + + Private imageField As ImageType + + Private sizeField As ULong + + Private sequenceField As ULong + + Private startBlockField As ULong + + Private endBlockField As ULong + + Private checksumsField() As ChecksumType + + Private fileField() As TapeFileType + + ''' + Public Property Image() As ImageType + Get + Return Me.imageField + End Get + Set + Me.imageField = value + End Set + End Property + + ''' + Public Property Size() As ULong + Get + Return Me.sizeField + End Get + Set + Me.sizeField = value + End Set + End Property + + ''' + Public Property Sequence() As ULong + Get + Return Me.sequenceField + End Get + Set + Me.sequenceField = value + End Set + End Property + + ''' + Public Property StartBlock() As ULong + Get + Return Me.startBlockField + End Get + Set + Me.startBlockField = value + End Set + End Property + + ''' + Public Property EndBlock() As ULong + Get + Return Me.endBlockField + End Get + Set + Me.endBlockField = value + End Set + End Property + + ''' + _ + Public Property Checksums() As ChecksumType() + Get + Return Me.checksumsField + End Get + Set + Me.checksumsField = value + End Set + End Property + + ''' + _ + Public Property File() As TapeFileType() + Get + Return Me.fileField + End Get + Set + Me.fileField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class BlockSizeType + + Private startingBlockField As UInteger + + Private valueField As UInteger + + ''' + _ + Public Property startingBlock() As UInteger + Get + Return Me.startingBlockField + End Get + Set + Me.startingBlockField = value + End Set + End Property + + ''' + _ + Public Property Value() As UInteger + Get + Return Me.valueField + End Get + Set + Me.valueField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class BlockMediaType + + Private imageField As ImageType + + Private sizeField As ULong + + Private checksumsField() As ChecksumType + + Private contentChecksumsField() As ChecksumType + + Private sequenceField As SequenceType + + Private manufacturerField As String + + Private modelField As String + + Private serialField As String + + Private firmwareField As String + + Private interfaceField As String + + Private partNumberField As String + + Private serialNumberField As String + + Private physicalBlockSizeField As UInteger + + Private logicalBlockSizeField As UInteger + + Private logicalBlocksField As ULong + + Private variableBlockSizeField() As BlockSizeType + + Private tapeInformationField() As TapePartitionType + + Private scansField As ScansType + + Private aTAField As ATAType + + Private pCIField As PCIType + + Private pCMCIAField As PCMCIAType + + Private secureDigitalField As SecureDigitalType + + Private multiMediaCardField As MultiMediaCardType + + Private sCSIField As SCSIType + + Private uSBField As USBType + + Private mAMField As DumpType + + Private headsField As UShort + + Private headsFieldSpecified As Boolean + + Private cylindersField As UInteger + + Private cylindersFieldSpecified As Boolean + + Private sectorsPerTrackField As ULong + + Private sectorsPerTrackFieldSpecified As Boolean + + Private trackField() As BlockTrackType + + Private copyProtectionField As String + + Private dimensionsField As DimensionsType + + Private fileSystemInformationField() As PartitionType + + Private dumpHardwareArrayField() As DumpHardwareType + + Private diskTypeField As String + + Private diskSubTypeField As String + + ''' + Public Property Image() As ImageType + Get + Return Me.imageField + End Get + Set + Me.imageField = value + End Set + End Property + + ''' + Public Property Size() As ULong + Get + Return Me.sizeField + End Get + Set + Me.sizeField = value + End Set + End Property + + ''' + _ + Public Property Checksums() As ChecksumType() + Get + Return Me.checksumsField + End Get + Set + Me.checksumsField = value + End Set + End Property + + ''' + _ + Public Property ContentChecksums() As ChecksumType() + Get + Return Me.contentChecksumsField + End Get + Set + Me.contentChecksumsField = value + End Set + End Property + + ''' + Public Property Sequence() As SequenceType + Get + Return Me.sequenceField + End Get + Set + Me.sequenceField = value + End Set + End Property + + ''' + Public Property Manufacturer() As String + Get + Return Me.manufacturerField + End Get + Set + Me.manufacturerField = value + End Set + End Property + + ''' + Public Property Model() As String + Get + Return Me.modelField + End Get + Set + Me.modelField = value + End Set + End Property + + ''' + Public Property Serial() As String + Get + Return Me.serialField + End Get + Set + Me.serialField = value + End Set + End Property + + ''' + Public Property Firmware() As String + Get + Return Me.firmwareField + End Get + Set + Me.firmwareField = value + End Set + End Property + + ''' + Public Property [Interface]() As String + Get + Return Me.interfaceField + End Get + Set + Me.interfaceField = value + End Set + End Property + + ''' + Public Property PartNumber() As String + Get + Return Me.partNumberField + End Get + Set + Me.partNumberField = value + End Set + End Property + + ''' + Public Property SerialNumber() As String + Get + Return Me.serialNumberField + End Get + Set + Me.serialNumberField = value + End Set + End Property + + ''' + Public Property PhysicalBlockSize() As UInteger + Get + Return Me.physicalBlockSizeField + End Get + Set + Me.physicalBlockSizeField = value + End Set + End Property + + ''' + Public Property LogicalBlockSize() As UInteger + Get + Return Me.logicalBlockSizeField + End Get + Set + Me.logicalBlockSizeField = value + End Set + End Property + + ''' + Public Property LogicalBlocks() As ULong + Get + Return Me.logicalBlocksField + End Get + Set + Me.logicalBlocksField = value + End Set + End Property + + ''' + _ + Public Property VariableBlockSize() As BlockSizeType() + Get + Return Me.variableBlockSizeField + End Get + Set + Me.variableBlockSizeField = value + End Set + End Property + + ''' + _ + Public Property TapeInformation() As TapePartitionType() + Get + Return Me.tapeInformationField + End Get + Set + Me.tapeInformationField = value + End Set + End Property + + ''' + Public Property Scans() As ScansType + Get + Return Me.scansField + End Get + Set + Me.scansField = value + End Set + End Property + + ''' + Public Property ATA() As ATAType + Get + Return Me.aTAField + End Get + Set + Me.aTAField = value + End Set + End Property + + ''' + Public Property PCI() As PCIType + Get + Return Me.pCIField + End Get + Set + Me.pCIField = value + End Set + End Property + + ''' + Public Property PCMCIA() As PCMCIAType + Get + Return Me.pCMCIAField + End Get + Set + Me.pCMCIAField = value + End Set + End Property + + ''' + Public Property SecureDigital() As SecureDigitalType + Get + Return Me.secureDigitalField + End Get + Set + Me.secureDigitalField = value + End Set + End Property + + ''' + Public Property MultiMediaCard() As MultiMediaCardType + Get + Return Me.multiMediaCardField + End Get + Set + Me.multiMediaCardField = value + End Set + End Property + + ''' + Public Property SCSI() As SCSIType + Get + Return Me.sCSIField + End Get + Set + Me.sCSIField = value + End Set + End Property + + ''' + Public Property USB() As USBType + Get + Return Me.uSBField + End Get + Set + Me.uSBField = value + End Set + End Property + + ''' + Public Property MAM() As DumpType + Get + Return Me.mAMField + End Get + Set + Me.mAMField = value + End Set + End Property + + ''' + Public Property Heads() As UShort + Get + Return Me.headsField + End Get + Set + Me.headsField = value + End Set + End Property + + ''' + _ + Public Property HeadsSpecified() As Boolean + Get + Return Me.headsFieldSpecified + End Get + Set + Me.headsFieldSpecified = value + End Set + End Property + + ''' + Public Property Cylinders() As UInteger + Get + Return Me.cylindersField + End Get + Set + Me.cylindersField = value + End Set + End Property + + ''' + _ + Public Property CylindersSpecified() As Boolean + Get + Return Me.cylindersFieldSpecified + End Get + Set + Me.cylindersFieldSpecified = value + End Set + End Property + + ''' + Public Property SectorsPerTrack() As ULong + Get + Return Me.sectorsPerTrackField + End Get + Set + Me.sectorsPerTrackField = value + End Set + End Property + + ''' + _ + Public Property SectorsPerTrackSpecified() As Boolean + Get + Return Me.sectorsPerTrackFieldSpecified + End Get + Set + Me.sectorsPerTrackFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property Track() As BlockTrackType() + Get + Return Me.trackField + End Get + Set + Me.trackField = value + End Set + End Property + + ''' + Public Property CopyProtection() As String + Get + Return Me.copyProtectionField + End Get + Set + Me.copyProtectionField = value + End Set + End Property + + ''' + Public Property Dimensions() As DimensionsType + Get + Return Me.dimensionsField + End Get + Set + Me.dimensionsField = value + End Set + End Property + + ''' + _ + Public Property FileSystemInformation() As PartitionType() + Get + Return Me.fileSystemInformationField + End Get + Set + Me.fileSystemInformationField = value + End Set + End Property + + ''' + _ + Public Property DumpHardwareArray() As DumpHardwareType() + Get + Return Me.dumpHardwareArrayField + End Get + Set + Me.dumpHardwareArrayField = value + End Set + End Property + + ''' + Public Property DiskType() As String + Get + Return Me.diskTypeField + End Get + Set + Me.diskTypeField = value + End Set + End Property + + ''' + Public Property DiskSubType() As String + Get + Return Me.diskSubTypeField + End Get + Set + Me.diskSubTypeField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class PCIType + + Private vendorIDField As UShort + + Private deviceIDField As UShort + + Private configurationField As DumpType + + Private expansionROMField As LinearMediaType + + ''' + Public Property VendorID() As UShort + Get + Return Me.vendorIDField + End Get + Set + Me.vendorIDField = value + End Set + End Property + + ''' + Public Property DeviceID() As UShort + Get + Return Me.deviceIDField + End Get + Set + Me.deviceIDField = value + End Set + End Property + + ''' + Public Property Configuration() As DumpType + Get + Return Me.configurationField + End Get + Set + Me.configurationField = value + End Set + End Property + + ''' + Public Property ExpansionROM() As LinearMediaType + Get + Return Me.expansionROMField + End Get + Set + Me.expansionROMField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class LinearMediaType + + Private imageField As ImageType + + Private sizeField As ULong + + Private imageChecksumsField() As ChecksumType + + Private checksumsField() As ChecksumType + + Private partNumberField As String + + Private serialNumberField As String + + Private titleField As String + + Private sequenceField As UInteger + + Private sequenceFieldSpecified As Boolean + + Private imageInterleaveField As UInteger + + Private imageInterleaveFieldSpecified As Boolean + + Private interleaveField As UInteger + + Private interleaveFieldSpecified As Boolean + + Private manufacturerField As String + + Private modelField As String + + Private packageField As String + + Private interfaceField As String + + Private dimensionsField As DimensionsType + + Private scansField As ScansType + + Private dumpHardwareArrayField() As DumpHardwareType + + Private pCMCIAField As PCMCIAType + + Private copyProtectionField As String + + ''' + Public Property Image() As ImageType + Get + Return Me.imageField + End Get + Set + Me.imageField = value + End Set + End Property + + ''' + Public Property Size() As ULong + Get + Return Me.sizeField + End Get + Set + Me.sizeField = value + End Set + End Property + + ''' + _ + Public Property ImageChecksums() As ChecksumType() + Get + Return Me.imageChecksumsField + End Get + Set + Me.imageChecksumsField = value + End Set + End Property + + ''' + _ + Public Property Checksums() As ChecksumType() + Get + Return Me.checksumsField + End Get + Set + Me.checksumsField = value + End Set + End Property + + ''' + Public Property PartNumber() As String + Get + Return Me.partNumberField + End Get + Set + Me.partNumberField = value + End Set + End Property + + ''' + Public Property SerialNumber() As String + Get + Return Me.serialNumberField + End Get + Set + Me.serialNumberField = value + End Set + End Property + + ''' + Public Property Title() As String + Get + Return Me.titleField + End Get + Set + Me.titleField = value + End Set + End Property + + ''' + Public Property Sequence() As UInteger + Get + Return Me.sequenceField + End Get + Set + Me.sequenceField = value + End Set + End Property + + ''' + _ + Public Property SequenceSpecified() As Boolean + Get + Return Me.sequenceFieldSpecified + End Get + Set + Me.sequenceFieldSpecified = value + End Set + End Property + + ''' + Public Property ImageInterleave() As UInteger + Get + Return Me.imageInterleaveField + End Get + Set + Me.imageInterleaveField = value + End Set + End Property + + ''' + _ + Public Property ImageInterleaveSpecified() As Boolean + Get + Return Me.imageInterleaveFieldSpecified + End Get + Set + Me.imageInterleaveFieldSpecified = value + End Set + End Property + + ''' + Public Property Interleave() As UInteger + Get + Return Me.interleaveField + End Get + Set + Me.interleaveField = value + End Set + End Property + + ''' + _ + Public Property InterleaveSpecified() As Boolean + Get + Return Me.interleaveFieldSpecified + End Get + Set + Me.interleaveFieldSpecified = value + End Set + End Property + + ''' + Public Property Manufacturer() As String + Get + Return Me.manufacturerField + End Get + Set + Me.manufacturerField = value + End Set + End Property + + ''' + Public Property Model() As String + Get + Return Me.modelField + End Get + Set + Me.modelField = value + End Set + End Property + + ''' + Public Property Package() As String + Get + Return Me.packageField + End Get + Set + Me.packageField = value + End Set + End Property + + ''' + Public Property [Interface]() As String + Get + Return Me.interfaceField + End Get + Set + Me.interfaceField = value + End Set + End Property + + ''' + Public Property Dimensions() As DimensionsType + Get + Return Me.dimensionsField + End Get + Set + Me.dimensionsField = value + End Set + End Property + + ''' + Public Property Scans() As ScansType + Get + Return Me.scansField + End Get + Set + Me.scansField = value + End Set + End Property + + ''' + _ + Public Property DumpHardwareArray() As DumpHardwareType() + Get + Return Me.dumpHardwareArrayField + End Get + Set + Me.dumpHardwareArrayField = value + End Set + End Property + + ''' + Public Property PCMCIA() As PCMCIAType + Get + Return Me.pCMCIAField + End Get + Set + Me.pCMCIAField = value + End Set + End Property + + ''' + Public Property CopyProtection() As String + Get + Return Me.copyProtectionField + End Get + Set + Me.copyProtectionField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class PCMCIAType + + Private cISField As DumpType + + Private complianceField As String + + Private manufacturerCodeField As UShort + + Private manufacturerCodeFieldSpecified As Boolean + + Private cardCodeField As UShort + + Private cardCodeFieldSpecified As Boolean + + Private manufacturerField As String + + Private productNameField As String + + Private additionalInformationField() As String + + ''' + Public Property CIS() As DumpType + Get + Return Me.cISField + End Get + Set + Me.cISField = value + End Set + End Property + + ''' + Public Property Compliance() As String + Get + Return Me.complianceField + End Get + Set + Me.complianceField = value + End Set + End Property + + ''' + Public Property ManufacturerCode() As UShort + Get + Return Me.manufacturerCodeField + End Get + Set + Me.manufacturerCodeField = value + End Set + End Property + + ''' + _ + Public Property ManufacturerCodeSpecified() As Boolean + Get + Return Me.manufacturerCodeFieldSpecified + End Get + Set + Me.manufacturerCodeFieldSpecified = value + End Set + End Property + + ''' + Public Property CardCode() As UShort + Get + Return Me.cardCodeField + End Get + Set + Me.cardCodeField = value + End Set + End Property + + ''' + _ + Public Property CardCodeSpecified() As Boolean + Get + Return Me.cardCodeFieldSpecified + End Get + Set + Me.cardCodeFieldSpecified = value + End Set + End Property + + ''' + Public Property Manufacturer() As String + Get + Return Me.manufacturerField + End Get + Set + Me.manufacturerField = value + End Set + End Property + + ''' + Public Property ProductName() As String + Get + Return Me.productNameField + End Get + Set + Me.productNameField = value + End Set + End Property + + ''' + _ + Public Property AdditionalInformation() As String() + Get + Return Me.additionalInformationField + End Get + Set + Me.additionalInformationField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class PartitionType + + Private sequenceField As UInteger + + Private nameField As String + + Private typeField As String + + Private startSectorField As ULong + + Private endSectorField As ULong + + Private descriptionField As String + + Private fileSystemsField() As FileSystemType + + ''' + Public Property Sequence() As UInteger + Get + Return Me.sequenceField + End Get + Set + Me.sequenceField = value + End Set + End Property + + ''' + Public Property Name() As String + Get + Return Me.nameField + End Get + Set + Me.nameField = value + End Set + End Property + + ''' + Public Property Type() As String + Get + Return Me.typeField + End Get + Set + Me.typeField = value + End Set + End Property + + ''' + Public Property StartSector() As ULong + Get + Return Me.startSectorField + End Get + Set + Me.startSectorField = value + End Set + End Property + + ''' + Public Property EndSector() As ULong + Get + Return Me.endSectorField + End Get + Set + Me.endSectorField = value + End Set + End Property + + ''' + Public Property Description() As String + Get + Return Me.descriptionField + End Get + Set + Me.descriptionField = value + End Set + End Property + + ''' + _ + Public Property FileSystems() As FileSystemType() + Get + Return Me.fileSystemsField + End Get + Set + Me.fileSystemsField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class FileSystemType + + Private typeField As String + + Private creationDateField As Date + + Private creationDateFieldSpecified As Boolean + + Private modificationDateField As Date + + Private modificationDateFieldSpecified As Boolean + + Private backupDateField As Date + + Private backupDateFieldSpecified As Boolean + + Private clusterSizeField As UInteger + + Private clustersField As ULong + + Private filesField As ULong + + Private filesFieldSpecified As Boolean + + Private bootableField As Boolean + + Private volumeSerialField As String + + Private volumeNameField As String + + Private freeClustersField As ULong + + Private freeClustersFieldSpecified As Boolean + + Private dirtyField As Boolean + + Private expirationDateField As Date + + Private expirationDateFieldSpecified As Boolean + + Private effectiveDateField As Date + + Private effectiveDateFieldSpecified As Boolean + + Private systemIdentifierField As String + + Private volumeSetIdentifierField As String + + Private publisherIdentifierField As String + + Private dataPreparerIdentifierField As String + + Private applicationIdentifierField As String + + Private contentsField As FilesystemContentsType + + ''' + Public Property Type() As String + Get + Return Me.typeField + End Get + Set + Me.typeField = value + End Set + End Property + + ''' + Public Property CreationDate() As Date + Get + Return Me.creationDateField + End Get + Set + Me.creationDateField = value + End Set + End Property + + ''' + _ + Public Property CreationDateSpecified() As Boolean + Get + Return Me.creationDateFieldSpecified + End Get + Set + Me.creationDateFieldSpecified = value + End Set + End Property + + ''' + Public Property ModificationDate() As Date + Get + Return Me.modificationDateField + End Get + Set + Me.modificationDateField = value + End Set + End Property + + ''' + _ + Public Property ModificationDateSpecified() As Boolean + Get + Return Me.modificationDateFieldSpecified + End Get + Set + Me.modificationDateFieldSpecified = value + End Set + End Property + + ''' + Public Property BackupDate() As Date + Get + Return Me.backupDateField + End Get + Set + Me.backupDateField = value + End Set + End Property + + ''' + _ + Public Property BackupDateSpecified() As Boolean + Get + Return Me.backupDateFieldSpecified + End Get + Set + Me.backupDateFieldSpecified = value + End Set + End Property + + ''' + Public Property ClusterSize() As UInteger + Get + Return Me.clusterSizeField + End Get + Set + Me.clusterSizeField = value + End Set + End Property + + ''' + Public Property Clusters() As ULong + Get + Return Me.clustersField + End Get + Set + Me.clustersField = value + End Set + End Property + + ''' + Public Property Files() As ULong + Get + Return Me.filesField + End Get + Set + Me.filesField = value + End Set + End Property + + ''' + _ + Public Property FilesSpecified() As Boolean + Get + Return Me.filesFieldSpecified + End Get + Set + Me.filesFieldSpecified = value + End Set + End Property + + ''' + Public Property Bootable() As Boolean + Get + Return Me.bootableField + End Get + Set + Me.bootableField = value + End Set + End Property + + ''' + Public Property VolumeSerial() As String + Get + Return Me.volumeSerialField + End Get + Set + Me.volumeSerialField = value + End Set + End Property + + ''' + Public Property VolumeName() As String + Get + Return Me.volumeNameField + End Get + Set + Me.volumeNameField = value + End Set + End Property + + ''' + Public Property FreeClusters() As ULong + Get + Return Me.freeClustersField + End Get + Set + Me.freeClustersField = value + End Set + End Property + + ''' + _ + Public Property FreeClustersSpecified() As Boolean + Get + Return Me.freeClustersFieldSpecified + End Get + Set + Me.freeClustersFieldSpecified = value + End Set + End Property + + ''' + Public Property Dirty() As Boolean + Get + Return Me.dirtyField + End Get + Set + Me.dirtyField = value + End Set + End Property + + ''' + Public Property ExpirationDate() As Date + Get + Return Me.expirationDateField + End Get + Set + Me.expirationDateField = value + End Set + End Property + + ''' + _ + Public Property ExpirationDateSpecified() As Boolean + Get + Return Me.expirationDateFieldSpecified + End Get + Set + Me.expirationDateFieldSpecified = value + End Set + End Property + + ''' + Public Property EffectiveDate() As Date + Get + Return Me.effectiveDateField + End Get + Set + Me.effectiveDateField = value + End Set + End Property + + ''' + _ + Public Property EffectiveDateSpecified() As Boolean + Get + Return Me.effectiveDateFieldSpecified + End Get + Set + Me.effectiveDateFieldSpecified = value + End Set + End Property + + ''' + Public Property SystemIdentifier() As String + Get + Return Me.systemIdentifierField + End Get + Set + Me.systemIdentifierField = value + End Set + End Property + + ''' + Public Property VolumeSetIdentifier() As String + Get + Return Me.volumeSetIdentifierField + End Get + Set + Me.volumeSetIdentifierField = value + End Set + End Property + + ''' + Public Property PublisherIdentifier() As String + Get + Return Me.publisherIdentifierField + End Get + Set + Me.publisherIdentifierField = value + End Set + End Property + + ''' + Public Property DataPreparerIdentifier() As String + Get + Return Me.dataPreparerIdentifierField + End Get + Set + Me.dataPreparerIdentifierField = value + End Set + End Property + + ''' + Public Property ApplicationIdentifier() As String + Get + Return Me.applicationIdentifierField + End Get + Set + Me.applicationIdentifierField = value + End Set + End Property + + ''' + Public Property Contents() As FilesystemContentsType + Get + Return Me.contentsField + End Get + Set + Me.contentsField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class FilesystemContentsType + + Private fileField() As ContentsFileType + + Private directoryField() As DirectoryType + + Private namespaceField As String + + ''' + _ + Public Property File() As ContentsFileType() + Get + Return Me.fileField + End Get + Set + Me.fileField = value + End Set + End Property + + ''' + _ + Public Property Directory() As DirectoryType() + Get + Return Me.directoryField + End Get + Set + Me.directoryField = value + End Set + End Property + + ''' + _ + Public Property [namespace]() As String + Get + Return Me.namespaceField + End Get + Set + Me.namespaceField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class ContentsFileType + + Private checksumsField() As ChecksumType + + Private extendedAttributesField() As ExtendedAttributeType + + Private nameField As String + + Private creationTimeField As Date + + Private creationTimeFieldSpecified As Boolean + + Private accessTimeField As Date + + Private accessTimeFieldSpecified As Boolean + + Private statusChangeTimeField As Date + + Private statusChangeTimeFieldSpecified As Boolean + + Private backupTimeField As Date + + Private backupTimeFieldSpecified As Boolean + + Private lastWriteTimeField As Date + + Private lastWriteTimeFieldSpecified As Boolean + + Private attributesField As ULong + + Private posixModeField As UInteger + + Private posixModeFieldSpecified As Boolean + + Private deviceNumberField As ULong + + Private deviceNumberFieldSpecified As Boolean + + Private posixGroupIdField As ULong + + Private posixGroupIdFieldSpecified As Boolean + + Private inodeField As ULong + + Private linksField As ULong + + Private posixUserIdField As ULong + + Private posixUserIdFieldSpecified As Boolean + + Private lengthField As ULong + + ''' + _ + Public Property Checksums() As ChecksumType() + Get + Return Me.checksumsField + End Get + Set + Me.checksumsField = value + End Set + End Property + + ''' + _ + Public Property ExtendedAttributes() As ExtendedAttributeType() + Get + Return Me.extendedAttributesField + End Get + Set + Me.extendedAttributesField = value + End Set + End Property + + ''' + _ + Public Property name() As String + Get + Return Me.nameField + End Get + Set + Me.nameField = value + End Set + End Property + + ''' + _ + Public Property creationTime() As Date + Get + Return Me.creationTimeField + End Get + Set + Me.creationTimeField = value + End Set + End Property + + ''' + _ + Public Property creationTimeSpecified() As Boolean + Get + Return Me.creationTimeFieldSpecified + End Get + Set + Me.creationTimeFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property accessTime() As Date + Get + Return Me.accessTimeField + End Get + Set + Me.accessTimeField = value + End Set + End Property + + ''' + _ + Public Property accessTimeSpecified() As Boolean + Get + Return Me.accessTimeFieldSpecified + End Get + Set + Me.accessTimeFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property statusChangeTime() As Date + Get + Return Me.statusChangeTimeField + End Get + Set + Me.statusChangeTimeField = value + End Set + End Property + + ''' + _ + Public Property statusChangeTimeSpecified() As Boolean + Get + Return Me.statusChangeTimeFieldSpecified + End Get + Set + Me.statusChangeTimeFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property backupTime() As Date + Get + Return Me.backupTimeField + End Get + Set + Me.backupTimeField = value + End Set + End Property + + ''' + _ + Public Property backupTimeSpecified() As Boolean + Get + Return Me.backupTimeFieldSpecified + End Get + Set + Me.backupTimeFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property lastWriteTime() As Date + Get + Return Me.lastWriteTimeField + End Get + Set + Me.lastWriteTimeField = value + End Set + End Property + + ''' + _ + Public Property lastWriteTimeSpecified() As Boolean + Get + Return Me.lastWriteTimeFieldSpecified + End Get + Set + Me.lastWriteTimeFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property attributes() As ULong + Get + Return Me.attributesField + End Get + Set + Me.attributesField = value + End Set + End Property + + ''' + _ + Public Property posixMode() As UInteger + Get + Return Me.posixModeField + End Get + Set + Me.posixModeField = value + End Set + End Property + + ''' + _ + Public Property posixModeSpecified() As Boolean + Get + Return Me.posixModeFieldSpecified + End Get + Set + Me.posixModeFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property deviceNumber() As ULong + Get + Return Me.deviceNumberField + End Get + Set + Me.deviceNumberField = value + End Set + End Property + + ''' + _ + Public Property deviceNumberSpecified() As Boolean + Get + Return Me.deviceNumberFieldSpecified + End Get + Set + Me.deviceNumberFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property posixGroupId() As ULong + Get + Return Me.posixGroupIdField + End Get + Set + Me.posixGroupIdField = value + End Set + End Property + + ''' + _ + Public Property posixGroupIdSpecified() As Boolean + Get + Return Me.posixGroupIdFieldSpecified + End Get + Set + Me.posixGroupIdFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property inode() As ULong + Get + Return Me.inodeField + End Get + Set + Me.inodeField = value + End Set + End Property + + ''' + _ + Public Property links() As ULong + Get + Return Me.linksField + End Get + Set + Me.linksField = value + End Set + End Property + + ''' + _ + Public Property posixUserId() As ULong + Get + Return Me.posixUserIdField + End Get + Set + Me.posixUserIdField = value + End Set + End Property + + ''' + _ + Public Property posixUserIdSpecified() As Boolean + Get + Return Me.posixUserIdFieldSpecified + End Get + Set + Me.posixUserIdFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property length() As ULong + Get + Return Me.lengthField + End Get + Set + Me.lengthField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class ExtendedAttributeType + + Private checksumsField() As ChecksumType + + Private nameField As String + + Private lengthField As ULong + + ''' + _ + Public Property Checksums() As ChecksumType() + Get + Return Me.checksumsField + End Get + Set + Me.checksumsField = value + End Set + End Property + + ''' + _ + Public Property name() As String + Get + Return Me.nameField + End Get + Set + Me.nameField = value + End Set + End Property + + ''' + _ + Public Property length() As ULong + Get + Return Me.lengthField + End Get + Set + Me.lengthField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class DirectoryType + + Private fileField() As ContentsFileType + + Private directoryField() As DirectoryType + + Private nameField As String + + Private creationTimeField As Date + + Private creationTimeFieldSpecified As Boolean + + Private accessTimeField As Date + + Private accessTimeFieldSpecified As Boolean + + Private statusChangeTimeField As Date + + Private statusChangeTimeFieldSpecified As Boolean + + Private backupTimeField As Date + + Private backupTimeFieldSpecified As Boolean + + Private lastWriteTimeField As Date + + Private lastWriteTimeFieldSpecified As Boolean + + Private attributesField As ULong + + Private posixModeField As UInteger + + Private posixModeFieldSpecified As Boolean + + Private deviceNumberField As ULong + + Private deviceNumberFieldSpecified As Boolean + + Private posixGroupIdField As ULong + + Private posixGroupIdFieldSpecified As Boolean + + Private inodeField As ULong + + Private inodeFieldSpecified As Boolean + + Private linksField As ULong + + Private linksFieldSpecified As Boolean + + Private posixUserIdField As ULong + + Private posixUserIdFieldSpecified As Boolean + + ''' + _ + Public Property File() As ContentsFileType() + Get + Return Me.fileField + End Get + Set + Me.fileField = value + End Set + End Property + + ''' + _ + Public Property Directory() As DirectoryType() + Get + Return Me.directoryField + End Get + Set + Me.directoryField = value + End Set + End Property + + ''' + _ + Public Property name() As String + Get + Return Me.nameField + End Get + Set + Me.nameField = value + End Set + End Property + + ''' + _ + Public Property creationTime() As Date + Get + Return Me.creationTimeField + End Get + Set + Me.creationTimeField = value + End Set + End Property + + ''' + _ + Public Property creationTimeSpecified() As Boolean + Get + Return Me.creationTimeFieldSpecified + End Get + Set + Me.creationTimeFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property accessTime() As Date + Get + Return Me.accessTimeField + End Get + Set + Me.accessTimeField = value + End Set + End Property + + ''' + _ + Public Property accessTimeSpecified() As Boolean + Get + Return Me.accessTimeFieldSpecified + End Get + Set + Me.accessTimeFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property statusChangeTime() As Date + Get + Return Me.statusChangeTimeField + End Get + Set + Me.statusChangeTimeField = value + End Set + End Property + + ''' + _ + Public Property statusChangeTimeSpecified() As Boolean + Get + Return Me.statusChangeTimeFieldSpecified + End Get + Set + Me.statusChangeTimeFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property backupTime() As Date + Get + Return Me.backupTimeField + End Get + Set + Me.backupTimeField = value + End Set + End Property + + ''' + _ + Public Property backupTimeSpecified() As Boolean + Get + Return Me.backupTimeFieldSpecified + End Get + Set + Me.backupTimeFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property lastWriteTime() As Date + Get + Return Me.lastWriteTimeField + End Get + Set + Me.lastWriteTimeField = value + End Set + End Property + + ''' + _ + Public Property lastWriteTimeSpecified() As Boolean + Get + Return Me.lastWriteTimeFieldSpecified + End Get + Set + Me.lastWriteTimeFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property attributes() As ULong + Get + Return Me.attributesField + End Get + Set + Me.attributesField = value + End Set + End Property + + ''' + _ + Public Property posixMode() As UInteger + Get + Return Me.posixModeField + End Get + Set + Me.posixModeField = value + End Set + End Property + + ''' + _ + Public Property posixModeSpecified() As Boolean + Get + Return Me.posixModeFieldSpecified + End Get + Set + Me.posixModeFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property deviceNumber() As ULong + Get + Return Me.deviceNumberField + End Get + Set + Me.deviceNumberField = value + End Set + End Property + + ''' + _ + Public Property deviceNumberSpecified() As Boolean + Get + Return Me.deviceNumberFieldSpecified + End Get + Set + Me.deviceNumberFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property posixGroupId() As ULong + Get + Return Me.posixGroupIdField + End Get + Set + Me.posixGroupIdField = value + End Set + End Property + + ''' + _ + Public Property posixGroupIdSpecified() As Boolean + Get + Return Me.posixGroupIdFieldSpecified + End Get + Set + Me.posixGroupIdFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property inode() As ULong + Get + Return Me.inodeField + End Get + Set + Me.inodeField = value + End Set + End Property + + ''' + _ + Public Property inodeSpecified() As Boolean + Get + Return Me.inodeFieldSpecified + End Get + Set + Me.inodeFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property links() As ULong + Get + Return Me.linksField + End Get + Set + Me.linksField = value + End Set + End Property + + ''' + _ + Public Property linksSpecified() As Boolean + Get + Return Me.linksFieldSpecified + End Get + Set + Me.linksFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property posixUserId() As ULong + Get + Return Me.posixUserIdField + End Get + Set + Me.posixUserIdField = value + End Set + End Property + + ''' + _ + Public Property posixUserIdSpecified() As Boolean + Get + Return Me.posixUserIdFieldSpecified + End Get + Set + Me.posixUserIdFieldSpecified = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class CoordinatesType + + Private latitudeField As Double + + Private longitudeField As Double + + ''' + Public Property Latitude() As Double + Get + Return Me.latitudeField + End Get + Set + Me.latitudeField = value + End Set + End Property + + ''' + Public Property Longitude() As Double + Get + Return Me.longitudeField + End Get + Set + Me.longitudeField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class RecordingType + + Private broadcasterField As String + + Private broadcastPlatformField As String + + Private sourceFormatField As RecordingTypeSourceFormat + + Private timestampField As Date + + Private softwareField() As SoftwareType + + Private coordinatesField As CoordinatesType + + ''' + Public Property Broadcaster() As String + Get + Return Me.broadcasterField + End Get + Set + Me.broadcasterField = value + End Set + End Property + + ''' + Public Property BroadcastPlatform() As String + Get + Return Me.broadcastPlatformField + End Get + Set + Me.broadcastPlatformField = value + End Set + End Property + + ''' + Public Property SourceFormat() As RecordingTypeSourceFormat + Get + Return Me.sourceFormatField + End Get + Set + Me.sourceFormatField = value + End Set + End Property + + ''' + Public Property Timestamp() As Date + Get + Return Me.timestampField + End Get + Set + Me.timestampField = value + End Set + End Property + + ''' + _ + Public Property Software() As SoftwareType() + Get + Return Me.softwareField + End Get + Set + Me.softwareField = value + End Set + End Property + + ''' + Public Property Coordinates() As CoordinatesType + Get + Return Me.coordinatesField + End Get + Set + Me.coordinatesField = value + End Set + End Property + End Class + + ''' + _ + Public Enum RecordingTypeSourceFormat + + ''' + _ + ITUA + + ''' + _ + ITUB + + ''' + _ + ITUC + + ''' + _ + ITUD + + ''' + _ + ITUE + + ''' + _ + ITUF + + ''' + _ + ITUG + + ''' + _ + ITUH + + ''' + _ + ITUI + + ''' + _ + ITUJ + + ''' + _ + ITUK + + ''' + _ + ITUL + + ''' + _ + ITUM + + ''' + _ + ITUN + + ''' + _ + PALB + + ''' + _ + SECAMB + + ''' + _ + PALD + + ''' + _ + SECAMD + + ''' + _ + PALG + + ''' + _ + SECAMG + + ''' + _ + PALH + + ''' + _ + PALI + + ''' + _ + PALK + + ''' + _ + SECAMK + + ''' + _ + NTSCM + + ''' + _ + PALN + + ''' + _ + PALM + + ''' + _ + SECAMM + + ''' + MUSE + + ''' + PALplus + + ''' + FM + + ''' + AM + + ''' + COFDM + + ''' + _ + CAMD + + ''' + DAB + + ''' + _ + DAB1 + + ''' + DRM + + ''' + _ + DRM1 + + ''' + FMeXtra + + ''' + ATSC + + ''' + ATSC2 + + ''' + ATSC3 + + ''' + _ + ATSCMH + + ''' + _ + DVBT + + ''' + _ + DVBT2 + + ''' + _ + DVBS + + ''' + _ + DVBS2 + + ''' + _ + DVBS2X + + ''' + _ + DVBC + + ''' + _ + DVBC2 + + ''' + _ + DVBH + + ''' + _ + DVBNGH + + ''' + _ + DVBSH + + ''' + _ + ISDBT + + ''' + _ + ISDBTb + + ''' + _ + ISDBS + + ''' + _ + ISDBC + + ''' + _ + Item1seg + + ''' + DTMB + + ''' + CCMB + + ''' + _ + TDMB + + ''' + _ + SDMB + + ''' + IPTV + + ''' + _ + DVBMT + + ''' + _ + DVBMC + + ''' + _ + DVBMS + + ''' + ADR + + ''' + SDR + End Enum + + ''' + _ + Partial Public Class SubtitleTracksType + + Private languagesField() As LanguagesTypeLanguage + + Private trackNumberField As UInteger + + Private codecField As String + + ''' + _ + Public Property Languages() As LanguagesTypeLanguage() + Get + Return Me.languagesField + End Get + Set + Me.languagesField = value + End Set + End Property + + ''' + _ + Public Property TrackNumber() As UInteger + Get + Return Me.trackNumberField + End Get + Set + Me.trackNumberField = value + End Set + End Property + + ''' + _ + Public Property Codec() As String + Get + Return Me.codecField + End Get + Set + Me.codecField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class VideoTracksType + + Private languagesField() As LanguagesTypeLanguage + + Private trackNumberField As UInteger + + Private codecField As String + + Private horizontalField As UInteger + + Private verticalField As UInteger + + Private meanBitrateField As Long + + Private threeDField As Boolean + + ''' + _ + Public Property Languages() As LanguagesTypeLanguage() + Get + Return Me.languagesField + End Get + Set + Me.languagesField = value + End Set + End Property + + ''' + _ + Public Property TrackNumber() As UInteger + Get + Return Me.trackNumberField + End Get + Set + Me.trackNumberField = value + End Set + End Property + + ''' + _ + Public Property Codec() As String + Get + Return Me.codecField + End Get + Set + Me.codecField = value + End Set + End Property + + ''' + _ + Public Property Horizontal() As UInteger + Get + Return Me.horizontalField + End Get + Set + Me.horizontalField = value + End Set + End Property + + ''' + _ + Public Property Vertical() As UInteger + Get + Return Me.verticalField + End Get + Set + Me.verticalField = value + End Set + End Property + + ''' + _ + Public Property MeanBitrate() As Long + Get + Return Me.meanBitrateField + End Get + Set + Me.meanBitrateField = value + End Set + End Property + + ''' + _ + Public Property ThreeD() As Boolean + Get + Return Me.threeDField + End Get + Set + Me.threeDField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class AudioTracksType + + Private languagesField() As LanguagesTypeLanguage + + Private trackNumberField As UInteger + + Private accoustIDField As String + + Private codecField As String + + Private channelsField As UInteger + + Private sampleRateField As Double + + Private meanBitrateField As Long + + ''' + _ + Public Property Languages() As LanguagesTypeLanguage() + Get + Return Me.languagesField + End Get + Set + Me.languagesField = value + End Set + End Property + + ''' + _ + Public Property TrackNumber() As UInteger + Get + Return Me.trackNumberField + End Get + Set + Me.trackNumberField = value + End Set + End Property + + ''' + _ + Public Property AccoustID() As String + Get + Return Me.accoustIDField + End Get + Set + Me.accoustIDField = value + End Set + End Property + + ''' + _ + Public Property Codec() As String + Get + Return Me.codecField + End Get + Set + Me.codecField = value + End Set + End Property + + ''' + _ + Public Property Channels() As UInteger + Get + Return Me.channelsField + End Get + Set + Me.channelsField = value + End Set + End Property + + ''' + _ + Public Property SampleRate() As Double + Get + Return Me.sampleRateField + End Get + Set + Me.sampleRateField = value + End Set + End Property + + ''' + _ + Public Property MeanBitrate() As Long + Get + Return Me.meanBitrateField + End Get + Set + Me.meanBitrateField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class AdvertisementType + + Private manufacturerField As String + + Private productField As String + + Private fileField As FileType + + Private fileSizeField As ULong + + Private framesField As ULong + + Private framesFieldSpecified As Boolean + + Private durationField As Double + + Private meanFrameRateField As Single + + Private meanFrameRateFieldSpecified As Boolean + + Private checksumsField() As ChecksumType + + Private audioTrackField() As AudioTracksType + + Private videoTrackField() As VideoTracksType + + Private subtitleTrackField() As SubtitleTracksType + + Private recordingField As RecordingType + + ''' + Public Property Manufacturer() As String + Get + Return Me.manufacturerField + End Get + Set + Me.manufacturerField = value + End Set + End Property + + ''' + Public Property Product() As String + Get + Return Me.productField + End Get + Set + Me.productField = value + End Set + End Property + + ''' + Public Property File() As FileType + Get + Return Me.fileField + End Get + Set + Me.fileField = value + End Set + End Property + + ''' + Public Property FileSize() As ULong + Get + Return Me.fileSizeField + End Get + Set + Me.fileSizeField = value + End Set + End Property + + ''' + Public Property Frames() As ULong + Get + Return Me.framesField + End Get + Set + Me.framesField = value + End Set + End Property + + ''' + _ + Public Property FramesSpecified() As Boolean + Get + Return Me.framesFieldSpecified + End Get + Set + Me.framesFieldSpecified = value + End Set + End Property + + ''' + Public Property Duration() As Double + Get + Return Me.durationField + End Get + Set + Me.durationField = value + End Set + End Property + + ''' + Public Property MeanFrameRate() As Single + Get + Return Me.meanFrameRateField + End Get + Set + Me.meanFrameRateField = value + End Set + End Property + + ''' + _ + Public Property MeanFrameRateSpecified() As Boolean + Get + Return Me.meanFrameRateFieldSpecified + End Get + Set + Me.meanFrameRateFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property Checksums() As ChecksumType() + Get + Return Me.checksumsField + End Get + Set + Me.checksumsField = value + End Set + End Property + + ''' + _ + Public Property AudioTrack() As AudioTracksType() + Get + Return Me.audioTrackField + End Get + Set + Me.audioTrackField = value + End Set + End Property + + ''' + _ + Public Property VideoTrack() As VideoTracksType() + Get + Return Me.videoTrackField + End Get + Set + Me.videoTrackField = value + End Set + End Property + + ''' + _ + Public Property SubtitleTrack() As SubtitleTracksType() + Get + Return Me.subtitleTrackField + End Get + Set + Me.subtitleTrackField = value + End Set + End Property + + ''' + Public Property Recording() As RecordingType + Get + Return Me.recordingField + End Get + Set + Me.recordingField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class SubChannelType + + Private imageField As ImageType + + Private sizeField As ULong + + Private checksumsField() As ChecksumType + + ''' + Public Property Image() As ImageType + Get + Return Me.imageField + End Get + Set + Me.imageField = value + End Set + End Property + + ''' + Public Property Size() As ULong + Get + Return Me.sizeField + End Get + Set + Me.sizeField = value + End Set + End Property + + ''' + _ + Public Property Checksums() As ChecksumType() + Get + Return Me.checksumsField + End Get + Set + Me.checksumsField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class TrackFlagsType + + Private quadraphonicField As Boolean + + Private dataField As Boolean + + Private copyPermittedField As Boolean + + Private preEmphasisField As Boolean + + ''' + Public Property Quadraphonic() As Boolean + Get + Return Me.quadraphonicField + End Get + Set + Me.quadraphonicField = value + End Set + End Property + + ''' + Public Property Data() As Boolean + Get + Return Me.dataField + End Get + Set + Me.dataField = value + End Set + End Property + + ''' + Public Property CopyPermitted() As Boolean + Get + Return Me.copyPermittedField + End Get + Set + Me.copyPermittedField = value + End Set + End Property + + ''' + Public Property PreEmphasis() As Boolean + Get + Return Me.preEmphasisField + End Get + Set + Me.preEmphasisField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class TrackIndexType + + Private indexField As UShort + + Private valueField As Integer + + ''' + _ + Public Property index() As UShort + Get + Return Me.indexField + End Get + Set + Me.indexField = value + End Set + End Property + + ''' + _ + Public Property Value() As Integer + Get + Return Me.valueField + End Get + Set + Me.valueField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class TrackSequenceType + + Private trackNumberField As UInteger + + Private sessionField As UInteger + + ''' + Public Property TrackNumber() As UInteger + Get + Return Me.trackNumberField + End Get + Set + Me.trackNumberField = value + End Set + End Property + + ''' + Public Property Session() As UInteger + Get + Return Me.sessionField + End Get + Set + Me.sessionField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class TrackType + + Private imageField As ImageType + + Private sizeField As ULong + + Private sequenceField As TrackSequenceType + + Private startMSFField As String + + Private endMSFField As String + + Private startSectorField As ULong + + Private endSectorField As ULong + + Private indexesField() As TrackIndexType + + Private flagsField As TrackFlagsType + + Private iSRCField As String + + Private trackType1Field As TrackTypeTrackType + + Private bytesPerSectorField As UInteger + + Private accoustIDField As String + + Private checksumsField() As ChecksumType + + Private subChannelField As SubChannelType + + Private fileSystemInformationField() As PartitionType + + ''' + Public Property Image() As ImageType + Get + Return Me.imageField + End Get + Set + Me.imageField = value + End Set + End Property + + ''' + Public Property Size() As ULong + Get + Return Me.sizeField + End Get + Set + Me.sizeField = value + End Set + End Property + + ''' + Public Property Sequence() As TrackSequenceType + Get + Return Me.sequenceField + End Get + Set + Me.sequenceField = value + End Set + End Property + + ''' + Public Property StartMSF() As String + Get + Return Me.startMSFField + End Get + Set + Me.startMSFField = value + End Set + End Property + + ''' + Public Property EndMSF() As String + Get + Return Me.endMSFField + End Get + Set + Me.endMSFField = value + End Set + End Property + + ''' + Public Property StartSector() As ULong + Get + Return Me.startSectorField + End Get + Set + Me.startSectorField = value + End Set + End Property + + ''' + Public Property EndSector() As ULong + Get + Return Me.endSectorField + End Get + Set + Me.endSectorField = value + End Set + End Property + + ''' + _ + Public Property Indexes() As TrackIndexType() + Get + Return Me.indexesField + End Get + Set + Me.indexesField = value + End Set + End Property + + ''' + Public Property Flags() As TrackFlagsType + Get + Return Me.flagsField + End Get + Set + Me.flagsField = value + End Set + End Property + + ''' + Public Property ISRC() As String + Get + Return Me.iSRCField + End Get + Set + Me.iSRCField = value + End Set + End Property + + ''' + _ + Public Property TrackType1() As TrackTypeTrackType + Get + Return Me.trackType1Field + End Get + Set + Me.trackType1Field = value + End Set + End Property + + ''' + Public Property BytesPerSector() As UInteger + Get + Return Me.bytesPerSectorField + End Get + Set + Me.bytesPerSectorField = value + End Set + End Property + + ''' + Public Property AccoustID() As String + Get + Return Me.accoustIDField + End Get + Set + Me.accoustIDField = value + End Set + End Property + + ''' + _ + Public Property Checksums() As ChecksumType() + Get + Return Me.checksumsField + End Get + Set + Me.checksumsField = value + End Set + End Property + + ''' + Public Property SubChannel() As SubChannelType + Get + Return Me.subChannelField + End Get + Set + Me.subChannelField = value + End Set + End Property + + ''' + _ + Public Property FileSystemInformation() As PartitionType() + Get + Return Me.fileSystemInformationField + End Get + Set + Me.fileSystemInformationField = value + End Set + End Property + End Class + + ''' + _ + Public Enum TrackTypeTrackType + + ''' + audio + + ''' + mode0 + + ''' + mode1 + + ''' + mode2 + + ''' + m2f1 + + ''' + m2f2 + + ''' + dvd + + ''' + hddvd + + ''' + bluray + + ''' + ddcd + End Enum + + ''' + _ + Partial Public Class PS3EncryptionType + + Private keyField As String + + Private serialField As String + + ''' + Public Property Key() As String + Get + Return Me.keyField + End Get + Set + Me.keyField = value + End Set + End Property + + ''' + Public Property Serial() As String + Get + Return Me.serialField + End Get + Set + Me.serialField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class XboxSecuritySectorsType + + Private requestVersionField As UInteger + + Private requestNumberField As UInteger + + Private securitySectorsField As DumpType + + ''' + Public Property RequestVersion() As UInteger + Get + Return Me.requestVersionField + End Get + Set + Me.requestVersionField = value + End Set + End Property + + ''' + Public Property RequestNumber() As UInteger + Get + Return Me.requestNumberField + End Get + Set + Me.requestNumberField = value + End Set + End Property + + ''' + Public Property SecuritySectors() As DumpType + Get + Return Me.securitySectorsField + End Get + Set + Me.securitySectorsField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class XboxType + + Private pFIField As DumpType + + Private dMIField As DumpType + + Private securitySectorsField() As XboxSecuritySectorsType + + ''' + Public Property PFI() As DumpType + Get + Return Me.pFIField + End Get + Set + Me.pFIField = value + End Set + End Property + + ''' + Public Property DMI() As DumpType + Get + Return Me.dMIField + End Get + Set + Me.dMIField = value + End Set + End Property + + ''' + _ + Public Property SecuritySectors() As XboxSecuritySectorsType() + Get + Return Me.securitySectorsField + End Get + Set + Me.securitySectorsField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class BorderType + + Private imageField As String + + Private sizeField As ULong + + Private checksumsField() As ChecksumType + + Private sessionField As UInteger + + Private sessionFieldSpecified As Boolean + + ''' + Public Property Image() As String + Get + Return Me.imageField + End Get + Set + Me.imageField = value + End Set + End Property + + ''' + Public Property Size() As ULong + Get + Return Me.sizeField + End Get + Set + Me.sizeField = value + End Set + End Property + + ''' + _ + Public Property Checksums() As ChecksumType() + Get + Return Me.checksumsField + End Get + Set + Me.checksumsField = value + End Set + End Property + + ''' + _ + Public Property session() As UInteger + Get + Return Me.sessionField + End Get + Set + Me.sessionField = value + End Set + End Property + + ''' + _ + Public Property sessionSpecified() As Boolean + Get + Return Me.sessionFieldSpecified + End Get + Set + Me.sessionFieldSpecified = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class CaseType + + Private caseType1Field As CaseTypeCaseType + + Private scansField As ScansType + + ''' + _ + Public Property CaseType1() As CaseTypeCaseType + Get + Return Me.caseType1Field + End Get + Set + Me.caseType1Field = value + End Set + End Property + + ''' + Public Property Scans() As ScansType + Get + Return Me.scansField + End Get + Set + Me.scansField = value + End Set + End Property + End Class + + ''' + _ + Public Enum CaseTypeCaseType + + ''' + jewel + + ''' + bigjewel + + ''' + slimjewel + + ''' + sleeve + + ''' + qpack + + ''' + digisleeve + + ''' + discboxslider + + ''' + compacplus + + ''' + keepcase + + ''' + snapcase + + ''' + softcase + + ''' + ecopack + + ''' + liftlock + + ''' + spindle + + ''' + ps2case + + ''' + ps3case + + ''' + bluraykeepcase + + ''' + pscase + + ''' + dccase + + ''' + saturncase + + ''' + xboxcase + + ''' + xbox360case + + ''' + xboxonecase + + ''' + saturnbigcase + + ''' + gccase + + ''' + wiicase + + ''' + unknown + End Enum + + ''' + _ + Partial Public Class LayeredTextType + + Private layerField As UInteger + + Private layerFieldSpecified As Boolean + + Private valueField As String + + ''' + _ + Public Property layer() As UInteger + Get + Return Me.layerField + End Get + Set + Me.layerField = value + End Set + End Property + + ''' + _ + Public Property layerSpecified() As Boolean + Get + Return Me.layerFieldSpecified + End Get + Set + Me.layerFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property Value() As String + Get + Return Me.valueField + End Get + Set + Me.valueField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class SectorsType + + Private layerField As UInteger + + Private layerFieldSpecified As Boolean + + Private valueField As ULong + + ''' + _ + Public Property layer() As UInteger + Get + Return Me.layerField + End Get + Set + Me.layerField = value + End Set + End Property + + ''' + _ + Public Property layerSpecified() As Boolean + Get + Return Me.layerFieldSpecified + End Get + Set + Me.layerFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property Value() As ULong + Get + Return Me.valueField + End Get + Set + Me.valueField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class LayersType + + Private sectorsField() As SectorsType + + Private typeField As LayersTypeType + + Private typeFieldSpecified As Boolean + + ''' + _ + Public Property Sectors() As SectorsType() + Get + Return Me.sectorsField + End Get + Set + Me.sectorsField = value + End Set + End Property + + ''' + _ + Public Property type() As LayersTypeType + Get + Return Me.typeField + End Get + Set + Me.typeField = value + End Set + End Property + + ''' + _ + Public Property typeSpecified() As Boolean + Get + Return Me.typeFieldSpecified + End Get + Set + Me.typeFieldSpecified = value + End Set + End Property + End Class + + ''' + _ + Public Enum LayersTypeType + + ''' + PTP + + ''' + OTP + End Enum + + ''' + _ + Partial Public Class OpticalDiscType + + Private imageField As ImageType + + Private sizeField As ULong + + Private sequenceField As SequenceType + + Private layersField As LayersType + + Private checksumsField() As ChecksumType + + Private partNumberField As String + + Private serialNumberField As String + + Private ringCodeField() As LayeredTextType + + Private masteringSIDField() As LayeredTextType + + Private toolstampField() As LayeredTextType + + Private mouldSIDField() As LayeredTextType + + Private mouldTextField() As LayeredTextType + + Private discTypeField As String + + Private discSubTypeField As String + + Private offsetField As Integer + + Private offsetFieldSpecified As Boolean + + Private tracksField() As UInteger + + Private sessionsField As UInteger + + Private copyProtectionField As String + + Private dimensionsField As DimensionsType + + Private caseField As CaseType + + Private scansField As ScansType + + Private pFIField As DumpType + + Private dMIField As DumpType + + Private cMIField As DumpType + + Private bCAField As DumpType + + Private aTIPField As DumpType + + Private aDIPField As DumpType + + Private pMAField As DumpType + + Private dDSField As DumpType + + Private sAIField As DumpType + + Private lastRMDField As DumpType + + Private pRIField As DumpType + + Private mediaIDField As DumpType + + Private pFIRField As DumpType + + Private dCBField As DumpType + + Private diField As DumpType + + Private pACField As DumpType + + Private tOCField As DumpType + + Private leadInCdTextField As DumpType + + Private firstTrackPregrapField() As BorderType + + Private leadInField() As BorderType + + Private leadOutField() As BorderType + + Private xboxField As XboxType + + Private pS3EncryptionField As PS3EncryptionType + + Private mediaCatalogueNumberField As String + + Private trackField() As TrackType + + Private dumpHardwareArrayField() As DumpHardwareType + + ''' + Public Property Image() As ImageType + Get + Return Me.imageField + End Get + Set + Me.imageField = value + End Set + End Property + + ''' + Public Property Size() As ULong + Get + Return Me.sizeField + End Get + Set + Me.sizeField = value + End Set + End Property + + ''' + Public Property Sequence() As SequenceType + Get + Return Me.sequenceField + End Get + Set + Me.sequenceField = value + End Set + End Property + + ''' + Public Property Layers() As LayersType + Get + Return Me.layersField + End Get + Set + Me.layersField = value + End Set + End Property + + ''' + _ + Public Property Checksums() As ChecksumType() + Get + Return Me.checksumsField + End Get + Set + Me.checksumsField = value + End Set + End Property + + ''' + Public Property PartNumber() As String + Get + Return Me.partNumberField + End Get + Set + Me.partNumberField = value + End Set + End Property + + ''' + Public Property SerialNumber() As String + Get + Return Me.serialNumberField + End Get + Set + Me.serialNumberField = value + End Set + End Property + + ''' + _ + Public Property RingCode() As LayeredTextType() + Get + Return Me.ringCodeField + End Get + Set + Me.ringCodeField = value + End Set + End Property + + ''' + _ + Public Property MasteringSID() As LayeredTextType() + Get + Return Me.masteringSIDField + End Get + Set + Me.masteringSIDField = value + End Set + End Property + + ''' + _ + Public Property Toolstamp() As LayeredTextType() + Get + Return Me.toolstampField + End Get + Set + Me.toolstampField = value + End Set + End Property + + ''' + _ + Public Property MouldSID() As LayeredTextType() + Get + Return Me.mouldSIDField + End Get + Set + Me.mouldSIDField = value + End Set + End Property + + ''' + _ + Public Property MouldText() As LayeredTextType() + Get + Return Me.mouldTextField + End Get + Set + Me.mouldTextField = value + End Set + End Property + + ''' + Public Property DiscType() As String + Get + Return Me.discTypeField + End Get + Set + Me.discTypeField = value + End Set + End Property + + ''' + Public Property DiscSubType() As String + Get + Return Me.discSubTypeField + End Get + Set + Me.discSubTypeField = value + End Set + End Property + + ''' + Public Property Offset() As Integer + Get + Return Me.offsetField + End Get + Set + Me.offsetField = value + End Set + End Property + + ''' + _ + Public Property OffsetSpecified() As Boolean + Get + Return Me.offsetFieldSpecified + End Get + Set + Me.offsetFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property Tracks() As UInteger() + Get + Return Me.tracksField + End Get + Set + Me.tracksField = value + End Set + End Property + + ''' + Public Property Sessions() As UInteger + Get + Return Me.sessionsField + End Get + Set + Me.sessionsField = value + End Set + End Property + + ''' + Public Property CopyProtection() As String + Get + Return Me.copyProtectionField + End Get + Set + Me.copyProtectionField = value + End Set + End Property + + ''' + Public Property Dimensions() As DimensionsType + Get + Return Me.dimensionsField + End Get + Set + Me.dimensionsField = value + End Set + End Property + + ''' + Public Property [Case]() As CaseType + Get + Return Me.caseField + End Get + Set + Me.caseField = value + End Set + End Property + + ''' + Public Property Scans() As ScansType + Get + Return Me.scansField + End Get + Set + Me.scansField = value + End Set + End Property + + ''' + Public Property PFI() As DumpType + Get + Return Me.pFIField + End Get + Set + Me.pFIField = value + End Set + End Property + + ''' + Public Property DMI() As DumpType + Get + Return Me.dMIField + End Get + Set + Me.dMIField = value + End Set + End Property + + ''' + Public Property CMI() As DumpType + Get + Return Me.cMIField + End Get + Set + Me.cMIField = value + End Set + End Property + + ''' + Public Property BCA() As DumpType + Get + Return Me.bCAField + End Get + Set + Me.bCAField = value + End Set + End Property + + ''' + Public Property ATIP() As DumpType + Get + Return Me.aTIPField + End Get + Set + Me.aTIPField = value + End Set + End Property + + ''' + Public Property ADIP() As DumpType + Get + Return Me.aDIPField + End Get + Set + Me.aDIPField = value + End Set + End Property + + ''' + Public Property PMA() As DumpType + Get + Return Me.pMAField + End Get + Set + Me.pMAField = value + End Set + End Property + + ''' + Public Property DDS() As DumpType + Get + Return Me.dDSField + End Get + Set + Me.dDSField = value + End Set + End Property + + ''' + Public Property SAI() As DumpType + Get + Return Me.sAIField + End Get + Set + Me.sAIField = value + End Set + End Property + + ''' + Public Property LastRMD() As DumpType + Get + Return Me.lastRMDField + End Get + Set + Me.lastRMDField = value + End Set + End Property + + ''' + Public Property PRI() As DumpType + Get + Return Me.pRIField + End Get + Set + Me.pRIField = value + End Set + End Property + + ''' + Public Property MediaID() As DumpType + Get + Return Me.mediaIDField + End Get + Set + Me.mediaIDField = value + End Set + End Property + + ''' + Public Property PFIR() As DumpType + Get + Return Me.pFIRField + End Get + Set + Me.pFIRField = value + End Set + End Property + + ''' + Public Property DCB() As DumpType + Get + Return Me.dCBField + End Get + Set + Me.dCBField = value + End Set + End Property + + ''' + Public Property DI() As DumpType + Get + Return Me.diField + End Get + Set + Me.diField = value + End Set + End Property + + ''' + Public Property PAC() As DumpType + Get + Return Me.pACField + End Get + Set + Me.pACField = value + End Set + End Property + + ''' + Public Property TOC() As DumpType + Get + Return Me.tOCField + End Get + Set + Me.tOCField = value + End Set + End Property + + ''' + Public Property LeadInCdText() As DumpType + Get + Return Me.leadInCdTextField + End Get + Set + Me.leadInCdTextField = value + End Set + End Property + + ''' + _ + Public Property FirstTrackPregrap() As BorderType() + Get + Return Me.firstTrackPregrapField + End Get + Set + Me.firstTrackPregrapField = value + End Set + End Property + + ''' + _ + Public Property LeadIn() As BorderType() + Get + Return Me.leadInField + End Get + Set + Me.leadInField = value + End Set + End Property + + ''' + _ + Public Property LeadOut() As BorderType() + Get + Return Me.leadOutField + End Get + Set + Me.leadOutField = value + End Set + End Property + + ''' + Public Property Xbox() As XboxType + Get + Return Me.xboxField + End Get + Set + Me.xboxField = value + End Set + End Property + + ''' + Public Property PS3Encryption() As PS3EncryptionType + Get + Return Me.pS3EncryptionField + End Get + Set + Me.pS3EncryptionField = value + End Set + End Property + + ''' + Public Property MediaCatalogueNumber() As String + Get + Return Me.mediaCatalogueNumberField + End Get + Set + Me.mediaCatalogueNumberField = value + End Set + End Property + + ''' + _ + Public Property Track() As TrackType() + Get + Return Me.trackField + End Get + Set + Me.trackField = value + End Set + End Property + + ''' + _ + Public Property DumpHardwareArray() As DumpHardwareType() + Get + Return Me.dumpHardwareArrayField + End Get + Set + Me.dumpHardwareArrayField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class UserManualType + + Private languageField() As LanguagesTypeLanguage + + Private pagesField As UInteger + + Private pageSizeField As String + + Private scanField As ScanType + + ''' + _ + Public Property Language() As LanguagesTypeLanguage() + Get + Return Me.languageField + End Get + Set + Me.languageField = value + End Set + End Property + + ''' + Public Property Pages() As UInteger + Get + Return Me.pagesField + End Get + Set + Me.pagesField = value + End Set + End Property + + ''' + Public Property PageSize() As String + Get + Return Me.pageSizeField + End Get + Set + Me.pageSizeField = value + End Set + End Property + + ''' + Public Property Scan() As ScanType + Get + Return Me.scanField + End Get + Set + Me.scanField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class RequiredOperatingSystemType + + Private nameField As String + + Private versionField() As String + + ''' + Public Property Name() As String + Get + Return Me.nameField + End Get + Set + Me.nameField = value + End Set + End Property + + ''' + _ + Public Property Version() As String() + Get + Return Me.versionField + End Get + Set + Me.versionField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class BookType + + Private barcodesField() As BarcodeType + + Private coverField As CoverType + + Private nameField As String + + Private editorialField As String + + Private authorField As String + + Private publicationDateField As Date + + Private publicationDateFieldSpecified As Boolean + + Private languageField() As LanguagesTypeLanguage + + Private pagesField As UInteger + + Private pagesFieldSpecified As Boolean + + Private pageSizeField As String + + Private scanField As ScanType + + ''' + _ + Public Property Barcodes() As BarcodeType() + Get + Return Me.barcodesField + End Get + Set + Me.barcodesField = value + End Set + End Property + + ''' + Public Property Cover() As CoverType + Get + Return Me.coverField + End Get + Set + Me.coverField = value + End Set + End Property + + ''' + Public Property Name() As String + Get + Return Me.nameField + End Get + Set + Me.nameField = value + End Set + End Property + + ''' + Public Property Editorial() As String + Get + Return Me.editorialField + End Get + Set + Me.editorialField = value + End Set + End Property + + ''' + Public Property Author() As String + Get + Return Me.authorField + End Get + Set + Me.authorField = value + End Set + End Property + + ''' + _ + Public Property PublicationDate() As Date + Get + Return Me.publicationDateField + End Get + Set + Me.publicationDateField = value + End Set + End Property + + ''' + _ + Public Property PublicationDateSpecified() As Boolean + Get + Return Me.publicationDateFieldSpecified + End Get + Set + Me.publicationDateFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property Language() As LanguagesTypeLanguage() + Get + Return Me.languageField + End Get + Set + Me.languageField = value + End Set + End Property + + ''' + Public Property Pages() As UInteger + Get + Return Me.pagesField + End Get + Set + Me.pagesField = value + End Set + End Property + + ''' + _ + Public Property PagesSpecified() As Boolean + Get + Return Me.pagesFieldSpecified + End Get + Set + Me.pagesFieldSpecified = value + End Set + End Property + + ''' + Public Property PageSize() As String + Get + Return Me.pageSizeField + End Get + Set + Me.pageSizeField = value + End Set + End Property + + ''' + Public Property Scan() As ScanType + Get + Return Me.scanField + End Get + Set + Me.scanField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class CoverType + + Private fileField As FileType + + Private checksumsField() As ChecksumType + + Private thumbnailField() As Byte + + ''' + Public Property File() As FileType + Get + Return Me.fileField + End Get + Set + Me.fileField = value + End Set + End Property + + ''' + _ + Public Property Checksums() As ChecksumType() + Get + Return Me.checksumsField + End Get + Set + Me.checksumsField = value + End Set + End Property + + ''' + _ + Public Property Thumbnail() As Byte() + Get + Return Me.thumbnailField + End Get + Set + Me.thumbnailField = value + End Set + End Property + End Class + + ''' + _ + Partial Public Class MagazineType + + Private barcodesField() As BarcodeType + + Private coverField As CoverType + + Private nameField As String + + Private editorialField As String + + Private publicationDateField As Date + + Private publicationDateFieldSpecified As Boolean + + Private numberField As UInteger + + Private numberFieldSpecified As Boolean + + Private languageField() As LanguagesTypeLanguage + + Private pagesField As UInteger + + Private pagesFieldSpecified As Boolean + + Private pageSizeField As String + + Private scanField As ScanType + + ''' + _ + Public Property Barcodes() As BarcodeType() + Get + Return Me.barcodesField + End Get + Set + Me.barcodesField = value + End Set + End Property + + ''' + Public Property Cover() As CoverType + Get + Return Me.coverField + End Get + Set + Me.coverField = value + End Set + End Property + + ''' + Public Property Name() As String + Get + Return Me.nameField + End Get + Set + Me.nameField = value + End Set + End Property + + ''' + Public Property Editorial() As String + Get + Return Me.editorialField + End Get + Set + Me.editorialField = value + End Set + End Property + + ''' + _ + Public Property PublicationDate() As Date + Get + Return Me.publicationDateField + End Get + Set + Me.publicationDateField = value + End Set + End Property + + ''' + _ + Public Property PublicationDateSpecified() As Boolean + Get + Return Me.publicationDateFieldSpecified + End Get + Set + Me.publicationDateFieldSpecified = value + End Set + End Property + + ''' + Public Property Number() As UInteger + Get + Return Me.numberField + End Get + Set + Me.numberField = value + End Set + End Property + + ''' + _ + Public Property NumberSpecified() As Boolean + Get + Return Me.numberFieldSpecified + End Get + Set + Me.numberFieldSpecified = value + End Set + End Property + + ''' + _ + Public Property Language() As LanguagesTypeLanguage() + Get + Return Me.languageField + End Get + Set + Me.languageField = value + End Set + End Property + + ''' + Public Property Pages() As UInteger + Get + Return Me.pagesField + End Get + Set + Me.pagesField = value + End Set + End Property + + ''' + _ + Public Property PagesSpecified() As Boolean + Get + Return Me.pagesFieldSpecified + End Get + Set + Me.pagesFieldSpecified = value + End Set + End Property + + ''' + Public Property PageSize() As String + Get + Return Me.pageSizeField + End Get + Set + Me.pageSizeField = value + End Set + End Property + + ''' + Public Property Scan() As ScanType + Get + Return Me.scanField + End Get + Set + Me.scanField = value + End Set + End Property + End Class + + ''' + _ + Public Enum ArchitecturesTypeArchitecture + + ''' + _ + Item4004 + + ''' + _ + Item4040 + + ''' + _ + Item6502 + + ''' + _ + Item65816 + + ''' + _ + Item8008 + + ''' + _ + Item8051 + + ''' + _ + Item8080 + + ''' + _ + Item8085 + + ''' + aarch64 + + ''' + am29000 + + ''' + amd64 + + ''' + apx432 + + ''' + arm + + ''' + avr + + ''' + avr32 + + ''' + axp + + ''' + clipper + + ''' + cray + + ''' + esa390 + + ''' + hobbit + + ''' + i86 + + ''' + i860 + + ''' + i960 + + ''' + ia32 + + ''' + ia64 + + ''' + m56k + + ''' + m6800 + + ''' + m6801 + + ''' + m6805 + + ''' + m6809 + + ''' + m68k + + ''' + m88k + + ''' + mcs41 + + ''' + mcs48 + + ''' + mips32 + + ''' + mips64 + + ''' + msp430 + + ''' + nios2 + + ''' + openrisc + + ''' + parisc + + ''' + pdp1 + + ''' + pdp10 + + ''' + pdp11 + + ''' + pdp7 + + ''' + pdp8 + + ''' + pic + + ''' + power + + ''' + ppc + + ''' + ppc64 + + ''' + prism + + ''' + renesasrx + + ''' + riscv + + ''' + s360 + + ''' + s370 + + ''' + sh + + ''' + sh1 + + ''' + sh2 + + ''' + sh3 + + ''' + sh4 + + ''' + sh5 + + ''' + sh64 + + ''' + sparc + + ''' + sparc64 + + ''' + transputer + + ''' + vax + + ''' + we32000 + + ''' + x32 + + ''' + z80 + + ''' + z800 + + ''' + z8000 + + ''' + z80000 + + ''' + zarch + End Enum +End Namespace diff --git a/CICMMetadata/java/generated/ATAType.java b/CICMMetadata/java/generated/ATAType.java new file mode 100644 index 000000000..044a1b12f --- /dev/null +++ b/CICMMetadata/java/generated/ATAType.java @@ -0,0 +1,71 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * Contains ATA/ATAPI device information + * + *

Clase Java para ATAType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="ATAType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Identify" type="{}DumpType"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ATAType", propOrder = { + "identify" +}) +public class ATAType { + + @XmlElement(name = "Identify", required = true) + protected DumpType identify; + + /** + * Obtiene el valor de la propiedad identify. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getIdentify() { + return identify; + } + + /** + * Define el valor de la propiedad identify. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setIdentify(DumpType value) { + this.identify = value; + } + +} diff --git a/CICMMetadata/java/generated/AdvertisementType.java b/CICMMetadata/java/generated/AdvertisementType.java new file mode 100644 index 000000000..d6fbdf5bb --- /dev/null +++ b/CICMMetadata/java/generated/AdvertisementType.java @@ -0,0 +1,390 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para AdvertisementType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="AdvertisementType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Manufacturer" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Product" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="File" type="{}FileType"/>
+ *         <element name="FileSize" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="Frames" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" minOccurs="0"/>
+ *         <element name="Duration" type="{http://www.w3.org/2001/XMLSchema}double"/>
+ *         <element name="MeanFrameRate" type="{http://www.w3.org/2001/XMLSchema}float" minOccurs="0"/>
+ *         <element name="Checksums" type="{}ChecksumsType"/>
+ *         <element name="AudioTrack" type="{}AudioTracksType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="VideoTrack" type="{}VideoTracksType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="SubtitleTrack" type="{}SubtitleTracksType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="Recording" type="{}RecordingType" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "AdvertisementType", propOrder = { + "manufacturer", + "product", + "file", + "fileSize", + "frames", + "duration", + "meanFrameRate", + "checksums", + "audioTrack", + "videoTrack", + "subtitleTrack", + "recording" +}) +public class AdvertisementType { + + @XmlElement(name = "Manufacturer", required = true) + protected String manufacturer; + @XmlElement(name = "Product", required = true) + protected String product; + @XmlElement(name = "File", required = true) + protected FileType file; + @XmlElement(name = "FileSize", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger fileSize; + @XmlElement(name = "Frames") + @XmlSchemaType(name = "unsignedLong") + protected BigInteger frames; + @XmlElement(name = "Duration") + protected double duration; + @XmlElement(name = "MeanFrameRate") + protected Float meanFrameRate; + @XmlElement(name = "Checksums", required = true) + protected ChecksumsType checksums; + @XmlElement(name = "AudioTrack") + protected List audioTrack; + @XmlElement(name = "VideoTrack") + protected List videoTrack; + @XmlElement(name = "SubtitleTrack") + protected List subtitleTrack; + @XmlElement(name = "Recording") + protected RecordingType recording; + + /** + * Obtiene el valor de la propiedad manufacturer. + * + * @return + * possible object is + * {@link String } + * + */ + public String getManufacturer() { + return manufacturer; + } + + /** + * Define el valor de la propiedad manufacturer. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setManufacturer(String value) { + this.manufacturer = value; + } + + /** + * Obtiene el valor de la propiedad product. + * + * @return + * possible object is + * {@link String } + * + */ + public String getProduct() { + return product; + } + + /** + * Define el valor de la propiedad product. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setProduct(String value) { + this.product = value; + } + + /** + * Obtiene el valor de la propiedad file. + * + * @return + * possible object is + * {@link FileType } + * + */ + public FileType getFile() { + return file; + } + + /** + * Define el valor de la propiedad file. + * + * @param value + * allowed object is + * {@link FileType } + * + */ + public void setFile(FileType value) { + this.file = value; + } + + /** + * Obtiene el valor de la propiedad fileSize. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getFileSize() { + return fileSize; + } + + /** + * Define el valor de la propiedad fileSize. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setFileSize(BigInteger value) { + this.fileSize = value; + } + + /** + * Obtiene el valor de la propiedad frames. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getFrames() { + return frames; + } + + /** + * Define el valor de la propiedad frames. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setFrames(BigInteger value) { + this.frames = value; + } + + /** + * Obtiene el valor de la propiedad duration. + * + */ + public double getDuration() { + return duration; + } + + /** + * Define el valor de la propiedad duration. + * + */ + public void setDuration(double value) { + this.duration = value; + } + + /** + * Obtiene el valor de la propiedad meanFrameRate. + * + * @return + * possible object is + * {@link Float } + * + */ + public Float getMeanFrameRate() { + return meanFrameRate; + } + + /** + * Define el valor de la propiedad meanFrameRate. + * + * @param value + * allowed object is + * {@link Float } + * + */ + public void setMeanFrameRate(Float value) { + this.meanFrameRate = value; + } + + /** + * Obtiene el valor de la propiedad checksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getChecksums() { + return checksums; + } + + /** + * Define el valor de la propiedad checksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setChecksums(ChecksumsType value) { + this.checksums = value; + } + + /** + * Gets the value of the audioTrack property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the audioTrack property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getAudioTrack().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link AudioTracksType } + * + * + */ + public List getAudioTrack() { + if (audioTrack == null) { + audioTrack = new ArrayList(); + } + return this.audioTrack; + } + + /** + * Gets the value of the videoTrack property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the videoTrack property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getVideoTrack().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link VideoTracksType } + * + * + */ + public List getVideoTrack() { + if (videoTrack == null) { + videoTrack = new ArrayList(); + } + return this.videoTrack; + } + + /** + * Gets the value of the subtitleTrack property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the subtitleTrack property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getSubtitleTrack().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link SubtitleTracksType } + * + * + */ + public List getSubtitleTrack() { + if (subtitleTrack == null) { + subtitleTrack = new ArrayList(); + } + return this.subtitleTrack; + } + + /** + * Obtiene el valor de la propiedad recording. + * + * @return + * possible object is + * {@link RecordingType } + * + */ + public RecordingType getRecording() { + return recording; + } + + /** + * Define el valor de la propiedad recording. + * + * @param value + * allowed object is + * {@link RecordingType } + * + */ + public void setRecording(RecordingType value) { + this.recording = value; + } + +} diff --git a/CICMMetadata/java/generated/ArchitecturesType.java b/CICMMetadata/java/generated/ArchitecturesType.java new file mode 100644 index 000000000..1838f6c49 --- /dev/null +++ b/CICMMetadata/java/generated/ArchitecturesType.java @@ -0,0 +1,156 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * CPU architectures this set is intended to be run on + * + * + *

Clase Java para ArchitecturesType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="ArchitecturesType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Architecture" maxOccurs="unbounded">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ *               <enumeration value="4004"/>
+ *               <enumeration value="4040"/>
+ *               <enumeration value="6502"/>
+ *               <enumeration value="65816"/>
+ *               <enumeration value="8008"/>
+ *               <enumeration value="8051"/>
+ *               <enumeration value="8080"/>
+ *               <enumeration value="8085"/>
+ *               <enumeration value="aarch64"/>
+ *               <enumeration value="am29000"/>
+ *               <enumeration value="amd64"/>
+ *               <enumeration value="apx432"/>
+ *               <enumeration value="arm"/>
+ *               <enumeration value="avr"/>
+ *               <enumeration value="avr32"/>
+ *               <enumeration value="axp"/>
+ *               <enumeration value="clipper"/>
+ *               <enumeration value="cray"/>
+ *               <enumeration value="esa390"/>
+ *               <enumeration value="hobbit"/>
+ *               <enumeration value="i86"/>
+ *               <enumeration value="i860"/>
+ *               <enumeration value="i960"/>
+ *               <enumeration value="ia32"/>
+ *               <enumeration value="ia64"/>
+ *               <enumeration value="m56k"/>
+ *               <enumeration value="m6800"/>
+ *               <enumeration value="m6801"/>
+ *               <enumeration value="m6805"/>
+ *               <enumeration value="m6809"/>
+ *               <enumeration value="m68k"/>
+ *               <enumeration value="m88k"/>
+ *               <enumeration value="mcs41"/>
+ *               <enumeration value="mcs48"/>
+ *               <enumeration value="mips32"/>
+ *               <enumeration value="mips64"/>
+ *               <enumeration value="msp430"/>
+ *               <enumeration value="nios2"/>
+ *               <enumeration value="openrisc"/>
+ *               <enumeration value="parisc"/>
+ *               <enumeration value="pdp1"/>
+ *               <enumeration value="pdp10"/>
+ *               <enumeration value="pdp11"/>
+ *               <enumeration value="pdp7"/>
+ *               <enumeration value="pdp8"/>
+ *               <enumeration value="pic"/>
+ *               <enumeration value="power"/>
+ *               <enumeration value="ppc"/>
+ *               <enumeration value="ppc64"/>
+ *               <enumeration value="prism"/>
+ *               <enumeration value="renesasrx"/>
+ *               <enumeration value="riscv"/>
+ *               <enumeration value="s360"/>
+ *               <enumeration value="s370"/>
+ *               <enumeration value="sh"/>
+ *               <enumeration value="sh1"/>
+ *               <enumeration value="sh2"/>
+ *               <enumeration value="sh3"/>
+ *               <enumeration value="sh4"/>
+ *               <enumeration value="sh5"/>
+ *               <enumeration value="sh64"/>
+ *               <enumeration value="sparc"/>
+ *               <enumeration value="sparc64"/>
+ *               <enumeration value="transputer"/>
+ *               <enumeration value="vax"/>
+ *               <enumeration value="we32000"/>
+ *               <enumeration value="x32"/>
+ *               <enumeration value="z80"/>
+ *               <enumeration value="z800"/>
+ *               <enumeration value="z8000"/>
+ *               <enumeration value="z80000"/>
+ *               <enumeration value="zarch"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ArchitecturesType", propOrder = { + "architecture" +}) +public class ArchitecturesType { + + @XmlElement(name = "Architecture", required = true) + protected List architecture; + + /** + * Gets the value of the architecture property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the architecture property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getArchitecture().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link String } + * + * + */ + public List getArchitecture() { + if (architecture == null) { + architecture = new ArrayList(); + } + return this.architecture; + } + +} diff --git a/CICMMetadata/java/generated/AudioBlockType.java b/CICMMetadata/java/generated/AudioBlockType.java new file mode 100644 index 000000000..70a785aca --- /dev/null +++ b/CICMMetadata/java/generated/AudioBlockType.java @@ -0,0 +1,186 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * Information about "blocks" in audio based media + * + *

Clase Java para AudioBlockType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="AudioBlockType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Image" type="{}ImageType"/>
+ *         <element name="Size" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="AccoustID" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Checksums" type="{}ChecksumsType"/>
+ *         <element name="Format" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "AudioBlockType", propOrder = { + "image", + "size", + "accoustID", + "checksums", + "format" +}) +public class AudioBlockType { + + @XmlElement(name = "Image", required = true) + protected ImageType image; + @XmlElement(name = "Size", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger size; + @XmlElement(name = "AccoustID", required = true) + protected String accoustID; + @XmlElement(name = "Checksums", required = true) + protected ChecksumsType checksums; + @XmlElement(name = "Format") + protected String format; + + /** + * Obtiene el valor de la propiedad image. + * + * @return + * possible object is + * {@link ImageType } + * + */ + public ImageType getImage() { + return image; + } + + /** + * Define el valor de la propiedad image. + * + * @param value + * allowed object is + * {@link ImageType } + * + */ + public void setImage(ImageType value) { + this.image = value; + } + + /** + * Obtiene el valor de la propiedad size. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getSize() { + return size; + } + + /** + * Define el valor de la propiedad size. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setSize(BigInteger value) { + this.size = value; + } + + /** + * Obtiene el valor de la propiedad accoustID. + * + * @return + * possible object is + * {@link String } + * + */ + public String getAccoustID() { + return accoustID; + } + + /** + * Define el valor de la propiedad accoustID. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setAccoustID(String value) { + this.accoustID = value; + } + + /** + * Obtiene el valor de la propiedad checksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getChecksums() { + return checksums; + } + + /** + * Define el valor de la propiedad checksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setChecksums(ChecksumsType value) { + this.checksums = value; + } + + /** + * Obtiene el valor de la propiedad format. + * + * @return + * possible object is + * {@link String } + * + */ + public String getFormat() { + return format; + } + + /** + * Define el valor de la propiedad format. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setFormat(String value) { + this.format = value; + } + +} diff --git a/CICMMetadata/java/generated/AudioMediaType.java b/CICMMetadata/java/generated/AudioMediaType.java new file mode 100644 index 000000000..6bc62069d --- /dev/null +++ b/CICMMetadata/java/generated/AudioMediaType.java @@ -0,0 +1,447 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * Describes a dump of a media that is stored in an audio device (like a ZX Spectrum + * cassette) + * + * + *

Clase Java para AudioMediaType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="AudioMediaType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Image" type="{}ImageType"/>
+ *         <element name="Size" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="Checksums" type="{}ChecksumsType"/>
+ *         <element name="Sequence" type="{}SequenceType"/>
+ *         <element name="PartNumber" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="SerialNumber" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Manufacturer" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Model" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="AccoustID" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Block" type="{}AudioBlockType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="CopyProtection" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Dimensions" type="{}DimensionsType"/>
+ *         <element name="Scans" type="{}ScansType" minOccurs="0"/>
+ *         <element name="DumpHardwareArray" type="{}DumpHardwareArrayType" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "AudioMediaType", propOrder = { + "image", + "size", + "checksums", + "sequence", + "partNumber", + "serialNumber", + "manufacturer", + "model", + "accoustID", + "block", + "copyProtection", + "dimensions", + "scans", + "dumpHardwareArray" +}) +public class AudioMediaType { + + @XmlElement(name = "Image", required = true) + protected ImageType image; + @XmlElement(name = "Size", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger size; + @XmlElement(name = "Checksums", required = true) + protected ChecksumsType checksums; + @XmlElement(name = "Sequence", required = true) + protected SequenceType sequence; + @XmlElement(name = "PartNumber") + protected String partNumber; + @XmlElement(name = "SerialNumber") + protected String serialNumber; + @XmlElement(name = "Manufacturer") + protected String manufacturer; + @XmlElement(name = "Model") + protected String model; + @XmlElement(name = "AccoustID") + protected String accoustID; + @XmlElement(name = "Block") + protected List block; + @XmlElement(name = "CopyProtection") + protected String copyProtection; + @XmlElement(name = "Dimensions", required = true) + protected DimensionsType dimensions; + @XmlElement(name = "Scans") + protected ScansType scans; + @XmlElement(name = "DumpHardwareArray") + protected DumpHardwareArrayType dumpHardwareArray; + + /** + * Obtiene el valor de la propiedad image. + * + * @return + * possible object is + * {@link ImageType } + * + */ + public ImageType getImage() { + return image; + } + + /** + * Define el valor de la propiedad image. + * + * @param value + * allowed object is + * {@link ImageType } + * + */ + public void setImage(ImageType value) { + this.image = value; + } + + /** + * Obtiene el valor de la propiedad size. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getSize() { + return size; + } + + /** + * Define el valor de la propiedad size. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setSize(BigInteger value) { + this.size = value; + } + + /** + * Obtiene el valor de la propiedad checksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getChecksums() { + return checksums; + } + + /** + * Define el valor de la propiedad checksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setChecksums(ChecksumsType value) { + this.checksums = value; + } + + /** + * Obtiene el valor de la propiedad sequence. + * + * @return + * possible object is + * {@link SequenceType } + * + */ + public SequenceType getSequence() { + return sequence; + } + + /** + * Define el valor de la propiedad sequence. + * + * @param value + * allowed object is + * {@link SequenceType } + * + */ + public void setSequence(SequenceType value) { + this.sequence = value; + } + + /** + * Obtiene el valor de la propiedad partNumber. + * + * @return + * possible object is + * {@link String } + * + */ + public String getPartNumber() { + return partNumber; + } + + /** + * Define el valor de la propiedad partNumber. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setPartNumber(String value) { + this.partNumber = value; + } + + /** + * Obtiene el valor de la propiedad serialNumber. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSerialNumber() { + return serialNumber; + } + + /** + * Define el valor de la propiedad serialNumber. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSerialNumber(String value) { + this.serialNumber = value; + } + + /** + * Obtiene el valor de la propiedad manufacturer. + * + * @return + * possible object is + * {@link String } + * + */ + public String getManufacturer() { + return manufacturer; + } + + /** + * Define el valor de la propiedad manufacturer. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setManufacturer(String value) { + this.manufacturer = value; + } + + /** + * Obtiene el valor de la propiedad model. + * + * @return + * possible object is + * {@link String } + * + */ + public String getModel() { + return model; + } + + /** + * Define el valor de la propiedad model. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setModel(String value) { + this.model = value; + } + + /** + * Obtiene el valor de la propiedad accoustID. + * + * @return + * possible object is + * {@link String } + * + */ + public String getAccoustID() { + return accoustID; + } + + /** + * Define el valor de la propiedad accoustID. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setAccoustID(String value) { + this.accoustID = value; + } + + /** + * Gets the value of the block property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the block property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getBlock().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link AudioBlockType } + * + * + */ + public List getBlock() { + if (block == null) { + block = new ArrayList(); + } + return this.block; + } + + /** + * Obtiene el valor de la propiedad copyProtection. + * + * @return + * possible object is + * {@link String } + * + */ + public String getCopyProtection() { + return copyProtection; + } + + /** + * Define el valor de la propiedad copyProtection. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setCopyProtection(String value) { + this.copyProtection = value; + } + + /** + * Obtiene el valor de la propiedad dimensions. + * + * @return + * possible object is + * {@link DimensionsType } + * + */ + public DimensionsType getDimensions() { + return dimensions; + } + + /** + * Define el valor de la propiedad dimensions. + * + * @param value + * allowed object is + * {@link DimensionsType } + * + */ + public void setDimensions(DimensionsType value) { + this.dimensions = value; + } + + /** + * Obtiene el valor de la propiedad scans. + * + * @return + * possible object is + * {@link ScansType } + * + */ + public ScansType getScans() { + return scans; + } + + /** + * Define el valor de la propiedad scans. + * + * @param value + * allowed object is + * {@link ScansType } + * + */ + public void setScans(ScansType value) { + this.scans = value; + } + + /** + * Obtiene el valor de la propiedad dumpHardwareArray. + * + * @return + * possible object is + * {@link DumpHardwareArrayType } + * + */ + public DumpHardwareArrayType getDumpHardwareArray() { + return dumpHardwareArray; + } + + /** + * Define el valor de la propiedad dumpHardwareArray. + * + * @param value + * allowed object is + * {@link DumpHardwareArrayType } + * + */ + public void setDumpHardwareArray(DumpHardwareArrayType value) { + this.dumpHardwareArray = value; + } + +} diff --git a/CICMMetadata/java/generated/AudioTracksType.java b/CICMMetadata/java/generated/AudioTracksType.java new file mode 100644 index 000000000..d471eb7c6 --- /dev/null +++ b/CICMMetadata/java/generated/AudioTracksType.java @@ -0,0 +1,208 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para AudioTracksType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="AudioTracksType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Languages" type="{}LanguagesType" minOccurs="0"/>
+ *       </sequence>
+ *       <attribute name="TrackNumber" use="required">
+ *         <simpleType>
+ *           <restriction base="{http://www.w3.org/2001/XMLSchema}unsignedInt">
+ *             <minInclusive value="1"/>
+ *           </restriction>
+ *         </simpleType>
+ *       </attribute>
+ *       <attribute name="AccoustID" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="Codec" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="Channels" use="required" type="{http://www.w3.org/2001/XMLSchema}unsignedInt" />
+ *       <attribute name="SampleRate" use="required" type="{http://www.w3.org/2001/XMLSchema}double" />
+ *       <attribute name="MeanBitrate" use="required" type="{http://www.w3.org/2001/XMLSchema}long" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "AudioTracksType", propOrder = { + "languages" +}) +public class AudioTracksType { + + @XmlElement(name = "Languages") + protected LanguagesType languages; + @XmlAttribute(name = "TrackNumber", required = true) + protected long trackNumber; + @XmlAttribute(name = "AccoustID") + protected String accoustID; + @XmlAttribute(name = "Codec", required = true) + protected String codec; + @XmlAttribute(name = "Channels", required = true) + @XmlSchemaType(name = "unsignedInt") + protected long channels; + @XmlAttribute(name = "SampleRate", required = true) + protected double sampleRate; + @XmlAttribute(name = "MeanBitrate", required = true) + protected long meanBitrate; + + /** + * Obtiene el valor de la propiedad languages. + * + * @return + * possible object is + * {@link LanguagesType } + * + */ + public LanguagesType getLanguages() { + return languages; + } + + /** + * Define el valor de la propiedad languages. + * + * @param value + * allowed object is + * {@link LanguagesType } + * + */ + public void setLanguages(LanguagesType value) { + this.languages = value; + } + + /** + * Obtiene el valor de la propiedad trackNumber. + * + */ + public long getTrackNumber() { + return trackNumber; + } + + /** + * Define el valor de la propiedad trackNumber. + * + */ + public void setTrackNumber(long value) { + this.trackNumber = value; + } + + /** + * Obtiene el valor de la propiedad accoustID. + * + * @return + * possible object is + * {@link String } + * + */ + public String getAccoustID() { + return accoustID; + } + + /** + * Define el valor de la propiedad accoustID. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setAccoustID(String value) { + this.accoustID = value; + } + + /** + * Obtiene el valor de la propiedad codec. + * + * @return + * possible object is + * {@link String } + * + */ + public String getCodec() { + return codec; + } + + /** + * Define el valor de la propiedad codec. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setCodec(String value) { + this.codec = value; + } + + /** + * Obtiene el valor de la propiedad channels. + * + */ + public long getChannels() { + return channels; + } + + /** + * Define el valor de la propiedad channels. + * + */ + public void setChannels(long value) { + this.channels = value; + } + + /** + * Obtiene el valor de la propiedad sampleRate. + * + */ + public double getSampleRate() { + return sampleRate; + } + + /** + * Define el valor de la propiedad sampleRate. + * + */ + public void setSampleRate(double value) { + this.sampleRate = value; + } + + /** + * Obtiene el valor de la propiedad meanBitrate. + * + */ + public long getMeanBitrate() { + return meanBitrate; + } + + /** + * Define el valor de la propiedad meanBitrate. + * + */ + public void setMeanBitrate(long value) { + this.meanBitrate = value; + } + +} diff --git a/CICMMetadata/java/generated/BarcodeType.java b/CICMMetadata/java/generated/BarcodeType.java new file mode 100644 index 000000000..b4c191d46 --- /dev/null +++ b/CICMMetadata/java/generated/BarcodeType.java @@ -0,0 +1,129 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + + +/** + *

Clase Java para BarcodeType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="BarcodeType">
+ *   <simpleContent>
+ *     <extension base="<http://www.w3.org/2001/XMLSchema>string">
+ *       <attribute name="type" use="required">
+ *         <simpleType>
+ *           <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ *             <enumeration value="aztec"/>
+ *             <enumeration value="codabar"/>
+ *             <enumeration value="code11"/>
+ *             <enumeration value="code128"/>
+ *             <enumeration value="code39"/>
+ *             <enumeration value="code93"/>
+ *             <enumeration value="cpcbinary"/>
+ *             <enumeration value="ezcode"/>
+ *             <enumeration value="fim"/>
+ *             <enumeration value="itf"/>
+ *             <enumeration value="itf14"/>
+ *             <enumeration value="ean13"/>
+ *             <enumeration value="ean8"/>
+ *             <enumeration value="maxicode"/>
+ *             <enumeration value="isbn"/>
+ *             <enumeration value="isrc"/>
+ *             <enumeration value="msi"/>
+ *             <enumeration value="tof"/>
+ *             <enumeration value="shotcode"/>
+ *             <enumeration value="rm4scc"/>
+ *             <enumeration value="qr"/>
+ *             <enumeration value="ean5"/>
+ *             <enumeration value="ean2"/>
+ *             <enumeration value="qr"/>
+ *             <enumeration value="postnet"/>
+ *             <enumeration value="postbar"/>
+ *             <enumeration value="plessey"/>
+ *             <enumeration value="pharmacode"/>
+ *             <enumeration value="pdf417"/>
+ *             <enumeration value="patchcode"/>
+ *           </restriction>
+ *         </simpleType>
+ *       </attribute>
+ *     </extension>
+ *   </simpleContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "BarcodeType", propOrder = { + "value" +}) +public class BarcodeType { + + @XmlValue + protected String value; + @XmlAttribute(name = "type", required = true) + protected String type; + + /** + * Obtiene el valor de la propiedad value. + * + * @return + * possible object is + * {@link String } + * + */ + public String getValue() { + return value; + } + + /** + * Define el valor de la propiedad value. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setValue(String value) { + this.value = value; + } + + /** + * Obtiene el valor de la propiedad type. + * + * @return + * possible object is + * {@link String } + * + */ + public String getType() { + return type; + } + + /** + * Define el valor de la propiedad type. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setType(String value) { + this.type = value; + } + +} diff --git a/CICMMetadata/java/generated/BarcodesType.java b/CICMMetadata/java/generated/BarcodesType.java new file mode 100644 index 000000000..0aef5f6fa --- /dev/null +++ b/CICMMetadata/java/generated/BarcodesType.java @@ -0,0 +1,78 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * Barcodes for this release + * + *

Clase Java para BarcodesType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="BarcodesType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Barcode" type="{}BarcodeType" maxOccurs="unbounded"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "BarcodesType", propOrder = { + "barcode" +}) +public class BarcodesType { + + @XmlElement(name = "Barcode", required = true) + protected List barcode; + + /** + * Gets the value of the barcode property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the barcode property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getBarcode().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link BarcodeType } + * + * + */ + public List getBarcode() { + if (barcode == null) { + barcode = new ArrayList(); + } + return this.barcode; + } + +} diff --git a/CICMMetadata/java/generated/BlockMediaType.java b/CICMMetadata/java/generated/BlockMediaType.java new file mode 100644 index 000000000..8e1ba38e5 --- /dev/null +++ b/CICMMetadata/java/generated/BlockMediaType.java @@ -0,0 +1,1051 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * Describes a dump of a block (sector) layered media + * + *

Clase Java para BlockMediaType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="BlockMediaType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Image" type="{}ImageType"/>
+ *         <element name="Size" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="Checksums" type="{}ChecksumsType"/>
+ *         <element name="ContentChecksums" type="{}ChecksumsType"/>
+ *         <element name="Sequence" type="{}SequenceType"/>
+ *         <element name="Manufacturer" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Model" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Serial" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Firmware" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Interface" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="PartNumber" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="SerialNumber" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="PhysicalBlockSize" type="{http://www.w3.org/2001/XMLSchema}unsignedInt"/>
+ *         <element name="LogicalBlockSize" type="{http://www.w3.org/2001/XMLSchema}unsignedInt"/>
+ *         <element name="LogicalBlocks" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="VariableBlockSize" type="{}VariableBlockSizeType" minOccurs="0"/>
+ *         <element name="TapeInformation" type="{}TapeInformationType" minOccurs="0"/>
+ *         <element name="Scans" type="{}ScansType" minOccurs="0"/>
+ *         <element name="ATA" type="{}ATAType" minOccurs="0"/>
+ *         <element name="PCI" type="{}PCIType" minOccurs="0"/>
+ *         <element name="PCMCIA" type="{}PCMCIAType" minOccurs="0"/>
+ *         <element name="SecureDigital" type="{}SecureDigitalType" minOccurs="0"/>
+ *         <element name="MultiMediaCard" type="{}MultiMediaCardType" minOccurs="0"/>
+ *         <element name="SCSI" type="{}SCSIType" minOccurs="0"/>
+ *         <element name="USB" type="{}USBType" minOccurs="0"/>
+ *         <element name="MAM" type="{}DumpType" minOccurs="0"/>
+ *         <element name="Heads" type="{http://www.w3.org/2001/XMLSchema}unsignedShort" minOccurs="0"/>
+ *         <element name="Cylinders" type="{http://www.w3.org/2001/XMLSchema}unsignedInt" minOccurs="0"/>
+ *         <element name="SectorsPerTrack" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" minOccurs="0"/>
+ *         <element name="Track" type="{}BlockTrackType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="CopyProtection" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Dimensions" type="{}DimensionsType"/>
+ *         <element name="FileSystemInformation" type="{}FileSystemInformationType" minOccurs="0"/>
+ *         <element name="DumpHardwareArray" type="{}DumpHardwareArrayType" minOccurs="0"/>
+ *         <element name="DiskType" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="DiskSubType" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "BlockMediaType", propOrder = { + "image", + "size", + "checksums", + "contentChecksums", + "sequence", + "manufacturer", + "model", + "serial", + "firmware", + "_interface", + "partNumber", + "serialNumber", + "physicalBlockSize", + "logicalBlockSize", + "logicalBlocks", + "variableBlockSize", + "tapeInformation", + "scans", + "ata", + "pci", + "pcmcia", + "secureDigital", + "multiMediaCard", + "scsi", + "usb", + "mam", + "heads", + "cylinders", + "sectorsPerTrack", + "track", + "copyProtection", + "dimensions", + "fileSystemInformation", + "dumpHardwareArray", + "diskType", + "diskSubType" +}) +public class BlockMediaType { + + @XmlElement(name = "Image", required = true) + protected ImageType image; + @XmlElement(name = "Size", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger size; + @XmlElement(name = "Checksums", required = true) + protected ChecksumsType checksums; + @XmlElement(name = "ContentChecksums", required = true) + protected ChecksumsType contentChecksums; + @XmlElement(name = "Sequence", required = true) + protected SequenceType sequence; + @XmlElement(name = "Manufacturer") + protected String manufacturer; + @XmlElement(name = "Model") + protected String model; + @XmlElement(name = "Serial") + protected String serial; + @XmlElement(name = "Firmware") + protected String firmware; + @XmlElement(name = "Interface") + protected String _interface; + @XmlElement(name = "PartNumber") + protected String partNumber; + @XmlElement(name = "SerialNumber") + protected String serialNumber; + @XmlElement(name = "PhysicalBlockSize") + @XmlSchemaType(name = "unsignedInt") + protected long physicalBlockSize; + @XmlElement(name = "LogicalBlockSize") + @XmlSchemaType(name = "unsignedInt") + protected long logicalBlockSize; + @XmlElement(name = "LogicalBlocks", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger logicalBlocks; + @XmlElement(name = "VariableBlockSize") + protected VariableBlockSizeType variableBlockSize; + @XmlElement(name = "TapeInformation") + protected TapeInformationType tapeInformation; + @XmlElement(name = "Scans") + protected ScansType scans; + @XmlElement(name = "ATA") + protected ATAType ata; + @XmlElement(name = "PCI") + protected PCIType pci; + @XmlElement(name = "PCMCIA") + protected PCMCIAType pcmcia; + @XmlElement(name = "SecureDigital") + protected SecureDigitalType secureDigital; + @XmlElement(name = "MultiMediaCard") + protected MultiMediaCardType multiMediaCard; + @XmlElement(name = "SCSI") + protected SCSIType scsi; + @XmlElement(name = "USB") + protected USBType usb; + @XmlElement(name = "MAM") + protected DumpType mam; + @XmlElement(name = "Heads") + @XmlSchemaType(name = "unsignedShort") + protected Integer heads; + @XmlElement(name = "Cylinders") + @XmlSchemaType(name = "unsignedInt") + protected Long cylinders; + @XmlElement(name = "SectorsPerTrack") + @XmlSchemaType(name = "unsignedLong") + protected BigInteger sectorsPerTrack; + @XmlElement(name = "Track") + protected List track; + @XmlElement(name = "CopyProtection") + protected String copyProtection; + @XmlElement(name = "Dimensions", required = true) + protected DimensionsType dimensions; + @XmlElement(name = "FileSystemInformation") + protected FileSystemInformationType fileSystemInformation; + @XmlElement(name = "DumpHardwareArray") + protected DumpHardwareArrayType dumpHardwareArray; + @XmlElement(name = "DiskType", required = true) + protected String diskType; + @XmlElement(name = "DiskSubType", required = true) + protected String diskSubType; + + /** + * Obtiene el valor de la propiedad image. + * + * @return + * possible object is + * {@link ImageType } + * + */ + public ImageType getImage() { + return image; + } + + /** + * Define el valor de la propiedad image. + * + * @param value + * allowed object is + * {@link ImageType } + * + */ + public void setImage(ImageType value) { + this.image = value; + } + + /** + * Obtiene el valor de la propiedad size. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getSize() { + return size; + } + + /** + * Define el valor de la propiedad size. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setSize(BigInteger value) { + this.size = value; + } + + /** + * Obtiene el valor de la propiedad checksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getChecksums() { + return checksums; + } + + /** + * Define el valor de la propiedad checksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setChecksums(ChecksumsType value) { + this.checksums = value; + } + + /** + * Obtiene el valor de la propiedad contentChecksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getContentChecksums() { + return contentChecksums; + } + + /** + * Define el valor de la propiedad contentChecksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setContentChecksums(ChecksumsType value) { + this.contentChecksums = value; + } + + /** + * Obtiene el valor de la propiedad sequence. + * + * @return + * possible object is + * {@link SequenceType } + * + */ + public SequenceType getSequence() { + return sequence; + } + + /** + * Define el valor de la propiedad sequence. + * + * @param value + * allowed object is + * {@link SequenceType } + * + */ + public void setSequence(SequenceType value) { + this.sequence = value; + } + + /** + * Obtiene el valor de la propiedad manufacturer. + * + * @return + * possible object is + * {@link String } + * + */ + public String getManufacturer() { + return manufacturer; + } + + /** + * Define el valor de la propiedad manufacturer. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setManufacturer(String value) { + this.manufacturer = value; + } + + /** + * Obtiene el valor de la propiedad model. + * + * @return + * possible object is + * {@link String } + * + */ + public String getModel() { + return model; + } + + /** + * Define el valor de la propiedad model. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setModel(String value) { + this.model = value; + } + + /** + * Obtiene el valor de la propiedad serial. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSerial() { + return serial; + } + + /** + * Define el valor de la propiedad serial. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSerial(String value) { + this.serial = value; + } + + /** + * Obtiene el valor de la propiedad firmware. + * + * @return + * possible object is + * {@link String } + * + */ + public String getFirmware() { + return firmware; + } + + /** + * Define el valor de la propiedad firmware. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setFirmware(String value) { + this.firmware = value; + } + + /** + * Obtiene el valor de la propiedad interface. + * + * @return + * possible object is + * {@link String } + * + */ + public String getInterface() { + return _interface; + } + + /** + * Define el valor de la propiedad interface. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setInterface(String value) { + this._interface = value; + } + + /** + * Obtiene el valor de la propiedad partNumber. + * + * @return + * possible object is + * {@link String } + * + */ + public String getPartNumber() { + return partNumber; + } + + /** + * Define el valor de la propiedad partNumber. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setPartNumber(String value) { + this.partNumber = value; + } + + /** + * Obtiene el valor de la propiedad serialNumber. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSerialNumber() { + return serialNumber; + } + + /** + * Define el valor de la propiedad serialNumber. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSerialNumber(String value) { + this.serialNumber = value; + } + + /** + * Obtiene el valor de la propiedad physicalBlockSize. + * + */ + public long getPhysicalBlockSize() { + return physicalBlockSize; + } + + /** + * Define el valor de la propiedad physicalBlockSize. + * + */ + public void setPhysicalBlockSize(long value) { + this.physicalBlockSize = value; + } + + /** + * Obtiene el valor de la propiedad logicalBlockSize. + * + */ + public long getLogicalBlockSize() { + return logicalBlockSize; + } + + /** + * Define el valor de la propiedad logicalBlockSize. + * + */ + public void setLogicalBlockSize(long value) { + this.logicalBlockSize = value; + } + + /** + * Obtiene el valor de la propiedad logicalBlocks. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getLogicalBlocks() { + return logicalBlocks; + } + + /** + * Define el valor de la propiedad logicalBlocks. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setLogicalBlocks(BigInteger value) { + this.logicalBlocks = value; + } + + /** + * Obtiene el valor de la propiedad variableBlockSize. + * + * @return + * possible object is + * {@link VariableBlockSizeType } + * + */ + public VariableBlockSizeType getVariableBlockSize() { + return variableBlockSize; + } + + /** + * Define el valor de la propiedad variableBlockSize. + * + * @param value + * allowed object is + * {@link VariableBlockSizeType } + * + */ + public void setVariableBlockSize(VariableBlockSizeType value) { + this.variableBlockSize = value; + } + + /** + * Obtiene el valor de la propiedad tapeInformation. + * + * @return + * possible object is + * {@link TapeInformationType } + * + */ + public TapeInformationType getTapeInformation() { + return tapeInformation; + } + + /** + * Define el valor de la propiedad tapeInformation. + * + * @param value + * allowed object is + * {@link TapeInformationType } + * + */ + public void setTapeInformation(TapeInformationType value) { + this.tapeInformation = value; + } + + /** + * Obtiene el valor de la propiedad scans. + * + * @return + * possible object is + * {@link ScansType } + * + */ + public ScansType getScans() { + return scans; + } + + /** + * Define el valor de la propiedad scans. + * + * @param value + * allowed object is + * {@link ScansType } + * + */ + public void setScans(ScansType value) { + this.scans = value; + } + + /** + * Obtiene el valor de la propiedad ata. + * + * @return + * possible object is + * {@link ATAType } + * + */ + public ATAType getATA() { + return ata; + } + + /** + * Define el valor de la propiedad ata. + * + * @param value + * allowed object is + * {@link ATAType } + * + */ + public void setATA(ATAType value) { + this.ata = value; + } + + /** + * Obtiene el valor de la propiedad pci. + * + * @return + * possible object is + * {@link PCIType } + * + */ + public PCIType getPCI() { + return pci; + } + + /** + * Define el valor de la propiedad pci. + * + * @param value + * allowed object is + * {@link PCIType } + * + */ + public void setPCI(PCIType value) { + this.pci = value; + } + + /** + * Obtiene el valor de la propiedad pcmcia. + * + * @return + * possible object is + * {@link PCMCIAType } + * + */ + public PCMCIAType getPCMCIA() { + return pcmcia; + } + + /** + * Define el valor de la propiedad pcmcia. + * + * @param value + * allowed object is + * {@link PCMCIAType } + * + */ + public void setPCMCIA(PCMCIAType value) { + this.pcmcia = value; + } + + /** + * Obtiene el valor de la propiedad secureDigital. + * + * @return + * possible object is + * {@link SecureDigitalType } + * + */ + public SecureDigitalType getSecureDigital() { + return secureDigital; + } + + /** + * Define el valor de la propiedad secureDigital. + * + * @param value + * allowed object is + * {@link SecureDigitalType } + * + */ + public void setSecureDigital(SecureDigitalType value) { + this.secureDigital = value; + } + + /** + * Obtiene el valor de la propiedad multiMediaCard. + * + * @return + * possible object is + * {@link MultiMediaCardType } + * + */ + public MultiMediaCardType getMultiMediaCard() { + return multiMediaCard; + } + + /** + * Define el valor de la propiedad multiMediaCard. + * + * @param value + * allowed object is + * {@link MultiMediaCardType } + * + */ + public void setMultiMediaCard(MultiMediaCardType value) { + this.multiMediaCard = value; + } + + /** + * Obtiene el valor de la propiedad scsi. + * + * @return + * possible object is + * {@link SCSIType } + * + */ + public SCSIType getSCSI() { + return scsi; + } + + /** + * Define el valor de la propiedad scsi. + * + * @param value + * allowed object is + * {@link SCSIType } + * + */ + public void setSCSI(SCSIType value) { + this.scsi = value; + } + + /** + * Obtiene el valor de la propiedad usb. + * + * @return + * possible object is + * {@link USBType } + * + */ + public USBType getUSB() { + return usb; + } + + /** + * Define el valor de la propiedad usb. + * + * @param value + * allowed object is + * {@link USBType } + * + */ + public void setUSB(USBType value) { + this.usb = value; + } + + /** + * Obtiene el valor de la propiedad mam. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getMAM() { + return mam; + } + + /** + * Define el valor de la propiedad mam. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setMAM(DumpType value) { + this.mam = value; + } + + /** + * Obtiene el valor de la propiedad heads. + * + * @return + * possible object is + * {@link Integer } + * + */ + public Integer getHeads() { + return heads; + } + + /** + * Define el valor de la propiedad heads. + * + * @param value + * allowed object is + * {@link Integer } + * + */ + public void setHeads(Integer value) { + this.heads = value; + } + + /** + * Obtiene el valor de la propiedad cylinders. + * + * @return + * possible object is + * {@link Long } + * + */ + public Long getCylinders() { + return cylinders; + } + + /** + * Define el valor de la propiedad cylinders. + * + * @param value + * allowed object is + * {@link Long } + * + */ + public void setCylinders(Long value) { + this.cylinders = value; + } + + /** + * Obtiene el valor de la propiedad sectorsPerTrack. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getSectorsPerTrack() { + return sectorsPerTrack; + } + + /** + * Define el valor de la propiedad sectorsPerTrack. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setSectorsPerTrack(BigInteger value) { + this.sectorsPerTrack = value; + } + + /** + * Gets the value of the track property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the track property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getTrack().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link BlockTrackType } + * + * + */ + public List getTrack() { + if (track == null) { + track = new ArrayList(); + } + return this.track; + } + + /** + * Obtiene el valor de la propiedad copyProtection. + * + * @return + * possible object is + * {@link String } + * + */ + public String getCopyProtection() { + return copyProtection; + } + + /** + * Define el valor de la propiedad copyProtection. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setCopyProtection(String value) { + this.copyProtection = value; + } + + /** + * Obtiene el valor de la propiedad dimensions. + * + * @return + * possible object is + * {@link DimensionsType } + * + */ + public DimensionsType getDimensions() { + return dimensions; + } + + /** + * Define el valor de la propiedad dimensions. + * + * @param value + * allowed object is + * {@link DimensionsType } + * + */ + public void setDimensions(DimensionsType value) { + this.dimensions = value; + } + + /** + * Obtiene el valor de la propiedad fileSystemInformation. + * + * @return + * possible object is + * {@link FileSystemInformationType } + * + */ + public FileSystemInformationType getFileSystemInformation() { + return fileSystemInformation; + } + + /** + * Define el valor de la propiedad fileSystemInformation. + * + * @param value + * allowed object is + * {@link FileSystemInformationType } + * + */ + public void setFileSystemInformation(FileSystemInformationType value) { + this.fileSystemInformation = value; + } + + /** + * Obtiene el valor de la propiedad dumpHardwareArray. + * + * @return + * possible object is + * {@link DumpHardwareArrayType } + * + */ + public DumpHardwareArrayType getDumpHardwareArray() { + return dumpHardwareArray; + } + + /** + * Define el valor de la propiedad dumpHardwareArray. + * + * @param value + * allowed object is + * {@link DumpHardwareArrayType } + * + */ + public void setDumpHardwareArray(DumpHardwareArrayType value) { + this.dumpHardwareArray = value; + } + + /** + * Obtiene el valor de la propiedad diskType. + * + * @return + * possible object is + * {@link String } + * + */ + public String getDiskType() { + return diskType; + } + + /** + * Define el valor de la propiedad diskType. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setDiskType(String value) { + this.diskType = value; + } + + /** + * Obtiene el valor de la propiedad diskSubType. + * + * @return + * possible object is + * {@link String } + * + */ + public String getDiskSubType() { + return diskSubType; + } + + /** + * Define el valor de la propiedad diskSubType. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setDiskSubType(String value) { + this.diskSubType = value; + } + +} diff --git a/CICMMetadata/java/generated/BlockSizeType.java b/CICMMetadata/java/generated/BlockSizeType.java new file mode 100644 index 000000000..89fd262b0 --- /dev/null +++ b/CICMMetadata/java/generated/BlockSizeType.java @@ -0,0 +1,81 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + + +/** + *

Clase Java para BlockSizeType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="BlockSizeType">
+ *   <simpleContent>
+ *     <extension base="<http://www.w3.org/2001/XMLSchema>unsignedInt">
+ *       <attribute name="startingBlock" use="required" type="{http://www.w3.org/2001/XMLSchema}unsignedInt" />
+ *     </extension>
+ *   </simpleContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "BlockSizeType", propOrder = { + "value" +}) +public class BlockSizeType { + + @XmlValue + @XmlSchemaType(name = "unsignedInt") + protected long value; + @XmlAttribute(name = "startingBlock", required = true) + @XmlSchemaType(name = "unsignedInt") + protected long startingBlock; + + /** + * Obtiene el valor de la propiedad value. + * + */ + public long getValue() { + return value; + } + + /** + * Define el valor de la propiedad value. + * + */ + public void setValue(long value) { + this.value = value; + } + + /** + * Obtiene el valor de la propiedad startingBlock. + * + */ + public long getStartingBlock() { + return startingBlock; + } + + /** + * Define el valor de la propiedad startingBlock. + * + */ + public void setStartingBlock(long value) { + this.startingBlock = value; + } + +} diff --git a/CICMMetadata/java/generated/BlockTrackType.java b/CICMMetadata/java/generated/BlockTrackType.java new file mode 100644 index 000000000..6e268133f --- /dev/null +++ b/CICMMetadata/java/generated/BlockTrackType.java @@ -0,0 +1,308 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * Information about track in non-abstracted block based media + * + *

Clase Java para BlockTrackType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="BlockTrackType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Image" type="{}ImageType"/>
+ *         <element name="Size" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="Head" type="{http://www.w3.org/2001/XMLSchema}unsignedShort"/>
+ *         <element name="Cylinder" type="{http://www.w3.org/2001/XMLSchema}unsignedInt"/>
+ *         <element name="StartSector" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="EndSector" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="Sectors" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="BytesPerSector" type="{http://www.w3.org/2001/XMLSchema}unsignedInt"/>
+ *         <element name="Checksums" type="{}ChecksumsType"/>
+ *         <element name="Format" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "BlockTrackType", propOrder = { + "image", + "size", + "head", + "cylinder", + "startSector", + "endSector", + "sectors", + "bytesPerSector", + "checksums", + "format" +}) +public class BlockTrackType { + + @XmlElement(name = "Image", required = true) + protected ImageType image; + @XmlElement(name = "Size", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger size; + @XmlElement(name = "Head") + @XmlSchemaType(name = "unsignedShort") + protected int head; + @XmlElement(name = "Cylinder") + @XmlSchemaType(name = "unsignedInt") + protected long cylinder; + @XmlElement(name = "StartSector", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger startSector; + @XmlElement(name = "EndSector", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger endSector; + @XmlElement(name = "Sectors", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger sectors; + @XmlElement(name = "BytesPerSector") + @XmlSchemaType(name = "unsignedInt") + protected long bytesPerSector; + @XmlElement(name = "Checksums", required = true) + protected ChecksumsType checksums; + @XmlElement(name = "Format") + protected String format; + + /** + * Obtiene el valor de la propiedad image. + * + * @return + * possible object is + * {@link ImageType } + * + */ + public ImageType getImage() { + return image; + } + + /** + * Define el valor de la propiedad image. + * + * @param value + * allowed object is + * {@link ImageType } + * + */ + public void setImage(ImageType value) { + this.image = value; + } + + /** + * Obtiene el valor de la propiedad size. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getSize() { + return size; + } + + /** + * Define el valor de la propiedad size. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setSize(BigInteger value) { + this.size = value; + } + + /** + * Obtiene el valor de la propiedad head. + * + */ + public int getHead() { + return head; + } + + /** + * Define el valor de la propiedad head. + * + */ + public void setHead(int value) { + this.head = value; + } + + /** + * Obtiene el valor de la propiedad cylinder. + * + */ + public long getCylinder() { + return cylinder; + } + + /** + * Define el valor de la propiedad cylinder. + * + */ + public void setCylinder(long value) { + this.cylinder = value; + } + + /** + * Obtiene el valor de la propiedad startSector. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getStartSector() { + return startSector; + } + + /** + * Define el valor de la propiedad startSector. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setStartSector(BigInteger value) { + this.startSector = value; + } + + /** + * Obtiene el valor de la propiedad endSector. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getEndSector() { + return endSector; + } + + /** + * Define el valor de la propiedad endSector. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setEndSector(BigInteger value) { + this.endSector = value; + } + + /** + * Obtiene el valor de la propiedad sectors. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getSectors() { + return sectors; + } + + /** + * Define el valor de la propiedad sectors. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setSectors(BigInteger value) { + this.sectors = value; + } + + /** + * Obtiene el valor de la propiedad bytesPerSector. + * + */ + public long getBytesPerSector() { + return bytesPerSector; + } + + /** + * Define el valor de la propiedad bytesPerSector. + * + */ + public void setBytesPerSector(long value) { + this.bytesPerSector = value; + } + + /** + * Obtiene el valor de la propiedad checksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getChecksums() { + return checksums; + } + + /** + * Define el valor de la propiedad checksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setChecksums(ChecksumsType value) { + this.checksums = value; + } + + /** + * Obtiene el valor de la propiedad format. + * + * @return + * possible object is + * {@link String } + * + */ + public String getFormat() { + return format; + } + + /** + * Define el valor de la propiedad format. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setFormat(String value) { + this.format = value; + } + +} diff --git a/CICMMetadata/java/generated/BookType.java b/CICMMetadata/java/generated/BookType.java new file mode 100644 index 000000000..556d5b9bd --- /dev/null +++ b/CICMMetadata/java/generated/BookType.java @@ -0,0 +1,325 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; +import javax.xml.datatype.XMLGregorianCalendar; + + +/** + *

Clase Java para BookType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="BookType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Barcodes" type="{}BarcodesType"/>
+ *         <element name="Cover" type="{}CoverType" minOccurs="0"/>
+ *         <element name="Name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Editorial" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Author" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="PublicationDate" type="{http://www.w3.org/2001/XMLSchema}date" minOccurs="0"/>
+ *         <element name="Language" type="{}LanguagesType" minOccurs="0"/>
+ *         <element name="Pages" type="{http://www.w3.org/2001/XMLSchema}unsignedInt" minOccurs="0"/>
+ *         <element name="PageSize" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Scan" type="{}ScanType"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "BookType", propOrder = { + "barcodes", + "cover", + "name", + "editorial", + "author", + "publicationDate", + "language", + "pages", + "pageSize", + "scan" +}) +public class BookType { + + @XmlElement(name = "Barcodes", required = true) + protected BarcodesType barcodes; + @XmlElement(name = "Cover") + protected CoverType cover; + @XmlElement(name = "Name", required = true) + protected String name; + @XmlElement(name = "Editorial") + protected String editorial; + @XmlElement(name = "Author", required = true) + protected String author; + @XmlElement(name = "PublicationDate") + @XmlSchemaType(name = "date") + protected XMLGregorianCalendar publicationDate; + @XmlElement(name = "Language") + protected LanguagesType language; + @XmlElement(name = "Pages") + @XmlSchemaType(name = "unsignedInt") + protected Long pages; + @XmlElement(name = "PageSize") + protected String pageSize; + @XmlElement(name = "Scan", required = true) + protected ScanType scan; + + /** + * Obtiene el valor de la propiedad barcodes. + * + * @return + * possible object is + * {@link BarcodesType } + * + */ + public BarcodesType getBarcodes() { + return barcodes; + } + + /** + * Define el valor de la propiedad barcodes. + * + * @param value + * allowed object is + * {@link BarcodesType } + * + */ + public void setBarcodes(BarcodesType value) { + this.barcodes = value; + } + + /** + * Obtiene el valor de la propiedad cover. + * + * @return + * possible object is + * {@link CoverType } + * + */ + public CoverType getCover() { + return cover; + } + + /** + * Define el valor de la propiedad cover. + * + * @param value + * allowed object is + * {@link CoverType } + * + */ + public void setCover(CoverType value) { + this.cover = value; + } + + /** + * Obtiene el valor de la propiedad name. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Define el valor de la propiedad name. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + /** + * Obtiene el valor de la propiedad editorial. + * + * @return + * possible object is + * {@link String } + * + */ + public String getEditorial() { + return editorial; + } + + /** + * Define el valor de la propiedad editorial. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setEditorial(String value) { + this.editorial = value; + } + + /** + * Obtiene el valor de la propiedad author. + * + * @return + * possible object is + * {@link String } + * + */ + public String getAuthor() { + return author; + } + + /** + * Define el valor de la propiedad author. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setAuthor(String value) { + this.author = value; + } + + /** + * Obtiene el valor de la propiedad publicationDate. + * + * @return + * possible object is + * {@link XMLGregorianCalendar } + * + */ + public XMLGregorianCalendar getPublicationDate() { + return publicationDate; + } + + /** + * Define el valor de la propiedad publicationDate. + * + * @param value + * allowed object is + * {@link XMLGregorianCalendar } + * + */ + public void setPublicationDate(XMLGregorianCalendar value) { + this.publicationDate = value; + } + + /** + * Obtiene el valor de la propiedad language. + * + * @return + * possible object is + * {@link LanguagesType } + * + */ + public LanguagesType getLanguage() { + return language; + } + + /** + * Define el valor de la propiedad language. + * + * @param value + * allowed object is + * {@link LanguagesType } + * + */ + public void setLanguage(LanguagesType value) { + this.language = value; + } + + /** + * Obtiene el valor de la propiedad pages. + * + * @return + * possible object is + * {@link Long } + * + */ + public Long getPages() { + return pages; + } + + /** + * Define el valor de la propiedad pages. + * + * @param value + * allowed object is + * {@link Long } + * + */ + public void setPages(Long value) { + this.pages = value; + } + + /** + * Obtiene el valor de la propiedad pageSize. + * + * @return + * possible object is + * {@link String } + * + */ + public String getPageSize() { + return pageSize; + } + + /** + * Define el valor de la propiedad pageSize. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setPageSize(String value) { + this.pageSize = value; + } + + /** + * Obtiene el valor de la propiedad scan. + * + * @return + * possible object is + * {@link ScanType } + * + */ + public ScanType getScan() { + return scan; + } + + /** + * Define el valor de la propiedad scan. + * + * @param value + * allowed object is + * {@link ScanType } + * + */ + public void setScan(ScanType value) { + this.scan = value; + } + +} diff --git a/CICMMetadata/java/generated/BorderType.java b/CICMMetadata/java/generated/BorderType.java new file mode 100644 index 000000000..8d9b45066 --- /dev/null +++ b/CICMMetadata/java/generated/BorderType.java @@ -0,0 +1,162 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para BorderType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="BorderType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Image" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Size" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="Checksums" type="{}ChecksumsType"/>
+ *       </sequence>
+ *       <attribute name="session">
+ *         <simpleType>
+ *           <restriction base="{http://www.w3.org/2001/XMLSchema}unsignedInt">
+ *             <minInclusive value="1"/>
+ *           </restriction>
+ *         </simpleType>
+ *       </attribute>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "BorderType", propOrder = { + "image", + "size", + "checksums" +}) +public class BorderType { + + @XmlElement(name = "Image", required = true) + protected String image; + @XmlElement(name = "Size", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger size; + @XmlElement(name = "Checksums", required = true) + protected ChecksumsType checksums; + @XmlAttribute(name = "session") + protected Long session; + + /** + * Obtiene el valor de la propiedad image. + * + * @return + * possible object is + * {@link String } + * + */ + public String getImage() { + return image; + } + + /** + * Define el valor de la propiedad image. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setImage(String value) { + this.image = value; + } + + /** + * Obtiene el valor de la propiedad size. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getSize() { + return size; + } + + /** + * Define el valor de la propiedad size. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setSize(BigInteger value) { + this.size = value; + } + + /** + * Obtiene el valor de la propiedad checksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getChecksums() { + return checksums; + } + + /** + * Define el valor de la propiedad checksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setChecksums(ChecksumsType value) { + this.checksums = value; + } + + /** + * Obtiene el valor de la propiedad session. + * + * @return + * possible object is + * {@link Long } + * + */ + public Long getSession() { + return session; + } + + /** + * Define el valor de la propiedad session. + * + * @param value + * allowed object is + * {@link Long } + * + */ + public void setSession(Long value) { + this.session = value; + } + +} diff --git a/CICMMetadata/java/generated/CICMMetadataType.java b/CICMMetadata/java/generated/CICMMetadataType.java new file mode 100644 index 000000000..09bf383bc --- /dev/null +++ b/CICMMetadata/java/generated/CICMMetadataType.java @@ -0,0 +1,886 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; +import javax.xml.datatype.XMLGregorianCalendar; + + +/** + * Digital Asset Metadata + * + *

Clase Java para CICMMetadataType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="CICMMetadataType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Developer" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="Publisher" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="Author" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="Performer" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="Name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Version" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="ReleaseType" minOccurs="0">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ *               <enumeration value="Retail"/>
+ *               <enumeration value="Bundle"/>
+ *               <enumeration value="Coverdisc"/>
+ *               <enumeration value="Subscription"/>
+ *               <enumeration value="Demo"/>
+ *               <enumeration value="OEM"/>
+ *               <enumeration value="Shareware"/>
+ *               <enumeration value="FOSS"/>
+ *               <enumeration value="Adware"/>
+ *               <enumeration value="Donationware"/>
+ *               <enumeration value="Digital download"/>
+ *               <enumeration value="SaaS"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *         <element name="ReleaseDate" type="{http://www.w3.org/2001/XMLSchema}date" minOccurs="0"/>
+ *         <element name="Barcodes" type="{}BarcodesType" minOccurs="0"/>
+ *         <element name="PartNumber" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="SerialNumber" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Keywords" type="{}KeywordsType" minOccurs="0"/>
+ *         <element name="Magazine" type="{}MagazineType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="Book" type="{}BookType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="Categories" type="{}CategoriesType" minOccurs="0"/>
+ *         <element name="Subcategories" type="{}SubcategoriesType" minOccurs="0"/>
+ *         <element name="Languages" type="{}LanguagesType" minOccurs="0"/>
+ *         <element name="Systems" type="{}SystemsType" minOccurs="0"/>
+ *         <element name="Architectures" type="{}ArchitecturesType" minOccurs="0"/>
+ *         <element name="RequiredOperatingSystems" type="{}RequiredOperatingSystemsType" minOccurs="0"/>
+ *         <element name="UserManual" type="{}UserManualType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="OpticalDisc" type="{}OpticalDiscType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="Advertisement" type="{}AdvertisementType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="LinearMedia" type="{}LinearMediaType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="PCICard" type="{}PCIType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="BlockMedia" type="{}BlockMediaType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="AudioMedia" type="{}AudioMediaType" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CICMMetadataType", propOrder = { + "developer", + "publisher", + "author", + "performer", + "name", + "version", + "releaseType", + "releaseDate", + "barcodes", + "partNumber", + "serialNumber", + "keywords", + "magazine", + "book", + "categories", + "subcategories", + "languages", + "systems", + "architectures", + "requiredOperatingSystems", + "userManual", + "opticalDisc", + "advertisement", + "linearMedia", + "pciCard", + "blockMedia", + "audioMedia" +}) +public class CICMMetadataType { + + @XmlElement(name = "Developer") + protected List developer; + @XmlElement(name = "Publisher") + protected List publisher; + @XmlElement(name = "Author") + protected List author; + @XmlElement(name = "Performer") + protected List performer; + @XmlElement(name = "Name", required = true) + protected String name; + @XmlElement(name = "Version") + protected String version; + @XmlElement(name = "ReleaseType") + protected String releaseType; + @XmlElement(name = "ReleaseDate") + @XmlSchemaType(name = "date") + protected XMLGregorianCalendar releaseDate; + @XmlElement(name = "Barcodes") + protected BarcodesType barcodes; + @XmlElement(name = "PartNumber") + protected String partNumber; + @XmlElement(name = "SerialNumber") + protected String serialNumber; + @XmlElement(name = "Keywords") + protected KeywordsType keywords; + @XmlElement(name = "Magazine") + protected List magazine; + @XmlElement(name = "Book") + protected List book; + @XmlElement(name = "Categories") + protected CategoriesType categories; + @XmlElement(name = "Subcategories") + protected SubcategoriesType subcategories; + @XmlElement(name = "Languages") + protected LanguagesType languages; + @XmlElement(name = "Systems") + protected SystemsType systems; + @XmlElement(name = "Architectures") + protected ArchitecturesType architectures; + @XmlElement(name = "RequiredOperatingSystems") + protected RequiredOperatingSystemsType requiredOperatingSystems; + @XmlElement(name = "UserManual") + protected List userManual; + @XmlElement(name = "OpticalDisc") + protected List opticalDisc; + @XmlElement(name = "Advertisement") + protected List advertisement; + @XmlElement(name = "LinearMedia") + protected List linearMedia; + @XmlElement(name = "PCICard") + protected List pciCard; + @XmlElement(name = "BlockMedia") + protected List blockMedia; + @XmlElement(name = "AudioMedia") + protected List audioMedia; + + /** + * Gets the value of the developer property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the developer property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getDeveloper().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link String } + * + * + */ + public List getDeveloper() { + if (developer == null) { + developer = new ArrayList(); + } + return this.developer; + } + + /** + * Gets the value of the publisher property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the publisher property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getPublisher().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link String } + * + * + */ + public List getPublisher() { + if (publisher == null) { + publisher = new ArrayList(); + } + return this.publisher; + } + + /** + * Gets the value of the author property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the author property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getAuthor().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link String } + * + * + */ + public List getAuthor() { + if (author == null) { + author = new ArrayList(); + } + return this.author; + } + + /** + * Gets the value of the performer property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the performer property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getPerformer().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link String } + * + * + */ + public List getPerformer() { + if (performer == null) { + performer = new ArrayList(); + } + return this.performer; + } + + /** + * Obtiene el valor de la propiedad name. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Define el valor de la propiedad name. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + /** + * Obtiene el valor de la propiedad version. + * + * @return + * possible object is + * {@link String } + * + */ + public String getVersion() { + return version; + } + + /** + * Define el valor de la propiedad version. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setVersion(String value) { + this.version = value; + } + + /** + * Obtiene el valor de la propiedad releaseType. + * + * @return + * possible object is + * {@link String } + * + */ + public String getReleaseType() { + return releaseType; + } + + /** + * Define el valor de la propiedad releaseType. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setReleaseType(String value) { + this.releaseType = value; + } + + /** + * Obtiene el valor de la propiedad releaseDate. + * + * @return + * possible object is + * {@link XMLGregorianCalendar } + * + */ + public XMLGregorianCalendar getReleaseDate() { + return releaseDate; + } + + /** + * Define el valor de la propiedad releaseDate. + * + * @param value + * allowed object is + * {@link XMLGregorianCalendar } + * + */ + public void setReleaseDate(XMLGregorianCalendar value) { + this.releaseDate = value; + } + + /** + * Obtiene el valor de la propiedad barcodes. + * + * @return + * possible object is + * {@link BarcodesType } + * + */ + public BarcodesType getBarcodes() { + return barcodes; + } + + /** + * Define el valor de la propiedad barcodes. + * + * @param value + * allowed object is + * {@link BarcodesType } + * + */ + public void setBarcodes(BarcodesType value) { + this.barcodes = value; + } + + /** + * Obtiene el valor de la propiedad partNumber. + * + * @return + * possible object is + * {@link String } + * + */ + public String getPartNumber() { + return partNumber; + } + + /** + * Define el valor de la propiedad partNumber. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setPartNumber(String value) { + this.partNumber = value; + } + + /** + * Obtiene el valor de la propiedad serialNumber. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSerialNumber() { + return serialNumber; + } + + /** + * Define el valor de la propiedad serialNumber. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSerialNumber(String value) { + this.serialNumber = value; + } + + /** + * Obtiene el valor de la propiedad keywords. + * + * @return + * possible object is + * {@link KeywordsType } + * + */ + public KeywordsType getKeywords() { + return keywords; + } + + /** + * Define el valor de la propiedad keywords. + * + * @param value + * allowed object is + * {@link KeywordsType } + * + */ + public void setKeywords(KeywordsType value) { + this.keywords = value; + } + + /** + * Gets the value of the magazine property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the magazine property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getMagazine().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link MagazineType } + * + * + */ + public List getMagazine() { + if (magazine == null) { + magazine = new ArrayList(); + } + return this.magazine; + } + + /** + * Gets the value of the book property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the book property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getBook().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link BookType } + * + * + */ + public List getBook() { + if (book == null) { + book = new ArrayList(); + } + return this.book; + } + + /** + * Obtiene el valor de la propiedad categories. + * + * @return + * possible object is + * {@link CategoriesType } + * + */ + public CategoriesType getCategories() { + return categories; + } + + /** + * Define el valor de la propiedad categories. + * + * @param value + * allowed object is + * {@link CategoriesType } + * + */ + public void setCategories(CategoriesType value) { + this.categories = value; + } + + /** + * Obtiene el valor de la propiedad subcategories. + * + * @return + * possible object is + * {@link SubcategoriesType } + * + */ + public SubcategoriesType getSubcategories() { + return subcategories; + } + + /** + * Define el valor de la propiedad subcategories. + * + * @param value + * allowed object is + * {@link SubcategoriesType } + * + */ + public void setSubcategories(SubcategoriesType value) { + this.subcategories = value; + } + + /** + * Obtiene el valor de la propiedad languages. + * + * @return + * possible object is + * {@link LanguagesType } + * + */ + public LanguagesType getLanguages() { + return languages; + } + + /** + * Define el valor de la propiedad languages. + * + * @param value + * allowed object is + * {@link LanguagesType } + * + */ + public void setLanguages(LanguagesType value) { + this.languages = value; + } + + /** + * Obtiene el valor de la propiedad systems. + * + * @return + * possible object is + * {@link SystemsType } + * + */ + public SystemsType getSystems() { + return systems; + } + + /** + * Define el valor de la propiedad systems. + * + * @param value + * allowed object is + * {@link SystemsType } + * + */ + public void setSystems(SystemsType value) { + this.systems = value; + } + + /** + * Obtiene el valor de la propiedad architectures. + * + * @return + * possible object is + * {@link ArchitecturesType } + * + */ + public ArchitecturesType getArchitectures() { + return architectures; + } + + /** + * Define el valor de la propiedad architectures. + * + * @param value + * allowed object is + * {@link ArchitecturesType } + * + */ + public void setArchitectures(ArchitecturesType value) { + this.architectures = value; + } + + /** + * Obtiene el valor de la propiedad requiredOperatingSystems. + * + * @return + * possible object is + * {@link RequiredOperatingSystemsType } + * + */ + public RequiredOperatingSystemsType getRequiredOperatingSystems() { + return requiredOperatingSystems; + } + + /** + * Define el valor de la propiedad requiredOperatingSystems. + * + * @param value + * allowed object is + * {@link RequiredOperatingSystemsType } + * + */ + public void setRequiredOperatingSystems(RequiredOperatingSystemsType value) { + this.requiredOperatingSystems = value; + } + + /** + * Gets the value of the userManual property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the userManual property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getUserManual().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link UserManualType } + * + * + */ + public List getUserManual() { + if (userManual == null) { + userManual = new ArrayList(); + } + return this.userManual; + } + + /** + * Gets the value of the opticalDisc property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the opticalDisc property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getOpticalDisc().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link OpticalDiscType } + * + * + */ + public List getOpticalDisc() { + if (opticalDisc == null) { + opticalDisc = new ArrayList(); + } + return this.opticalDisc; + } + + /** + * Gets the value of the advertisement property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the advertisement property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getAdvertisement().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link AdvertisementType } + * + * + */ + public List getAdvertisement() { + if (advertisement == null) { + advertisement = new ArrayList(); + } + return this.advertisement; + } + + /** + * Gets the value of the linearMedia property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the linearMedia property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getLinearMedia().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link LinearMediaType } + * + * + */ + public List getLinearMedia() { + if (linearMedia == null) { + linearMedia = new ArrayList(); + } + return this.linearMedia; + } + + /** + * Gets the value of the pciCard property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the pciCard property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getPCICard().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link PCIType } + * + * + */ + public List getPCICard() { + if (pciCard == null) { + pciCard = new ArrayList(); + } + return this.pciCard; + } + + /** + * Gets the value of the blockMedia property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the blockMedia property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getBlockMedia().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link BlockMediaType } + * + * + */ + public List getBlockMedia() { + if (blockMedia == null) { + blockMedia = new ArrayList(); + } + return this.blockMedia; + } + + /** + * Gets the value of the audioMedia property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the audioMedia property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getAudioMedia().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link AudioMediaType } + * + * + */ + public List getAudioMedia() { + if (audioMedia == null) { + audioMedia = new ArrayList(); + } + return this.audioMedia; + } + +} diff --git a/CICMMetadata/java/generated/CaseScanType.java b/CICMMetadata/java/generated/CaseScanType.java new file mode 100644 index 000000000..c982b55e8 --- /dev/null +++ b/CICMMetadata/java/generated/CaseScanType.java @@ -0,0 +1,111 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para CaseScanType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="CaseScanType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="CaseScanElement">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ *               <enumeration value="sleeve"/>
+ *               <enumeration value="inner"/>
+ *               <enumeration value="inlay"/>
+ *               <enumeration value="frontback"/>
+ *               <enumeration value="frontfull"/>
+ *               <enumeration value="boxfront"/>
+ *               <enumeration value="boxback"/>
+ *               <enumeration value="boxspine"/>
+ *               <enumeration value="external"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *         <element name="Scan" type="{}ScanType"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CaseScanType", propOrder = { + "caseScanElement", + "scan" +}) +public class CaseScanType { + + @XmlElement(name = "CaseScanElement", required = true) + protected String caseScanElement; + @XmlElement(name = "Scan", required = true) + protected ScanType scan; + + /** + * Obtiene el valor de la propiedad caseScanElement. + * + * @return + * possible object is + * {@link String } + * + */ + public String getCaseScanElement() { + return caseScanElement; + } + + /** + * Define el valor de la propiedad caseScanElement. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setCaseScanElement(String value) { + this.caseScanElement = value; + } + + /** + * Obtiene el valor de la propiedad scan. + * + * @return + * possible object is + * {@link ScanType } + * + */ + public ScanType getScan() { + return scan; + } + + /** + * Define el valor de la propiedad scan. + * + * @param value + * allowed object is + * {@link ScanType } + * + */ + public void setScan(ScanType value) { + this.scan = value; + } + +} diff --git a/CICMMetadata/java/generated/CaseType.java b/CICMMetadata/java/generated/CaseType.java new file mode 100644 index 000000000..9482fc2ed --- /dev/null +++ b/CICMMetadata/java/generated/CaseType.java @@ -0,0 +1,129 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para CaseType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="CaseType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="CaseType">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ *               <enumeration value="jewel"/>
+ *               <enumeration value="bigjewel"/>
+ *               <enumeration value="slimjewel"/>
+ *               <enumeration value="sleeve"/>
+ *               <enumeration value="qpack"/>
+ *               <enumeration value="digisleeve"/>
+ *               <enumeration value="discboxslider"/>
+ *               <enumeration value="compacplus"/>
+ *               <enumeration value="keepcase"/>
+ *               <enumeration value="snapcase"/>
+ *               <enumeration value="softcase"/>
+ *               <enumeration value="ecopack"/>
+ *               <enumeration value="liftlock"/>
+ *               <enumeration value="spindle"/>
+ *               <enumeration value="ps2case"/>
+ *               <enumeration value="ps3case"/>
+ *               <enumeration value="bluraykeepcase"/>
+ *               <enumeration value="pscase"/>
+ *               <enumeration value="dccase"/>
+ *               <enumeration value="saturncase"/>
+ *               <enumeration value="xboxcase"/>
+ *               <enumeration value="xbox360case"/>
+ *               <enumeration value="xboxonecase"/>
+ *               <enumeration value="saturnbigcase"/>
+ *               <enumeration value="gccase"/>
+ *               <enumeration value="wiicase"/>
+ *               <enumeration value="unknown"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *         <element name="Scans" type="{}ScansType"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CaseType", propOrder = { + "caseType", + "scans" +}) +public class CaseType { + + @XmlElement(name = "CaseType", required = true) + protected String caseType; + @XmlElement(name = "Scans", required = true) + protected ScansType scans; + + /** + * Obtiene el valor de la propiedad caseType. + * + * @return + * possible object is + * {@link String } + * + */ + public String getCaseType() { + return caseType; + } + + /** + * Define el valor de la propiedad caseType. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setCaseType(String value) { + this.caseType = value; + } + + /** + * Obtiene el valor de la propiedad scans. + * + * @return + * possible object is + * {@link ScansType } + * + */ + public ScansType getScans() { + return scans; + } + + /** + * Define el valor de la propiedad scans. + * + * @param value + * allowed object is + * {@link ScansType } + * + */ + public void setScans(ScansType value) { + this.scans = value; + } + +} diff --git a/CICMMetadata/java/generated/CategoriesType.java b/CICMMetadata/java/generated/CategoriesType.java new file mode 100644 index 000000000..372cbec0c --- /dev/null +++ b/CICMMetadata/java/generated/CategoriesType.java @@ -0,0 +1,76 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para CategoriesType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="CategoriesType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Category" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CategoriesType", propOrder = { + "category" +}) +public class CategoriesType { + + @XmlElement(name = "Category", required = true) + protected List category; + + /** + * Gets the value of the category property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the category property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getCategory().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link String } + * + * + */ + public List getCategory() { + if (category == null) { + category = new ArrayList(); + } + return this.category; + } + +} diff --git a/CICMMetadata/java/generated/ChecksumType.java b/CICMMetadata/java/generated/ChecksumType.java new file mode 100644 index 000000000..33d243069 --- /dev/null +++ b/CICMMetadata/java/generated/ChecksumType.java @@ -0,0 +1,125 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + + +/** + *

Clase Java para ChecksumType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="ChecksumType">
+ *   <simpleContent>
+ *     <extension base="<http://www.w3.org/2001/XMLSchema>string">
+ *       <attribute name="type" use="required">
+ *         <simpleType>
+ *           <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ *             <enumeration value="fletcher16"/>
+ *             <enumeration value="fletcher32"/>
+ *             <enumeration value="adler32"/>
+ *             <enumeration value="crc16"/>
+ *             <enumeration value="crc16ccitt"/>
+ *             <enumeration value="crc32"/>
+ *             <enumeration value="crc64"/>
+ *             <enumeration value="md4"/>
+ *             <enumeration value="md5"/>
+ *             <enumeration value="dm6"/>
+ *             <enumeration value="ripemd128"/>
+ *             <enumeration value="ripemd160"/>
+ *             <enumeration value="ripemed320"/>
+ *             <enumeration value="sha1"/>
+ *             <enumeration value="sha224"/>
+ *             <enumeration value="sha256"/>
+ *             <enumeration value="sha384"/>
+ *             <enumeration value="sha512"/>
+ *             <enumeration value="sha3"/>
+ *             <enumeration value="skein"/>
+ *             <enumeration value="snefru"/>
+ *             <enumeration value="blake256"/>
+ *             <enumeration value="blake512"/>
+ *             <enumeration value="tiger"/>
+ *             <enumeration value="whirlpool"/>
+ *             <enumeration value="spamsum"/>
+ *           </restriction>
+ *         </simpleType>
+ *       </attribute>
+ *     </extension>
+ *   </simpleContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ChecksumType", propOrder = { + "value" +}) +public class ChecksumType { + + @XmlValue + protected String value; + @XmlAttribute(name = "type", required = true) + protected String type; + + /** + * Obtiene el valor de la propiedad value. + * + * @return + * possible object is + * {@link String } + * + */ + public String getValue() { + return value; + } + + /** + * Define el valor de la propiedad value. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setValue(String value) { + this.value = value; + } + + /** + * Obtiene el valor de la propiedad type. + * + * @return + * possible object is + * {@link String } + * + */ + public String getType() { + return type; + } + + /** + * Define el valor de la propiedad type. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setType(String value) { + this.type = value; + } + +} diff --git a/CICMMetadata/java/generated/ChecksumsType.java b/CICMMetadata/java/generated/ChecksumsType.java new file mode 100644 index 000000000..328f0bf64 --- /dev/null +++ b/CICMMetadata/java/generated/ChecksumsType.java @@ -0,0 +1,78 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * Checksum of file element + * + *

Clase Java para ChecksumsType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="ChecksumsType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Checksum" type="{}ChecksumType" maxOccurs="unbounded"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ChecksumsType", propOrder = { + "checksum" +}) +public class ChecksumsType { + + @XmlElement(name = "Checksum", required = true) + protected List checksum; + + /** + * Gets the value of the checksum property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the checksum property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getChecksum().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link ChecksumType } + * + * + */ + public List getChecksum() { + if (checksum == null) { + checksum = new ArrayList(); + } + return this.checksum; + } + +} diff --git a/CICMMetadata/java/generated/ContentsFileType.java b/CICMMetadata/java/generated/ContentsFileType.java new file mode 100644 index 000000000..fb9fef915 --- /dev/null +++ b/CICMMetadata/java/generated/ContentsFileType.java @@ -0,0 +1,492 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; +import javax.xml.datatype.XMLGregorianCalendar; + + +/** + *

Clase Java para ContentsFileType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="ContentsFileType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Checksums" type="{}ChecksumsType"/>
+ *         <element name="ExtendedAttributes" type="{}ExtendedAttributesType"/>
+ *       </sequence>
+ *       <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="creationTime" type="{http://www.w3.org/2001/XMLSchema}dateTime" />
+ *       <attribute name="accessTime" type="{http://www.w3.org/2001/XMLSchema}dateTime" />
+ *       <attribute name="statusChangeTime" type="{http://www.w3.org/2001/XMLSchema}dateTime" />
+ *       <attribute name="backupTime" type="{http://www.w3.org/2001/XMLSchema}dateTime" />
+ *       <attribute name="lastWriteTime" type="{http://www.w3.org/2001/XMLSchema}dateTime" />
+ *       <attribute name="attributes" use="required" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" />
+ *       <attribute name="posixMode" type="{http://www.w3.org/2001/XMLSchema}unsignedInt" />
+ *       <attribute name="deviceNumber" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" />
+ *       <attribute name="posixGroupId" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" />
+ *       <attribute name="inode" use="required" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" />
+ *       <attribute name="links" use="required" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" />
+ *       <attribute name="posixUserId" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" />
+ *       <attribute name="length" use="required" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ContentsFileType", propOrder = { + "checksums", + "extendedAttributes" +}) +public class ContentsFileType { + + @XmlElement(name = "Checksums", required = true) + protected ChecksumsType checksums; + @XmlElement(name = "ExtendedAttributes", required = true) + protected ExtendedAttributesType extendedAttributes; + @XmlAttribute(name = "name", required = true) + protected String name; + @XmlAttribute(name = "creationTime") + @XmlSchemaType(name = "dateTime") + protected XMLGregorianCalendar creationTime; + @XmlAttribute(name = "accessTime") + @XmlSchemaType(name = "dateTime") + protected XMLGregorianCalendar accessTime; + @XmlAttribute(name = "statusChangeTime") + @XmlSchemaType(name = "dateTime") + protected XMLGregorianCalendar statusChangeTime; + @XmlAttribute(name = "backupTime") + @XmlSchemaType(name = "dateTime") + protected XMLGregorianCalendar backupTime; + @XmlAttribute(name = "lastWriteTime") + @XmlSchemaType(name = "dateTime") + protected XMLGregorianCalendar lastWriteTime; + @XmlAttribute(name = "attributes", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger attributes; + @XmlAttribute(name = "posixMode") + @XmlSchemaType(name = "unsignedInt") + protected Long posixMode; + @XmlAttribute(name = "deviceNumber") + @XmlSchemaType(name = "unsignedLong") + protected BigInteger deviceNumber; + @XmlAttribute(name = "posixGroupId") + @XmlSchemaType(name = "unsignedLong") + protected BigInteger posixGroupId; + @XmlAttribute(name = "inode", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger inode; + @XmlAttribute(name = "links", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger links; + @XmlAttribute(name = "posixUserId") + @XmlSchemaType(name = "unsignedLong") + protected BigInteger posixUserId; + @XmlAttribute(name = "length", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger length; + + /** + * Obtiene el valor de la propiedad checksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getChecksums() { + return checksums; + } + + /** + * Define el valor de la propiedad checksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setChecksums(ChecksumsType value) { + this.checksums = value; + } + + /** + * Obtiene el valor de la propiedad extendedAttributes. + * + * @return + * possible object is + * {@link ExtendedAttributesType } + * + */ + public ExtendedAttributesType getExtendedAttributes() { + return extendedAttributes; + } + + /** + * Define el valor de la propiedad extendedAttributes. + * + * @param value + * allowed object is + * {@link ExtendedAttributesType } + * + */ + public void setExtendedAttributes(ExtendedAttributesType value) { + this.extendedAttributes = value; + } + + /** + * Obtiene el valor de la propiedad name. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Define el valor de la propiedad name. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + /** + * Obtiene el valor de la propiedad creationTime. + * + * @return + * possible object is + * {@link XMLGregorianCalendar } + * + */ + public XMLGregorianCalendar getCreationTime() { + return creationTime; + } + + /** + * Define el valor de la propiedad creationTime. + * + * @param value + * allowed object is + * {@link XMLGregorianCalendar } + * + */ + public void setCreationTime(XMLGregorianCalendar value) { + this.creationTime = value; + } + + /** + * Obtiene el valor de la propiedad accessTime. + * + * @return + * possible object is + * {@link XMLGregorianCalendar } + * + */ + public XMLGregorianCalendar getAccessTime() { + return accessTime; + } + + /** + * Define el valor de la propiedad accessTime. + * + * @param value + * allowed object is + * {@link XMLGregorianCalendar } + * + */ + public void setAccessTime(XMLGregorianCalendar value) { + this.accessTime = value; + } + + /** + * Obtiene el valor de la propiedad statusChangeTime. + * + * @return + * possible object is + * {@link XMLGregorianCalendar } + * + */ + public XMLGregorianCalendar getStatusChangeTime() { + return statusChangeTime; + } + + /** + * Define el valor de la propiedad statusChangeTime. + * + * @param value + * allowed object is + * {@link XMLGregorianCalendar } + * + */ + public void setStatusChangeTime(XMLGregorianCalendar value) { + this.statusChangeTime = value; + } + + /** + * Obtiene el valor de la propiedad backupTime. + * + * @return + * possible object is + * {@link XMLGregorianCalendar } + * + */ + public XMLGregorianCalendar getBackupTime() { + return backupTime; + } + + /** + * Define el valor de la propiedad backupTime. + * + * @param value + * allowed object is + * {@link XMLGregorianCalendar } + * + */ + public void setBackupTime(XMLGregorianCalendar value) { + this.backupTime = value; + } + + /** + * Obtiene el valor de la propiedad lastWriteTime. + * + * @return + * possible object is + * {@link XMLGregorianCalendar } + * + */ + public XMLGregorianCalendar getLastWriteTime() { + return lastWriteTime; + } + + /** + * Define el valor de la propiedad lastWriteTime. + * + * @param value + * allowed object is + * {@link XMLGregorianCalendar } + * + */ + public void setLastWriteTime(XMLGregorianCalendar value) { + this.lastWriteTime = value; + } + + /** + * Obtiene el valor de la propiedad attributes. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getAttributes() { + return attributes; + } + + /** + * Define el valor de la propiedad attributes. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setAttributes(BigInteger value) { + this.attributes = value; + } + + /** + * Obtiene el valor de la propiedad posixMode. + * + * @return + * possible object is + * {@link Long } + * + */ + public Long getPosixMode() { + return posixMode; + } + + /** + * Define el valor de la propiedad posixMode. + * + * @param value + * allowed object is + * {@link Long } + * + */ + public void setPosixMode(Long value) { + this.posixMode = value; + } + + /** + * Obtiene el valor de la propiedad deviceNumber. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getDeviceNumber() { + return deviceNumber; + } + + /** + * Define el valor de la propiedad deviceNumber. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setDeviceNumber(BigInteger value) { + this.deviceNumber = value; + } + + /** + * Obtiene el valor de la propiedad posixGroupId. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getPosixGroupId() { + return posixGroupId; + } + + /** + * Define el valor de la propiedad posixGroupId. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setPosixGroupId(BigInteger value) { + this.posixGroupId = value; + } + + /** + * Obtiene el valor de la propiedad inode. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getInode() { + return inode; + } + + /** + * Define el valor de la propiedad inode. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setInode(BigInteger value) { + this.inode = value; + } + + /** + * Obtiene el valor de la propiedad links. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getLinks() { + return links; + } + + /** + * Define el valor de la propiedad links. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setLinks(BigInteger value) { + this.links = value; + } + + /** + * Obtiene el valor de la propiedad posixUserId. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getPosixUserId() { + return posixUserId; + } + + /** + * Define el valor de la propiedad posixUserId. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setPosixUserId(BigInteger value) { + this.posixUserId = value; + } + + /** + * Obtiene el valor de la propiedad length. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getLength() { + return length; + } + + /** + * Define el valor de la propiedad length. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setLength(BigInteger value) { + this.length = value; + } + +} diff --git a/CICMMetadata/java/generated/CoordinatesType.java b/CICMMetadata/java/generated/CoordinatesType.java new file mode 100644 index 000000000..39fd6eac3 --- /dev/null +++ b/CICMMetadata/java/generated/CoordinatesType.java @@ -0,0 +1,81 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para CoordinatesType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="CoordinatesType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Latitude" type="{http://www.w3.org/2001/XMLSchema}double"/>
+ *         <element name="Longitude" type="{http://www.w3.org/2001/XMLSchema}double"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CoordinatesType", propOrder = { + "latitude", + "longitude" +}) +public class CoordinatesType { + + @XmlElement(name = "Latitude") + protected double latitude; + @XmlElement(name = "Longitude") + protected double longitude; + + /** + * Obtiene el valor de la propiedad latitude. + * + */ + public double getLatitude() { + return latitude; + } + + /** + * Define el valor de la propiedad latitude. + * + */ + public void setLatitude(double value) { + this.latitude = value; + } + + /** + * Obtiene el valor de la propiedad longitude. + * + */ + public double getLongitude() { + return longitude; + } + + /** + * Define el valor de la propiedad longitude. + * + */ + public void setLongitude(double value) { + this.longitude = value; + } + +} diff --git a/CICMMetadata/java/generated/CoverType.java b/CICMMetadata/java/generated/CoverType.java new file mode 100644 index 000000000..f3923db60 --- /dev/null +++ b/CICMMetadata/java/generated/CoverType.java @@ -0,0 +1,123 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para CoverType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="CoverType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="File" type="{}FileType"/>
+ *         <element name="Checksums" type="{}ChecksumsType"/>
+ *         <element name="Thumbnail" type="{http://www.w3.org/2001/XMLSchema}base64Binary"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "CoverType", propOrder = { + "file", + "checksums", + "thumbnail" +}) +public class CoverType { + + @XmlElement(name = "File", required = true) + protected FileType file; + @XmlElement(name = "Checksums", required = true) + protected ChecksumsType checksums; + @XmlElement(name = "Thumbnail", required = true) + protected byte[] thumbnail; + + /** + * Obtiene el valor de la propiedad file. + * + * @return + * possible object is + * {@link FileType } + * + */ + public FileType getFile() { + return file; + } + + /** + * Define el valor de la propiedad file. + * + * @param value + * allowed object is + * {@link FileType } + * + */ + public void setFile(FileType value) { + this.file = value; + } + + /** + * Obtiene el valor de la propiedad checksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getChecksums() { + return checksums; + } + + /** + * Define el valor de la propiedad checksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setChecksums(ChecksumsType value) { + this.checksums = value; + } + + /** + * Obtiene el valor de la propiedad thumbnail. + * + * @return + * possible object is + * byte[] + */ + public byte[] getThumbnail() { + return thumbnail; + } + + /** + * Define el valor de la propiedad thumbnail. + * + * @param value + * allowed object is + * byte[] + */ + public void setThumbnail(byte[] value) { + this.thumbnail = value; + } + +} diff --git a/CICMMetadata/java/generated/DimensionsType.java b/CICMMetadata/java/generated/DimensionsType.java new file mode 100644 index 000000000..dd020b6f7 --- /dev/null +++ b/CICMMetadata/java/generated/DimensionsType.java @@ -0,0 +1,147 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * Dimensions of media + * + *

Clase Java para DimensionsType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="DimensionsType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Diameter" type="{http://www.w3.org/2001/XMLSchema}double" minOccurs="0"/>
+ *         <element name="Height" type="{http://www.w3.org/2001/XMLSchema}double" minOccurs="0"/>
+ *         <element name="Width" type="{http://www.w3.org/2001/XMLSchema}double" minOccurs="0"/>
+ *         <element name="Thickness" type="{http://www.w3.org/2001/XMLSchema}double"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "DimensionsType", propOrder = { + "diameter", + "height", + "width", + "thickness" +}) +public class DimensionsType { + + @XmlElement(name = "Diameter") + protected Double diameter; + @XmlElement(name = "Height") + protected Double height; + @XmlElement(name = "Width") + protected Double width; + @XmlElement(name = "Thickness") + protected double thickness; + + /** + * Obtiene el valor de la propiedad diameter. + * + * @return + * possible object is + * {@link Double } + * + */ + public Double getDiameter() { + return diameter; + } + + /** + * Define el valor de la propiedad diameter. + * + * @param value + * allowed object is + * {@link Double } + * + */ + public void setDiameter(Double value) { + this.diameter = value; + } + + /** + * Obtiene el valor de la propiedad height. + * + * @return + * possible object is + * {@link Double } + * + */ + public Double getHeight() { + return height; + } + + /** + * Define el valor de la propiedad height. + * + * @param value + * allowed object is + * {@link Double } + * + */ + public void setHeight(Double value) { + this.height = value; + } + + /** + * Obtiene el valor de la propiedad width. + * + * @return + * possible object is + * {@link Double } + * + */ + public Double getWidth() { + return width; + } + + /** + * Define el valor de la propiedad width. + * + * @param value + * allowed object is + * {@link Double } + * + */ + public void setWidth(Double value) { + this.width = value; + } + + /** + * Obtiene el valor de la propiedad thickness. + * + */ + public double getThickness() { + return thickness; + } + + /** + * Define el valor de la propiedad thickness. + * + */ + public void setThickness(double value) { + this.thickness = value; + } + +} diff --git a/CICMMetadata/java/generated/DirectoryType.java b/CICMMetadata/java/generated/DirectoryType.java new file mode 100644 index 000000000..ec3e43231 --- /dev/null +++ b/CICMMetadata/java/generated/DirectoryType.java @@ -0,0 +1,476 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; +import javax.xml.datatype.XMLGregorianCalendar; + + +/** + *

Clase Java para DirectoryType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="DirectoryType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="File" type="{}ContentsFileType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="Directory" type="{}DirectoryType" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *       <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="creationTime" type="{http://www.w3.org/2001/XMLSchema}dateTime" />
+ *       <attribute name="accessTime" type="{http://www.w3.org/2001/XMLSchema}dateTime" />
+ *       <attribute name="statusChangeTime" type="{http://www.w3.org/2001/XMLSchema}dateTime" />
+ *       <attribute name="backupTime" type="{http://www.w3.org/2001/XMLSchema}dateTime" />
+ *       <attribute name="lastWriteTime" type="{http://www.w3.org/2001/XMLSchema}dateTime" />
+ *       <attribute name="attributes" use="required" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" />
+ *       <attribute name="posixMode" type="{http://www.w3.org/2001/XMLSchema}unsignedInt" />
+ *       <attribute name="deviceNumber" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" />
+ *       <attribute name="posixGroupId" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" />
+ *       <attribute name="inode" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" />
+ *       <attribute name="links" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" />
+ *       <attribute name="posixUserId" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "DirectoryType", propOrder = { + "file", + "directory" +}) +public class DirectoryType { + + @XmlElement(name = "File") + protected List file; + @XmlElement(name = "Directory") + protected List directory; + @XmlAttribute(name = "name", required = true) + protected String name; + @XmlAttribute(name = "creationTime") + @XmlSchemaType(name = "dateTime") + protected XMLGregorianCalendar creationTime; + @XmlAttribute(name = "accessTime") + @XmlSchemaType(name = "dateTime") + protected XMLGregorianCalendar accessTime; + @XmlAttribute(name = "statusChangeTime") + @XmlSchemaType(name = "dateTime") + protected XMLGregorianCalendar statusChangeTime; + @XmlAttribute(name = "backupTime") + @XmlSchemaType(name = "dateTime") + protected XMLGregorianCalendar backupTime; + @XmlAttribute(name = "lastWriteTime") + @XmlSchemaType(name = "dateTime") + protected XMLGregorianCalendar lastWriteTime; + @XmlAttribute(name = "attributes", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger attributes; + @XmlAttribute(name = "posixMode") + @XmlSchemaType(name = "unsignedInt") + protected Long posixMode; + @XmlAttribute(name = "deviceNumber") + @XmlSchemaType(name = "unsignedLong") + protected BigInteger deviceNumber; + @XmlAttribute(name = "posixGroupId") + @XmlSchemaType(name = "unsignedLong") + protected BigInteger posixGroupId; + @XmlAttribute(name = "inode") + @XmlSchemaType(name = "unsignedLong") + protected BigInteger inode; + @XmlAttribute(name = "links") + @XmlSchemaType(name = "unsignedLong") + protected BigInteger links; + @XmlAttribute(name = "posixUserId") + @XmlSchemaType(name = "unsignedLong") + protected BigInteger posixUserId; + + /** + * Gets the value of the file property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the file property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getFile().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link ContentsFileType } + * + * + */ + public List getFile() { + if (file == null) { + file = new ArrayList(); + } + return this.file; + } + + /** + * Gets the value of the directory property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the directory property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getDirectory().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link DirectoryType } + * + * + */ + public List getDirectory() { + if (directory == null) { + directory = new ArrayList(); + } + return this.directory; + } + + /** + * Obtiene el valor de la propiedad name. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Define el valor de la propiedad name. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + /** + * Obtiene el valor de la propiedad creationTime. + * + * @return + * possible object is + * {@link XMLGregorianCalendar } + * + */ + public XMLGregorianCalendar getCreationTime() { + return creationTime; + } + + /** + * Define el valor de la propiedad creationTime. + * + * @param value + * allowed object is + * {@link XMLGregorianCalendar } + * + */ + public void setCreationTime(XMLGregorianCalendar value) { + this.creationTime = value; + } + + /** + * Obtiene el valor de la propiedad accessTime. + * + * @return + * possible object is + * {@link XMLGregorianCalendar } + * + */ + public XMLGregorianCalendar getAccessTime() { + return accessTime; + } + + /** + * Define el valor de la propiedad accessTime. + * + * @param value + * allowed object is + * {@link XMLGregorianCalendar } + * + */ + public void setAccessTime(XMLGregorianCalendar value) { + this.accessTime = value; + } + + /** + * Obtiene el valor de la propiedad statusChangeTime. + * + * @return + * possible object is + * {@link XMLGregorianCalendar } + * + */ + public XMLGregorianCalendar getStatusChangeTime() { + return statusChangeTime; + } + + /** + * Define el valor de la propiedad statusChangeTime. + * + * @param value + * allowed object is + * {@link XMLGregorianCalendar } + * + */ + public void setStatusChangeTime(XMLGregorianCalendar value) { + this.statusChangeTime = value; + } + + /** + * Obtiene el valor de la propiedad backupTime. + * + * @return + * possible object is + * {@link XMLGregorianCalendar } + * + */ + public XMLGregorianCalendar getBackupTime() { + return backupTime; + } + + /** + * Define el valor de la propiedad backupTime. + * + * @param value + * allowed object is + * {@link XMLGregorianCalendar } + * + */ + public void setBackupTime(XMLGregorianCalendar value) { + this.backupTime = value; + } + + /** + * Obtiene el valor de la propiedad lastWriteTime. + * + * @return + * possible object is + * {@link XMLGregorianCalendar } + * + */ + public XMLGregorianCalendar getLastWriteTime() { + return lastWriteTime; + } + + /** + * Define el valor de la propiedad lastWriteTime. + * + * @param value + * allowed object is + * {@link XMLGregorianCalendar } + * + */ + public void setLastWriteTime(XMLGregorianCalendar value) { + this.lastWriteTime = value; + } + + /** + * Obtiene el valor de la propiedad attributes. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getAttributes() { + return attributes; + } + + /** + * Define el valor de la propiedad attributes. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setAttributes(BigInteger value) { + this.attributes = value; + } + + /** + * Obtiene el valor de la propiedad posixMode. + * + * @return + * possible object is + * {@link Long } + * + */ + public Long getPosixMode() { + return posixMode; + } + + /** + * Define el valor de la propiedad posixMode. + * + * @param value + * allowed object is + * {@link Long } + * + */ + public void setPosixMode(Long value) { + this.posixMode = value; + } + + /** + * Obtiene el valor de la propiedad deviceNumber. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getDeviceNumber() { + return deviceNumber; + } + + /** + * Define el valor de la propiedad deviceNumber. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setDeviceNumber(BigInteger value) { + this.deviceNumber = value; + } + + /** + * Obtiene el valor de la propiedad posixGroupId. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getPosixGroupId() { + return posixGroupId; + } + + /** + * Define el valor de la propiedad posixGroupId. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setPosixGroupId(BigInteger value) { + this.posixGroupId = value; + } + + /** + * Obtiene el valor de la propiedad inode. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getInode() { + return inode; + } + + /** + * Define el valor de la propiedad inode. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setInode(BigInteger value) { + this.inode = value; + } + + /** + * Obtiene el valor de la propiedad links. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getLinks() { + return links; + } + + /** + * Define el valor de la propiedad links. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setLinks(BigInteger value) { + this.links = value; + } + + /** + * Obtiene el valor de la propiedad posixUserId. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getPosixUserId() { + return posixUserId; + } + + /** + * Define el valor de la propiedad posixUserId. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setPosixUserId(BigInteger value) { + this.posixUserId = value; + } + +} diff --git a/CICMMetadata/java/generated/DiscScanType.java b/CICMMetadata/java/generated/DiscScanType.java new file mode 100644 index 000000000..ba8ab06f7 --- /dev/null +++ b/CICMMetadata/java/generated/DiscScanType.java @@ -0,0 +1,108 @@ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2015.11.07 at 05:27:06 AM WET +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for DiscScanType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="DiscScanType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="DiscScanElement">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ *               <enumeration value="up"/>
+ *               <enumeration value="down"/>
+ *               <enumeration value="front"/>
+ *               <enumeration value="back"/>
+ *               <enumeration value="left"/>
+ *               <enumeration value="right"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *         <element name="Scan" type="{}ScanType"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "DiscScanType", propOrder = { + "discScanElement", + "scan" +}) +public class DiscScanType { + + @XmlElement(name = "DiscScanElement", required = true) + protected String discScanElement; + @XmlElement(name = "Scan", required = true) + protected ScanType scan; + + /** + * Gets the value of the discScanElement property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getDiscScanElement() { + return discScanElement; + } + + /** + * Sets the value of the discScanElement property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setDiscScanElement(String value) { + this.discScanElement = value; + } + + /** + * Gets the value of the scan property. + * + * @return + * possible object is + * {@link ScanType } + * + */ + public ScanType getScan() { + return scan; + } + + /** + * Sets the value of the scan property. + * + * @param value + * allowed object is + * {@link ScanType } + * + */ + public void setScan(ScanType value) { + this.scan = value; + } + +} diff --git a/CICMMetadata/java/generated/DumpHardwareArrayType.java b/CICMMetadata/java/generated/DumpHardwareArrayType.java new file mode 100644 index 000000000..de9565bcd --- /dev/null +++ b/CICMMetadata/java/generated/DumpHardwareArrayType.java @@ -0,0 +1,78 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * Array of drives information + * + *

Clase Java para DumpHardwareArrayType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="DumpHardwareArrayType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="DumpHardware" type="{}DumpHardwareType" maxOccurs="unbounded"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "DumpHardwareArrayType", propOrder = { + "dumpHardware" +}) +public class DumpHardwareArrayType { + + @XmlElement(name = "DumpHardware", required = true) + protected List dumpHardware; + + /** + * Gets the value of the dumpHardware property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the dumpHardware property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getDumpHardware().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link DumpHardwareType } + * + * + */ + public List getDumpHardware() { + if (dumpHardware == null) { + dumpHardware = new ArrayList(); + } + return this.dumpHardware; + } + +} diff --git a/CICMMetadata/java/generated/DumpHardwareType.java b/CICMMetadata/java/generated/DumpHardwareType.java new file mode 100644 index 000000000..4c37cb164 --- /dev/null +++ b/CICMMetadata/java/generated/DumpHardwareType.java @@ -0,0 +1,237 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para DumpHardwareType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="DumpHardwareType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Manufacturer" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Model" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Revision" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Firmware" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Serial" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Extents" type="{}ExtentsType"/>
+ *         <element name="Software" type="{}SoftwareType"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "DumpHardwareType", propOrder = { + "manufacturer", + "model", + "revision", + "firmware", + "serial", + "extents", + "software" +}) +public class DumpHardwareType { + + @XmlElement(name = "Manufacturer", required = true) + protected String manufacturer; + @XmlElement(name = "Model", required = true) + protected String model; + @XmlElement(name = "Revision", required = true) + protected String revision; + @XmlElement(name = "Firmware", required = true) + protected String firmware; + @XmlElement(name = "Serial", required = true) + protected String serial; + @XmlElement(name = "Extents", required = true) + protected ExtentsType extents; + @XmlElement(name = "Software", required = true) + protected SoftwareType software; + + /** + * Obtiene el valor de la propiedad manufacturer. + * + * @return + * possible object is + * {@link String } + * + */ + public String getManufacturer() { + return manufacturer; + } + + /** + * Define el valor de la propiedad manufacturer. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setManufacturer(String value) { + this.manufacturer = value; + } + + /** + * Obtiene el valor de la propiedad model. + * + * @return + * possible object is + * {@link String } + * + */ + public String getModel() { + return model; + } + + /** + * Define el valor de la propiedad model. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setModel(String value) { + this.model = value; + } + + /** + * Obtiene el valor de la propiedad revision. + * + * @return + * possible object is + * {@link String } + * + */ + public String getRevision() { + return revision; + } + + /** + * Define el valor de la propiedad revision. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setRevision(String value) { + this.revision = value; + } + + /** + * Obtiene el valor de la propiedad firmware. + * + * @return + * possible object is + * {@link String } + * + */ + public String getFirmware() { + return firmware; + } + + /** + * Define el valor de la propiedad firmware. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setFirmware(String value) { + this.firmware = value; + } + + /** + * Obtiene el valor de la propiedad serial. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSerial() { + return serial; + } + + /** + * Define el valor de la propiedad serial. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSerial(String value) { + this.serial = value; + } + + /** + * Obtiene el valor de la propiedad extents. + * + * @return + * possible object is + * {@link ExtentsType } + * + */ + public ExtentsType getExtents() { + return extents; + } + + /** + * Define el valor de la propiedad extents. + * + * @param value + * allowed object is + * {@link ExtentsType } + * + */ + public void setExtents(ExtentsType value) { + this.extents = value; + } + + /** + * Obtiene el valor de la propiedad software. + * + * @return + * possible object is + * {@link SoftwareType } + * + */ + public SoftwareType getSoftware() { + return software; + } + + /** + * Define el valor de la propiedad software. + * + * @param value + * allowed object is + * {@link SoftwareType } + * + */ + public void setSoftware(SoftwareType value) { + this.software = value; + } + +} diff --git a/CICMMetadata/java/generated/DumpType.java b/CICMMetadata/java/generated/DumpType.java new file mode 100644 index 000000000..749bf9a7a --- /dev/null +++ b/CICMMetadata/java/generated/DumpType.java @@ -0,0 +1,131 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * Information about dumped structure + * + * + *

Clase Java para DumpType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="DumpType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Image" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Size" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="Checksums" type="{}ChecksumsType"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "DumpType", propOrder = { + "image", + "size", + "checksums" +}) +public class DumpType { + + @XmlElement(name = "Image", required = true) + protected String image; + @XmlElement(name = "Size", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger size; + @XmlElement(name = "Checksums", required = true) + protected ChecksumsType checksums; + + /** + * Obtiene el valor de la propiedad image. + * + * @return + * possible object is + * {@link String } + * + */ + public String getImage() { + return image; + } + + /** + * Define el valor de la propiedad image. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setImage(String value) { + this.image = value; + } + + /** + * Obtiene el valor de la propiedad size. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getSize() { + return size; + } + + /** + * Define el valor de la propiedad size. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setSize(BigInteger value) { + this.size = value; + } + + /** + * Obtiene el valor de la propiedad checksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getChecksums() { + return checksums; + } + + /** + * Define el valor de la propiedad checksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setChecksums(ChecksumsType value) { + this.checksums = value; + } + +} diff --git a/CICMMetadata/java/generated/EVPDType.java b/CICMMetadata/java/generated/EVPDType.java new file mode 100644 index 000000000..901ece198 --- /dev/null +++ b/CICMMetadata/java/generated/EVPDType.java @@ -0,0 +1,163 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para EVPDType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="EVPDType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Image" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Size" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="Checksums" type="{}ChecksumsType"/>
+ *       </sequence>
+ *       <attribute name="page">
+ *         <simpleType>
+ *           <restriction base="{http://www.w3.org/2001/XMLSchema}unsignedByte">
+ *             <minInclusive value="1"/>
+ *             <maxInclusive value="255"/>
+ *           </restriction>
+ *         </simpleType>
+ *       </attribute>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "EVPDType", propOrder = { + "image", + "size", + "checksums" +}) +public class EVPDType { + + @XmlElement(name = "Image", required = true) + protected String image; + @XmlElement(name = "Size", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger size; + @XmlElement(name = "Checksums", required = true) + protected ChecksumsType checksums; + @XmlAttribute(name = "page") + protected Short page; + + /** + * Obtiene el valor de la propiedad image. + * + * @return + * possible object is + * {@link String } + * + */ + public String getImage() { + return image; + } + + /** + * Define el valor de la propiedad image. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setImage(String value) { + this.image = value; + } + + /** + * Obtiene el valor de la propiedad size. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getSize() { + return size; + } + + /** + * Define el valor de la propiedad size. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setSize(BigInteger value) { + this.size = value; + } + + /** + * Obtiene el valor de la propiedad checksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getChecksums() { + return checksums; + } + + /** + * Define el valor de la propiedad checksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setChecksums(ChecksumsType value) { + this.checksums = value; + } + + /** + * Obtiene el valor de la propiedad page. + * + * @return + * possible object is + * {@link Short } + * + */ + public Short getPage() { + return page; + } + + /** + * Define el valor de la propiedad page. + * + * @param value + * allowed object is + * {@link Short } + * + */ + public void setPage(Short value) { + this.page = value; + } + +} diff --git a/CICMMetadata/java/generated/ExtendedAttributeType.java b/CICMMetadata/java/generated/ExtendedAttributeType.java new file mode 100644 index 000000000..a7c441fa7 --- /dev/null +++ b/CICMMetadata/java/generated/ExtendedAttributeType.java @@ -0,0 +1,127 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para ExtendedAttributeType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="ExtendedAttributeType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Checksums" type="{}ChecksumsType"/>
+ *       </sequence>
+ *       <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="length" use="required" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ExtendedAttributeType", propOrder = { + "checksums" +}) +public class ExtendedAttributeType { + + @XmlElement(name = "Checksums", required = true) + protected ChecksumsType checksums; + @XmlAttribute(name = "name", required = true) + protected String name; + @XmlAttribute(name = "length", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger length; + + /** + * Obtiene el valor de la propiedad checksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getChecksums() { + return checksums; + } + + /** + * Define el valor de la propiedad checksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setChecksums(ChecksumsType value) { + this.checksums = value; + } + + /** + * Obtiene el valor de la propiedad name. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Define el valor de la propiedad name. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + /** + * Obtiene el valor de la propiedad length. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getLength() { + return length; + } + + /** + * Define el valor de la propiedad length. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setLength(BigInteger value) { + this.length = value; + } + +} diff --git a/CICMMetadata/java/generated/ExtendedAttributesType.java b/CICMMetadata/java/generated/ExtendedAttributesType.java new file mode 100644 index 000000000..b4f48ddbd --- /dev/null +++ b/CICMMetadata/java/generated/ExtendedAttributesType.java @@ -0,0 +1,76 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para ExtendedAttributesType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="ExtendedAttributesType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="ExtendedAttribute" type="{}ExtendedAttributeType" maxOccurs="unbounded"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ExtendedAttributesType", propOrder = { + "extendedAttribute" +}) +public class ExtendedAttributesType { + + @XmlElement(name = "ExtendedAttribute", required = true) + protected List extendedAttribute; + + /** + * Gets the value of the extendedAttribute property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the extendedAttribute property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getExtendedAttribute().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link ExtendedAttributeType } + * + * + */ + public List getExtendedAttribute() { + if (extendedAttribute == null) { + extendedAttribute = new ArrayList(); + } + return this.extendedAttribute; + } + +} diff --git a/CICMMetadata/java/generated/ExtentType.java b/CICMMetadata/java/generated/ExtentType.java new file mode 100644 index 000000000..21860e4d2 --- /dev/null +++ b/CICMMetadata/java/generated/ExtentType.java @@ -0,0 +1,101 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para ExtentType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="ExtentType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Start" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="End" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ExtentType", propOrder = { + "start", + "end" +}) +public class ExtentType { + + @XmlElement(name = "Start", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger start; + @XmlElement(name = "End", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger end; + + /** + * Obtiene el valor de la propiedad start. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getStart() { + return start; + } + + /** + * Define el valor de la propiedad start. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setStart(BigInteger value) { + this.start = value; + } + + /** + * Obtiene el valor de la propiedad end. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getEnd() { + return end; + } + + /** + * Define el valor de la propiedad end. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setEnd(BigInteger value) { + this.end = value; + } + +} diff --git a/CICMMetadata/java/generated/ExtentsType.java b/CICMMetadata/java/generated/ExtentsType.java new file mode 100644 index 000000000..ab5d4ee74 --- /dev/null +++ b/CICMMetadata/java/generated/ExtentsType.java @@ -0,0 +1,76 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para ExtentsType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="ExtentsType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Extent" type="{}ExtentType" maxOccurs="unbounded"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ExtentsType", propOrder = { + "extent" +}) +public class ExtentsType { + + @XmlElement(name = "Extent", required = true) + protected List extent; + + /** + * Gets the value of the extent property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the extent property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getExtent().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link ExtentType } + * + * + */ + public List getExtent() { + if (extent == null) { + extent = new ArrayList(); + } + return this.extent; + } + +} diff --git a/CICMMetadata/java/generated/FileSystemInformationType.java b/CICMMetadata/java/generated/FileSystemInformationType.java new file mode 100644 index 000000000..1df2c74ae --- /dev/null +++ b/CICMMetadata/java/generated/FileSystemInformationType.java @@ -0,0 +1,76 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para FileSystemInformationType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="FileSystemInformationType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Partition" type="{}PartitionType" maxOccurs="unbounded"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "FileSystemInformationType", propOrder = { + "partition" +}) +public class FileSystemInformationType { + + @XmlElement(name = "Partition", required = true) + protected List partition; + + /** + * Gets the value of the partition property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the partition property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getPartition().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link PartitionType } + * + * + */ + public List getPartition() { + if (partition == null) { + partition = new ArrayList(); + } + return this.partition; + } + +} diff --git a/CICMMetadata/java/generated/FileSystemType.java b/CICMMetadata/java/generated/FileSystemType.java new file mode 100644 index 000000000..bf7fa7074 --- /dev/null +++ b/CICMMetadata/java/generated/FileSystemType.java @@ -0,0 +1,591 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; +import javax.xml.datatype.XMLGregorianCalendar; + + +/** + * Information about a filesystem + * + *

Clase Java para FileSystemType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="FileSystemType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Type" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="CreationDate" type="{http://www.w3.org/2001/XMLSchema}dateTime" minOccurs="0"/>
+ *         <element name="ModificationDate" type="{http://www.w3.org/2001/XMLSchema}dateTime" minOccurs="0"/>
+ *         <element name="BackupDate" type="{http://www.w3.org/2001/XMLSchema}dateTime" minOccurs="0"/>
+ *         <element name="ClusterSize" type="{http://www.w3.org/2001/XMLSchema}unsignedInt"/>
+ *         <element name="Clusters" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="Files" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" minOccurs="0"/>
+ *         <element name="Bootable" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
+ *         <element name="VolumeSerial" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="VolumeName" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="FreeClusters" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" minOccurs="0"/>
+ *         <element name="Dirty" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
+ *         <element name="ExpirationDate" type="{http://www.w3.org/2001/XMLSchema}dateTime" minOccurs="0"/>
+ *         <element name="EffectiveDate" type="{http://www.w3.org/2001/XMLSchema}dateTime" minOccurs="0"/>
+ *         <element name="SystemIdentifier" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="VolumeSetIdentifier" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="PublisherIdentifier" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="DataPreparerIdentifier" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="ApplicationIdentifier" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Contents" type="{}FilesystemContentsType" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "FileSystemType", propOrder = { + "type", + "creationDate", + "modificationDate", + "backupDate", + "clusterSize", + "clusters", + "files", + "bootable", + "volumeSerial", + "volumeName", + "freeClusters", + "dirty", + "expirationDate", + "effectiveDate", + "systemIdentifier", + "volumeSetIdentifier", + "publisherIdentifier", + "dataPreparerIdentifier", + "applicationIdentifier", + "contents" +}) +public class FileSystemType { + + @XmlElement(name = "Type", required = true) + protected String type; + @XmlElement(name = "CreationDate") + @XmlSchemaType(name = "dateTime") + protected XMLGregorianCalendar creationDate; + @XmlElement(name = "ModificationDate") + @XmlSchemaType(name = "dateTime") + protected XMLGregorianCalendar modificationDate; + @XmlElement(name = "BackupDate") + @XmlSchemaType(name = "dateTime") + protected XMLGregorianCalendar backupDate; + @XmlElement(name = "ClusterSize") + @XmlSchemaType(name = "unsignedInt") + protected long clusterSize; + @XmlElement(name = "Clusters", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger clusters; + @XmlElement(name = "Files") + @XmlSchemaType(name = "unsignedLong") + protected BigInteger files; + @XmlElement(name = "Bootable") + protected boolean bootable; + @XmlElement(name = "VolumeSerial") + protected String volumeSerial; + @XmlElement(name = "VolumeName") + protected String volumeName; + @XmlElement(name = "FreeClusters") + @XmlSchemaType(name = "unsignedLong") + protected BigInteger freeClusters; + @XmlElement(name = "Dirty") + protected boolean dirty; + @XmlElement(name = "ExpirationDate") + @XmlSchemaType(name = "dateTime") + protected XMLGregorianCalendar expirationDate; + @XmlElement(name = "EffectiveDate") + @XmlSchemaType(name = "dateTime") + protected XMLGregorianCalendar effectiveDate; + @XmlElement(name = "SystemIdentifier") + protected String systemIdentifier; + @XmlElement(name = "VolumeSetIdentifier") + protected String volumeSetIdentifier; + @XmlElement(name = "PublisherIdentifier") + protected String publisherIdentifier; + @XmlElement(name = "DataPreparerIdentifier") + protected String dataPreparerIdentifier; + @XmlElement(name = "ApplicationIdentifier") + protected String applicationIdentifier; + @XmlElement(name = "Contents") + protected FilesystemContentsType contents; + + /** + * Obtiene el valor de la propiedad type. + * + * @return + * possible object is + * {@link String } + * + */ + public String getType() { + return type; + } + + /** + * Define el valor de la propiedad type. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setType(String value) { + this.type = value; + } + + /** + * Obtiene el valor de la propiedad creationDate. + * + * @return + * possible object is + * {@link XMLGregorianCalendar } + * + */ + public XMLGregorianCalendar getCreationDate() { + return creationDate; + } + + /** + * Define el valor de la propiedad creationDate. + * + * @param value + * allowed object is + * {@link XMLGregorianCalendar } + * + */ + public void setCreationDate(XMLGregorianCalendar value) { + this.creationDate = value; + } + + /** + * Obtiene el valor de la propiedad modificationDate. + * + * @return + * possible object is + * {@link XMLGregorianCalendar } + * + */ + public XMLGregorianCalendar getModificationDate() { + return modificationDate; + } + + /** + * Define el valor de la propiedad modificationDate. + * + * @param value + * allowed object is + * {@link XMLGregorianCalendar } + * + */ + public void setModificationDate(XMLGregorianCalendar value) { + this.modificationDate = value; + } + + /** + * Obtiene el valor de la propiedad backupDate. + * + * @return + * possible object is + * {@link XMLGregorianCalendar } + * + */ + public XMLGregorianCalendar getBackupDate() { + return backupDate; + } + + /** + * Define el valor de la propiedad backupDate. + * + * @param value + * allowed object is + * {@link XMLGregorianCalendar } + * + */ + public void setBackupDate(XMLGregorianCalendar value) { + this.backupDate = value; + } + + /** + * Obtiene el valor de la propiedad clusterSize. + * + */ + public long getClusterSize() { + return clusterSize; + } + + /** + * Define el valor de la propiedad clusterSize. + * + */ + public void setClusterSize(long value) { + this.clusterSize = value; + } + + /** + * Obtiene el valor de la propiedad clusters. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getClusters() { + return clusters; + } + + /** + * Define el valor de la propiedad clusters. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setClusters(BigInteger value) { + this.clusters = value; + } + + /** + * Obtiene el valor de la propiedad files. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getFiles() { + return files; + } + + /** + * Define el valor de la propiedad files. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setFiles(BigInteger value) { + this.files = value; + } + + /** + * Obtiene el valor de la propiedad bootable. + * + */ + public boolean isBootable() { + return bootable; + } + + /** + * Define el valor de la propiedad bootable. + * + */ + public void setBootable(boolean value) { + this.bootable = value; + } + + /** + * Obtiene el valor de la propiedad volumeSerial. + * + * @return + * possible object is + * {@link String } + * + */ + public String getVolumeSerial() { + return volumeSerial; + } + + /** + * Define el valor de la propiedad volumeSerial. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setVolumeSerial(String value) { + this.volumeSerial = value; + } + + /** + * Obtiene el valor de la propiedad volumeName. + * + * @return + * possible object is + * {@link String } + * + */ + public String getVolumeName() { + return volumeName; + } + + /** + * Define el valor de la propiedad volumeName. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setVolumeName(String value) { + this.volumeName = value; + } + + /** + * Obtiene el valor de la propiedad freeClusters. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getFreeClusters() { + return freeClusters; + } + + /** + * Define el valor de la propiedad freeClusters. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setFreeClusters(BigInteger value) { + this.freeClusters = value; + } + + /** + * Obtiene el valor de la propiedad dirty. + * + */ + public boolean isDirty() { + return dirty; + } + + /** + * Define el valor de la propiedad dirty. + * + */ + public void setDirty(boolean value) { + this.dirty = value; + } + + /** + * Obtiene el valor de la propiedad expirationDate. + * + * @return + * possible object is + * {@link XMLGregorianCalendar } + * + */ + public XMLGregorianCalendar getExpirationDate() { + return expirationDate; + } + + /** + * Define el valor de la propiedad expirationDate. + * + * @param value + * allowed object is + * {@link XMLGregorianCalendar } + * + */ + public void setExpirationDate(XMLGregorianCalendar value) { + this.expirationDate = value; + } + + /** + * Obtiene el valor de la propiedad effectiveDate. + * + * @return + * possible object is + * {@link XMLGregorianCalendar } + * + */ + public XMLGregorianCalendar getEffectiveDate() { + return effectiveDate; + } + + /** + * Define el valor de la propiedad effectiveDate. + * + * @param value + * allowed object is + * {@link XMLGregorianCalendar } + * + */ + public void setEffectiveDate(XMLGregorianCalendar value) { + this.effectiveDate = value; + } + + /** + * Obtiene el valor de la propiedad systemIdentifier. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSystemIdentifier() { + return systemIdentifier; + } + + /** + * Define el valor de la propiedad systemIdentifier. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSystemIdentifier(String value) { + this.systemIdentifier = value; + } + + /** + * Obtiene el valor de la propiedad volumeSetIdentifier. + * + * @return + * possible object is + * {@link String } + * + */ + public String getVolumeSetIdentifier() { + return volumeSetIdentifier; + } + + /** + * Define el valor de la propiedad volumeSetIdentifier. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setVolumeSetIdentifier(String value) { + this.volumeSetIdentifier = value; + } + + /** + * Obtiene el valor de la propiedad publisherIdentifier. + * + * @return + * possible object is + * {@link String } + * + */ + public String getPublisherIdentifier() { + return publisherIdentifier; + } + + /** + * Define el valor de la propiedad publisherIdentifier. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setPublisherIdentifier(String value) { + this.publisherIdentifier = value; + } + + /** + * Obtiene el valor de la propiedad dataPreparerIdentifier. + * + * @return + * possible object is + * {@link String } + * + */ + public String getDataPreparerIdentifier() { + return dataPreparerIdentifier; + } + + /** + * Define el valor de la propiedad dataPreparerIdentifier. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setDataPreparerIdentifier(String value) { + this.dataPreparerIdentifier = value; + } + + /** + * Obtiene el valor de la propiedad applicationIdentifier. + * + * @return + * possible object is + * {@link String } + * + */ + public String getApplicationIdentifier() { + return applicationIdentifier; + } + + /** + * Define el valor de la propiedad applicationIdentifier. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setApplicationIdentifier(String value) { + this.applicationIdentifier = value; + } + + /** + * Obtiene el valor de la propiedad contents. + * + * @return + * possible object is + * {@link FilesystemContentsType } + * + */ + public FilesystemContentsType getContents() { + return contents; + } + + /** + * Define el valor de la propiedad contents. + * + * @param value + * allowed object is + * {@link FilesystemContentsType } + * + */ + public void setContents(FilesystemContentsType value) { + this.contents = value; + } + +} diff --git a/CICMMetadata/java/generated/FileSystemsType.java b/CICMMetadata/java/generated/FileSystemsType.java new file mode 100644 index 000000000..1d41f4a8e --- /dev/null +++ b/CICMMetadata/java/generated/FileSystemsType.java @@ -0,0 +1,76 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para FileSystemsType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="FileSystemsType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="FileSystem" type="{}FileSystemType" maxOccurs="unbounded"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "FileSystemsType", propOrder = { + "fileSystem" +}) +public class FileSystemsType { + + @XmlElement(name = "FileSystem", required = true) + protected List fileSystem; + + /** + * Gets the value of the fileSystem property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the fileSystem property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getFileSystem().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link FileSystemType } + * + * + */ + public List getFileSystem() { + if (fileSystem == null) { + fileSystem = new ArrayList(); + } + return this.fileSystem; + } + +} diff --git a/CICMMetadata/java/generated/FileType.java b/CICMMetadata/java/generated/FileType.java new file mode 100644 index 000000000..7541bca79 --- /dev/null +++ b/CICMMetadata/java/generated/FileType.java @@ -0,0 +1,96 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + + +/** + * File + * + *

Clase Java para FileType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="FileType">
+ *   <simpleContent>
+ *     <extension base="<http://www.w3.org/2001/XMLSchema>string">
+ *       <attribute name="format" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     </extension>
+ *   </simpleContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "FileType", propOrder = { + "value" +}) +public class FileType { + + @XmlValue + protected String value; + @XmlAttribute(name = "format") + protected String format; + + /** + * Obtiene el valor de la propiedad value. + * + * @return + * possible object is + * {@link String } + * + */ + public String getValue() { + return value; + } + + /** + * Define el valor de la propiedad value. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setValue(String value) { + this.value = value; + } + + /** + * Obtiene el valor de la propiedad format. + * + * @return + * possible object is + * {@link String } + * + */ + public String getFormat() { + return format; + } + + /** + * Define el valor de la propiedad format. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setFormat(String value) { + this.format = value; + } + +} diff --git a/CICMMetadata/java/generated/FilesystemContentsType.java b/CICMMetadata/java/generated/FilesystemContentsType.java new file mode 100644 index 000000000..204c355dc --- /dev/null +++ b/CICMMetadata/java/generated/FilesystemContentsType.java @@ -0,0 +1,137 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para FilesystemContentsType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="FilesystemContentsType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="File" type="{}ContentsFileType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="Directory" type="{}DirectoryType" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *       <attribute name="namespace" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "FilesystemContentsType", propOrder = { + "file", + "directory" +}) +public class FilesystemContentsType { + + @XmlElement(name = "File") + protected List file; + @XmlElement(name = "Directory") + protected List directory; + @XmlAttribute(name = "namespace") + protected String namespace; + + /** + * Gets the value of the file property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the file property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getFile().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link ContentsFileType } + * + * + */ + public List getFile() { + if (file == null) { + file = new ArrayList(); + } + return this.file; + } + + /** + * Gets the value of the directory property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the directory property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getDirectory().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link DirectoryType } + * + * + */ + public List getDirectory() { + if (directory == null) { + directory = new ArrayList(); + } + return this.directory; + } + + /** + * Obtiene el valor de la propiedad namespace. + * + * @return + * possible object is + * {@link String } + * + */ + public String getNamespace() { + return namespace; + } + + /** + * Define el valor de la propiedad namespace. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setNamespace(String value) { + this.namespace = value; + } + +} diff --git a/CICMMetadata/java/generated/ImageType.java b/CICMMetadata/java/generated/ImageType.java new file mode 100644 index 000000000..565733b3a --- /dev/null +++ b/CICMMetadata/java/generated/ImageType.java @@ -0,0 +1,127 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + + +/** + * File containing track dump, and format, binary, yranib, or audio/video container + * + * + *

Clase Java para ImageType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="ImageType">
+ *   <simpleContent>
+ *     <extension base="<http://www.w3.org/2001/XMLSchema>string">
+ *       <attribute name="format" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="offset" type="{http://www.w3.org/2001/XMLSchema}unsignedLong" />
+ *     </extension>
+ *   </simpleContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ImageType", propOrder = { + "value" +}) +public class ImageType { + + @XmlValue + protected String value; + @XmlAttribute(name = "format") + protected String format; + @XmlAttribute(name = "offset") + @XmlSchemaType(name = "unsignedLong") + protected BigInteger offset; + + /** + * Obtiene el valor de la propiedad value. + * + * @return + * possible object is + * {@link String } + * + */ + public String getValue() { + return value; + } + + /** + * Define el valor de la propiedad value. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setValue(String value) { + this.value = value; + } + + /** + * Obtiene el valor de la propiedad format. + * + * @return + * possible object is + * {@link String } + * + */ + public String getFormat() { + return format; + } + + /** + * Define el valor de la propiedad format. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setFormat(String value) { + this.format = value; + } + + /** + * Obtiene el valor de la propiedad offset. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getOffset() { + return offset; + } + + /** + * Define el valor de la propiedad offset. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setOffset(BigInteger value) { + this.offset = value; + } + +} diff --git a/CICMMetadata/java/generated/KeywordsType.java b/CICMMetadata/java/generated/KeywordsType.java new file mode 100644 index 000000000..bdab9c572 --- /dev/null +++ b/CICMMetadata/java/generated/KeywordsType.java @@ -0,0 +1,76 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para KeywordsType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="KeywordsType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Keyword" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "KeywordsType", propOrder = { + "keyword" +}) +public class KeywordsType { + + @XmlElement(name = "Keyword", required = true) + protected List keyword; + + /** + * Gets the value of the keyword property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the keyword property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getKeyword().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link String } + * + * + */ + public List getKeyword() { + if (keyword == null) { + keyword = new ArrayList(); + } + return this.keyword; + } + +} diff --git a/CICMMetadata/java/generated/LanguagesType.java b/CICMMetadata/java/generated/LanguagesType.java new file mode 100644 index 000000000..a99bc2f6c --- /dev/null +++ b/CICMMetadata/java/generated/LanguagesType.java @@ -0,0 +1,567 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para LanguagesType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="LanguagesType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Language" maxOccurs="unbounded">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ *               <enumeration value="aar"/>
+ *               <enumeration value="abk"/>
+ *               <enumeration value="ace"/>
+ *               <enumeration value="ach"/>
+ *               <enumeration value="ada"/>
+ *               <enumeration value="ady"/>
+ *               <enumeration value="afa"/>
+ *               <enumeration value="afh"/>
+ *               <enumeration value="afr"/>
+ *               <enumeration value="ain"/>
+ *               <enumeration value="aka"/>
+ *               <enumeration value="akk"/>
+ *               <enumeration value="alb"/>
+ *               <enumeration value="ale"/>
+ *               <enumeration value="alg"/>
+ *               <enumeration value="alt"/>
+ *               <enumeration value="amh"/>
+ *               <enumeration value="ang"/>
+ *               <enumeration value="anp"/>
+ *               <enumeration value="apa"/>
+ *               <enumeration value="ara"/>
+ *               <enumeration value="arc"/>
+ *               <enumeration value="arg"/>
+ *               <enumeration value="arm"/>
+ *               <enumeration value="arn"/>
+ *               <enumeration value="arp"/>
+ *               <enumeration value="art"/>
+ *               <enumeration value="arw"/>
+ *               <enumeration value="asm"/>
+ *               <enumeration value="ast"/>
+ *               <enumeration value="ath"/>
+ *               <enumeration value="aus"/>
+ *               <enumeration value="ava"/>
+ *               <enumeration value="ave"/>
+ *               <enumeration value="awa"/>
+ *               <enumeration value="aym"/>
+ *               <enumeration value="aze"/>
+ *               <enumeration value="bad"/>
+ *               <enumeration value="bai"/>
+ *               <enumeration value="bak"/>
+ *               <enumeration value="bal"/>
+ *               <enumeration value="bam"/>
+ *               <enumeration value="ban"/>
+ *               <enumeration value="baq"/>
+ *               <enumeration value="bas"/>
+ *               <enumeration value="bat"/>
+ *               <enumeration value="bej"/>
+ *               <enumeration value="bel"/>
+ *               <enumeration value="bem"/>
+ *               <enumeration value="ben"/>
+ *               <enumeration value="ber"/>
+ *               <enumeration value="bho"/>
+ *               <enumeration value="bih"/>
+ *               <enumeration value="bik"/>
+ *               <enumeration value="bin"/>
+ *               <enumeration value="bis"/>
+ *               <enumeration value="bla"/>
+ *               <enumeration value="bnt"/>
+ *               <enumeration value="bos"/>
+ *               <enumeration value="bra"/>
+ *               <enumeration value="bre"/>
+ *               <enumeration value="btk"/>
+ *               <enumeration value="bua"/>
+ *               <enumeration value="bug"/>
+ *               <enumeration value="bul"/>
+ *               <enumeration value="bur"/>
+ *               <enumeration value="byn"/>
+ *               <enumeration value="cad"/>
+ *               <enumeration value="cai"/>
+ *               <enumeration value="car"/>
+ *               <enumeration value="cat"/>
+ *               <enumeration value="cau"/>
+ *               <enumeration value="ceb"/>
+ *               <enumeration value="cel"/>
+ *               <enumeration value="cha"/>
+ *               <enumeration value="chb"/>
+ *               <enumeration value="che"/>
+ *               <enumeration value="chg"/>
+ *               <enumeration value="chi"/>
+ *               <enumeration value="chk"/>
+ *               <enumeration value="chm"/>
+ *               <enumeration value="chn"/>
+ *               <enumeration value="cho"/>
+ *               <enumeration value="chp"/>
+ *               <enumeration value="chr"/>
+ *               <enumeration value="chu"/>
+ *               <enumeration value="chv"/>
+ *               <enumeration value="chy"/>
+ *               <enumeration value="cmc"/>
+ *               <enumeration value="cop"/>
+ *               <enumeration value="cor"/>
+ *               <enumeration value="cos"/>
+ *               <enumeration value="cpe"/>
+ *               <enumeration value="cpf"/>
+ *               <enumeration value="cpp"/>
+ *               <enumeration value="cre"/>
+ *               <enumeration value="crh"/>
+ *               <enumeration value="crp"/>
+ *               <enumeration value="csb"/>
+ *               <enumeration value="cus"/>
+ *               <enumeration value="cze"/>
+ *               <enumeration value="dak"/>
+ *               <enumeration value="dan"/>
+ *               <enumeration value="dar"/>
+ *               <enumeration value="day"/>
+ *               <enumeration value="del"/>
+ *               <enumeration value="den"/>
+ *               <enumeration value="dgr"/>
+ *               <enumeration value="din"/>
+ *               <enumeration value="div"/>
+ *               <enumeration value="doi"/>
+ *               <enumeration value="dra"/>
+ *               <enumeration value="dsb"/>
+ *               <enumeration value="dua"/>
+ *               <enumeration value="dum"/>
+ *               <enumeration value="dut"/>
+ *               <enumeration value="dyu"/>
+ *               <enumeration value="dzo"/>
+ *               <enumeration value="efi"/>
+ *               <enumeration value="egy"/>
+ *               <enumeration value="eka"/>
+ *               <enumeration value="elx"/>
+ *               <enumeration value="eng"/>
+ *               <enumeration value="enm"/>
+ *               <enumeration value="epo"/>
+ *               <enumeration value="est"/>
+ *               <enumeration value="ewe"/>
+ *               <enumeration value="ewo"/>
+ *               <enumeration value="fan"/>
+ *               <enumeration value="fao"/>
+ *               <enumeration value="fat"/>
+ *               <enumeration value="fij"/>
+ *               <enumeration value="fil"/>
+ *               <enumeration value="fin"/>
+ *               <enumeration value="fiu"/>
+ *               <enumeration value="fon"/>
+ *               <enumeration value="fre"/>
+ *               <enumeration value="frm"/>
+ *               <enumeration value="fro"/>
+ *               <enumeration value="frr"/>
+ *               <enumeration value="frs"/>
+ *               <enumeration value="fry"/>
+ *               <enumeration value="ful"/>
+ *               <enumeration value="fur"/>
+ *               <enumeration value="gaa"/>
+ *               <enumeration value="gay"/>
+ *               <enumeration value="gba"/>
+ *               <enumeration value="gem"/>
+ *               <enumeration value="geo"/>
+ *               <enumeration value="ger"/>
+ *               <enumeration value="gez"/>
+ *               <enumeration value="gil"/>
+ *               <enumeration value="gla"/>
+ *               <enumeration value="gle"/>
+ *               <enumeration value="glg"/>
+ *               <enumeration value="glv"/>
+ *               <enumeration value="gmh"/>
+ *               <enumeration value="goh"/>
+ *               <enumeration value="gon"/>
+ *               <enumeration value="gor"/>
+ *               <enumeration value="got"/>
+ *               <enumeration value="grb"/>
+ *               <enumeration value="grc"/>
+ *               <enumeration value="gre"/>
+ *               <enumeration value="grn"/>
+ *               <enumeration value="gsw"/>
+ *               <enumeration value="guj"/>
+ *               <enumeration value="gwi"/>
+ *               <enumeration value="hai"/>
+ *               <enumeration value="hat"/>
+ *               <enumeration value="hau"/>
+ *               <enumeration value="haw"/>
+ *               <enumeration value="heb"/>
+ *               <enumeration value="her"/>
+ *               <enumeration value="hil"/>
+ *               <enumeration value="him"/>
+ *               <enumeration value="hin"/>
+ *               <enumeration value="hit"/>
+ *               <enumeration value="hmn"/>
+ *               <enumeration value="hmo"/>
+ *               <enumeration value="hrv"/>
+ *               <enumeration value="hsb"/>
+ *               <enumeration value="hun"/>
+ *               <enumeration value="hup"/>
+ *               <enumeration value="iba"/>
+ *               <enumeration value="ibo"/>
+ *               <enumeration value="ice"/>
+ *               <enumeration value="ido"/>
+ *               <enumeration value="iii"/>
+ *               <enumeration value="ijo"/>
+ *               <enumeration value="iku"/>
+ *               <enumeration value="ile"/>
+ *               <enumeration value="ilo"/>
+ *               <enumeration value="ina"/>
+ *               <enumeration value="inc"/>
+ *               <enumeration value="ind"/>
+ *               <enumeration value="ine"/>
+ *               <enumeration value="inh"/>
+ *               <enumeration value="ipk"/>
+ *               <enumeration value="ira"/>
+ *               <enumeration value="iro"/>
+ *               <enumeration value="ita"/>
+ *               <enumeration value="jav"/>
+ *               <enumeration value="jbo"/>
+ *               <enumeration value="jpn"/>
+ *               <enumeration value="jpr"/>
+ *               <enumeration value="jrb"/>
+ *               <enumeration value="kaa"/>
+ *               <enumeration value="kab"/>
+ *               <enumeration value="kac"/>
+ *               <enumeration value="kal"/>
+ *               <enumeration value="kam"/>
+ *               <enumeration value="kan"/>
+ *               <enumeration value="kar"/>
+ *               <enumeration value="kas"/>
+ *               <enumeration value="kau"/>
+ *               <enumeration value="kaw"/>
+ *               <enumeration value="kaz"/>
+ *               <enumeration value="kbd"/>
+ *               <enumeration value="kha"/>
+ *               <enumeration value="khi"/>
+ *               <enumeration value="khm"/>
+ *               <enumeration value="kho"/>
+ *               <enumeration value="kik"/>
+ *               <enumeration value="kin"/>
+ *               <enumeration value="kir"/>
+ *               <enumeration value="kmb"/>
+ *               <enumeration value="kok"/>
+ *               <enumeration value="kom"/>
+ *               <enumeration value="kon"/>
+ *               <enumeration value="kor"/>
+ *               <enumeration value="kos"/>
+ *               <enumeration value="kpe"/>
+ *               <enumeration value="krc"/>
+ *               <enumeration value="krl"/>
+ *               <enumeration value="kro"/>
+ *               <enumeration value="kru"/>
+ *               <enumeration value="kua"/>
+ *               <enumeration value="kum"/>
+ *               <enumeration value="kur"/>
+ *               <enumeration value="kut"/>
+ *               <enumeration value="lad"/>
+ *               <enumeration value="lah"/>
+ *               <enumeration value="lam"/>
+ *               <enumeration value="lao"/>
+ *               <enumeration value="lat"/>
+ *               <enumeration value="lav"/>
+ *               <enumeration value="lez"/>
+ *               <enumeration value="lim"/>
+ *               <enumeration value="lin"/>
+ *               <enumeration value="lit"/>
+ *               <enumeration value="lol"/>
+ *               <enumeration value="loz"/>
+ *               <enumeration value="ltz"/>
+ *               <enumeration value="lua"/>
+ *               <enumeration value="lub"/>
+ *               <enumeration value="lug"/>
+ *               <enumeration value="lui"/>
+ *               <enumeration value="lun"/>
+ *               <enumeration value="luo"/>
+ *               <enumeration value="lus"/>
+ *               <enumeration value="mac"/>
+ *               <enumeration value="mad"/>
+ *               <enumeration value="mag"/>
+ *               <enumeration value="mah"/>
+ *               <enumeration value="mai"/>
+ *               <enumeration value="mak"/>
+ *               <enumeration value="mal"/>
+ *               <enumeration value="man"/>
+ *               <enumeration value="mao"/>
+ *               <enumeration value="map"/>
+ *               <enumeration value="mar"/>
+ *               <enumeration value="mas"/>
+ *               <enumeration value="may"/>
+ *               <enumeration value="mdf"/>
+ *               <enumeration value="mdr"/>
+ *               <enumeration value="men"/>
+ *               <enumeration value="mga"/>
+ *               <enumeration value="mic"/>
+ *               <enumeration value="min"/>
+ *               <enumeration value="mis"/>
+ *               <enumeration value="mkh"/>
+ *               <enumeration value="mlg"/>
+ *               <enumeration value="mlt"/>
+ *               <enumeration value="mnc"/>
+ *               <enumeration value="mni"/>
+ *               <enumeration value="mno"/>
+ *               <enumeration value="moh"/>
+ *               <enumeration value="mon"/>
+ *               <enumeration value="mos"/>
+ *               <enumeration value="mul"/>
+ *               <enumeration value="mun"/>
+ *               <enumeration value="mus"/>
+ *               <enumeration value="mwl"/>
+ *               <enumeration value="mwr"/>
+ *               <enumeration value="myn"/>
+ *               <enumeration value="myv"/>
+ *               <enumeration value="nah"/>
+ *               <enumeration value="nai"/>
+ *               <enumeration value="nap"/>
+ *               <enumeration value="nau"/>
+ *               <enumeration value="nav"/>
+ *               <enumeration value="nbl"/>
+ *               <enumeration value="nde"/>
+ *               <enumeration value="ndo"/>
+ *               <enumeration value="nds"/>
+ *               <enumeration value="nep"/>
+ *               <enumeration value="new"/>
+ *               <enumeration value="nia"/>
+ *               <enumeration value="nic"/>
+ *               <enumeration value="niu"/>
+ *               <enumeration value="nno"/>
+ *               <enumeration value="nob"/>
+ *               <enumeration value="nog"/>
+ *               <enumeration value="non"/>
+ *               <enumeration value="nor"/>
+ *               <enumeration value="nqo"/>
+ *               <enumeration value="nso"/>
+ *               <enumeration value="nub"/>
+ *               <enumeration value="nwc"/>
+ *               <enumeration value="nya"/>
+ *               <enumeration value="nym"/>
+ *               <enumeration value="nyn"/>
+ *               <enumeration value="nyo"/>
+ *               <enumeration value="nzi"/>
+ *               <enumeration value="oci"/>
+ *               <enumeration value="oji"/>
+ *               <enumeration value="ori"/>
+ *               <enumeration value="orm"/>
+ *               <enumeration value="osa"/>
+ *               <enumeration value="oss"/>
+ *               <enumeration value="ota"/>
+ *               <enumeration value="oto"/>
+ *               <enumeration value="paa"/>
+ *               <enumeration value="pag"/>
+ *               <enumeration value="pal"/>
+ *               <enumeration value="pam"/>
+ *               <enumeration value="pan"/>
+ *               <enumeration value="pap"/>
+ *               <enumeration value="pau"/>
+ *               <enumeration value="peo"/>
+ *               <enumeration value="per"/>
+ *               <enumeration value="phi"/>
+ *               <enumeration value="phn"/>
+ *               <enumeration value="pli"/>
+ *               <enumeration value="pol"/>
+ *               <enumeration value="pon"/>
+ *               <enumeration value="por"/>
+ *               <enumeration value="pra"/>
+ *               <enumeration value="pro"/>
+ *               <enumeration value="pus"/>
+ *               <enumeration value="qaa-qtz"/>
+ *               <enumeration value="que"/>
+ *               <enumeration value="raj"/>
+ *               <enumeration value="rap"/>
+ *               <enumeration value="rar"/>
+ *               <enumeration value="roa"/>
+ *               <enumeration value="roh"/>
+ *               <enumeration value="rom"/>
+ *               <enumeration value="rum"/>
+ *               <enumeration value="run"/>
+ *               <enumeration value="rup"/>
+ *               <enumeration value="rus"/>
+ *               <enumeration value="sad"/>
+ *               <enumeration value="sag"/>
+ *               <enumeration value="sah"/>
+ *               <enumeration value="sai"/>
+ *               <enumeration value="sal"/>
+ *               <enumeration value="sam"/>
+ *               <enumeration value="san"/>
+ *               <enumeration value="sas"/>
+ *               <enumeration value="sat"/>
+ *               <enumeration value="scn"/>
+ *               <enumeration value="sco"/>
+ *               <enumeration value="sel"/>
+ *               <enumeration value="sem"/>
+ *               <enumeration value="sga"/>
+ *               <enumeration value="sgn"/>
+ *               <enumeration value="shn"/>
+ *               <enumeration value="sid"/>
+ *               <enumeration value="sin"/>
+ *               <enumeration value="sio"/>
+ *               <enumeration value="sit"/>
+ *               <enumeration value="sla"/>
+ *               <enumeration value="slo"/>
+ *               <enumeration value="slv"/>
+ *               <enumeration value="sma"/>
+ *               <enumeration value="sme"/>
+ *               <enumeration value="smi"/>
+ *               <enumeration value="smj"/>
+ *               <enumeration value="smn"/>
+ *               <enumeration value="smo"/>
+ *               <enumeration value="sms"/>
+ *               <enumeration value="sna"/>
+ *               <enumeration value="snd"/>
+ *               <enumeration value="snk"/>
+ *               <enumeration value="sog"/>
+ *               <enumeration value="som"/>
+ *               <enumeration value="son"/>
+ *               <enumeration value="sot"/>
+ *               <enumeration value="spa"/>
+ *               <enumeration value="srd"/>
+ *               <enumeration value="srn"/>
+ *               <enumeration value="srp"/>
+ *               <enumeration value="srr"/>
+ *               <enumeration value="ssa"/>
+ *               <enumeration value="ssw"/>
+ *               <enumeration value="suk"/>
+ *               <enumeration value="sun"/>
+ *               <enumeration value="sus"/>
+ *               <enumeration value="sux"/>
+ *               <enumeration value="swa"/>
+ *               <enumeration value="swe"/>
+ *               <enumeration value="syc"/>
+ *               <enumeration value="syr"/>
+ *               <enumeration value="tah"/>
+ *               <enumeration value="tai"/>
+ *               <enumeration value="tam"/>
+ *               <enumeration value="tat"/>
+ *               <enumeration value="tel"/>
+ *               <enumeration value="tem"/>
+ *               <enumeration value="ter"/>
+ *               <enumeration value="tet"/>
+ *               <enumeration value="tgk"/>
+ *               <enumeration value="tgl"/>
+ *               <enumeration value="tha"/>
+ *               <enumeration value="tib"/>
+ *               <enumeration value="tig"/>
+ *               <enumeration value="tir"/>
+ *               <enumeration value="tiv"/>
+ *               <enumeration value="tkl"/>
+ *               <enumeration value="tlh"/>
+ *               <enumeration value="tli"/>
+ *               <enumeration value="tmh"/>
+ *               <enumeration value="tog"/>
+ *               <enumeration value="ton"/>
+ *               <enumeration value="tpi"/>
+ *               <enumeration value="tsi"/>
+ *               <enumeration value="tsn"/>
+ *               <enumeration value="tso"/>
+ *               <enumeration value="tuk"/>
+ *               <enumeration value="tum"/>
+ *               <enumeration value="tup"/>
+ *               <enumeration value="tur"/>
+ *               <enumeration value="tut"/>
+ *               <enumeration value="tvl"/>
+ *               <enumeration value="twi"/>
+ *               <enumeration value="tyv"/>
+ *               <enumeration value="udm"/>
+ *               <enumeration value="uga"/>
+ *               <enumeration value="uig"/>
+ *               <enumeration value="ukr"/>
+ *               <enumeration value="umb"/>
+ *               <enumeration value="und"/>
+ *               <enumeration value="urd"/>
+ *               <enumeration value="uzb"/>
+ *               <enumeration value="vai"/>
+ *               <enumeration value="ven"/>
+ *               <enumeration value="vie"/>
+ *               <enumeration value="vol"/>
+ *               <enumeration value="vot"/>
+ *               <enumeration value="wak"/>
+ *               <enumeration value="wal"/>
+ *               <enumeration value="war"/>
+ *               <enumeration value="was"/>
+ *               <enumeration value="wel"/>
+ *               <enumeration value="wen"/>
+ *               <enumeration value="wln"/>
+ *               <enumeration value="wol"/>
+ *               <enumeration value="xal"/>
+ *               <enumeration value="xho"/>
+ *               <enumeration value="yao"/>
+ *               <enumeration value="yap"/>
+ *               <enumeration value="yid"/>
+ *               <enumeration value="yor"/>
+ *               <enumeration value="ypk"/>
+ *               <enumeration value="zap"/>
+ *               <enumeration value="zbl"/>
+ *               <enumeration value="zen"/>
+ *               <enumeration value="zgh"/>
+ *               <enumeration value="zha"/>
+ *               <enumeration value="znd"/>
+ *               <enumeration value="zul"/>
+ *               <enumeration value="zun"/>
+ *               <enumeration value="zxx"/>
+ *               <enumeration value="zza"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "LanguagesType", propOrder = { + "language" +}) +public class LanguagesType { + + @XmlElement(name = "Language", required = true) + protected List language; + + /** + * Gets the value of the language property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the language property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getLanguage().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link String } + * + * + */ + public List getLanguage() { + if (language == null) { + language = new ArrayList(); + } + return this.language; + } + +} diff --git a/CICMMetadata/java/generated/LayeredTextType.java b/CICMMetadata/java/generated/LayeredTextType.java new file mode 100644 index 000000000..cb452bec5 --- /dev/null +++ b/CICMMetadata/java/generated/LayeredTextType.java @@ -0,0 +1,100 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + + +/** + *

Clase Java para LayeredTextType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="LayeredTextType">
+ *   <simpleContent>
+ *     <extension base="<http://www.w3.org/2001/XMLSchema>string">
+ *       <attribute name="layer">
+ *         <simpleType>
+ *           <restriction base="{http://www.w3.org/2001/XMLSchema}unsignedInt">
+ *             <minInclusive value="0"/>
+ *           </restriction>
+ *         </simpleType>
+ *       </attribute>
+ *     </extension>
+ *   </simpleContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "LayeredTextType", propOrder = { + "value" +}) +public class LayeredTextType { + + @XmlValue + protected String value; + @XmlAttribute(name = "layer") + protected Long layer; + + /** + * Obtiene el valor de la propiedad value. + * + * @return + * possible object is + * {@link String } + * + */ + public String getValue() { + return value; + } + + /** + * Define el valor de la propiedad value. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setValue(String value) { + this.value = value; + } + + /** + * Obtiene el valor de la propiedad layer. + * + * @return + * possible object is + * {@link Long } + * + */ + public Long getLayer() { + return layer; + } + + /** + * Define el valor de la propiedad layer. + * + * @param value + * allowed object is + * {@link Long } + * + */ + public void setLayer(Long value) { + this.layer = value; + } + +} diff --git a/CICMMetadata/java/generated/LayersType.java b/CICMMetadata/java/generated/LayersType.java new file mode 100644 index 000000000..fea8757b5 --- /dev/null +++ b/CICMMetadata/java/generated/LayersType.java @@ -0,0 +1,111 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para LayersType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="LayersType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Sectors" type="{}SectorsType" maxOccurs="unbounded"/>
+ *       </sequence>
+ *       <attribute name="type">
+ *         <simpleType>
+ *           <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ *             <enumeration value="PTP"/>
+ *             <enumeration value="OTP"/>
+ *           </restriction>
+ *         </simpleType>
+ *       </attribute>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "LayersType", propOrder = { + "sectors" +}) +public class LayersType { + + @XmlElement(name = "Sectors", required = true) + protected List sectors; + @XmlAttribute(name = "type") + protected String type; + + /** + * Gets the value of the sectors property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the sectors property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getSectors().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link SectorsType } + * + * + */ + public List getSectors() { + if (sectors == null) { + sectors = new ArrayList(); + } + return this.sectors; + } + + /** + * Obtiene el valor de la propiedad type. + * + * @return + * possible object is + * {@link String } + * + */ + public String getType() { + return type; + } + + /** + * Define el valor de la propiedad type. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setType(String value) { + this.type = value; + } + +} diff --git a/CICMMetadata/java/generated/LinearMediaType.java b/CICMMetadata/java/generated/LinearMediaType.java new file mode 100644 index 000000000..95998da81 --- /dev/null +++ b/CICMMetadata/java/generated/LinearMediaType.java @@ -0,0 +1,583 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * Describes a dump of a linear media, that is, a media that is read byte-by-byte like for + * example, a ROM chip, a game cartridge, a PCMCIA SRAM card, etc... + * + * + *

Clase Java para LinearMediaType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="LinearMediaType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Image" type="{}ImageType"/>
+ *         <element name="Size" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="ImageChecksums" type="{}ChecksumsType"/>
+ *         <element name="Checksums" type="{}ChecksumsType" minOccurs="0"/>
+ *         <element name="PartNumber" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="SerialNumber" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Title" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Sequence" type="{http://www.w3.org/2001/XMLSchema}unsignedInt" minOccurs="0"/>
+ *         <element name="ImageInterleave" type="{http://www.w3.org/2001/XMLSchema}unsignedInt" minOccurs="0"/>
+ *         <element name="Interleave" type="{http://www.w3.org/2001/XMLSchema}unsignedInt" minOccurs="0"/>
+ *         <element name="Manufacturer" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Model" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Package" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Interface" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Dimensions" type="{}DimensionsType" minOccurs="0"/>
+ *         <element name="Scans" type="{}ScansType" minOccurs="0"/>
+ *         <element name="DumpHardwareArray" type="{}DumpHardwareArrayType" minOccurs="0"/>
+ *         <element name="PCMCIA" type="{}PCMCIAType" minOccurs="0"/>
+ *         <element name="CopyProtection" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "LinearMediaType", propOrder = { + "image", + "size", + "imageChecksums", + "checksums", + "partNumber", + "serialNumber", + "title", + "sequence", + "imageInterleave", + "interleave", + "manufacturer", + "model", + "_package", + "_interface", + "dimensions", + "scans", + "dumpHardwareArray", + "pcmcia", + "copyProtection" +}) +public class LinearMediaType { + + @XmlElement(name = "Image", required = true) + protected ImageType image; + @XmlElement(name = "Size", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger size; + @XmlElement(name = "ImageChecksums", required = true) + protected ChecksumsType imageChecksums; + @XmlElement(name = "Checksums") + protected ChecksumsType checksums; + @XmlElement(name = "PartNumber") + protected String partNumber; + @XmlElement(name = "SerialNumber") + protected String serialNumber; + @XmlElement(name = "Title", required = true) + protected String title; + @XmlElement(name = "Sequence") + @XmlSchemaType(name = "unsignedInt") + protected Long sequence; + @XmlElement(name = "ImageInterleave") + @XmlSchemaType(name = "unsignedInt") + protected Long imageInterleave; + @XmlElement(name = "Interleave") + @XmlSchemaType(name = "unsignedInt") + protected Long interleave; + @XmlElement(name = "Manufacturer") + protected String manufacturer; + @XmlElement(name = "Model") + protected String model; + @XmlElement(name = "Package", required = true) + protected String _package; + @XmlElement(name = "Interface") + protected String _interface; + @XmlElement(name = "Dimensions") + protected DimensionsType dimensions; + @XmlElement(name = "Scans") + protected ScansType scans; + @XmlElement(name = "DumpHardwareArray") + protected DumpHardwareArrayType dumpHardwareArray; + @XmlElement(name = "PCMCIA") + protected PCMCIAType pcmcia; + @XmlElement(name = "CopyProtection") + protected String copyProtection; + + /** + * Obtiene el valor de la propiedad image. + * + * @return + * possible object is + * {@link ImageType } + * + */ + public ImageType getImage() { + return image; + } + + /** + * Define el valor de la propiedad image. + * + * @param value + * allowed object is + * {@link ImageType } + * + */ + public void setImage(ImageType value) { + this.image = value; + } + + /** + * Obtiene el valor de la propiedad size. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getSize() { + return size; + } + + /** + * Define el valor de la propiedad size. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setSize(BigInteger value) { + this.size = value; + } + + /** + * Obtiene el valor de la propiedad imageChecksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getImageChecksums() { + return imageChecksums; + } + + /** + * Define el valor de la propiedad imageChecksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setImageChecksums(ChecksumsType value) { + this.imageChecksums = value; + } + + /** + * Obtiene el valor de la propiedad checksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getChecksums() { + return checksums; + } + + /** + * Define el valor de la propiedad checksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setChecksums(ChecksumsType value) { + this.checksums = value; + } + + /** + * Obtiene el valor de la propiedad partNumber. + * + * @return + * possible object is + * {@link String } + * + */ + public String getPartNumber() { + return partNumber; + } + + /** + * Define el valor de la propiedad partNumber. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setPartNumber(String value) { + this.partNumber = value; + } + + /** + * Obtiene el valor de la propiedad serialNumber. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSerialNumber() { + return serialNumber; + } + + /** + * Define el valor de la propiedad serialNumber. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSerialNumber(String value) { + this.serialNumber = value; + } + + /** + * Obtiene el valor de la propiedad title. + * + * @return + * possible object is + * {@link String } + * + */ + public String getTitle() { + return title; + } + + /** + * Define el valor de la propiedad title. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setTitle(String value) { + this.title = value; + } + + /** + * Obtiene el valor de la propiedad sequence. + * + * @return + * possible object is + * {@link Long } + * + */ + public Long getSequence() { + return sequence; + } + + /** + * Define el valor de la propiedad sequence. + * + * @param value + * allowed object is + * {@link Long } + * + */ + public void setSequence(Long value) { + this.sequence = value; + } + + /** + * Obtiene el valor de la propiedad imageInterleave. + * + * @return + * possible object is + * {@link Long } + * + */ + public Long getImageInterleave() { + return imageInterleave; + } + + /** + * Define el valor de la propiedad imageInterleave. + * + * @param value + * allowed object is + * {@link Long } + * + */ + public void setImageInterleave(Long value) { + this.imageInterleave = value; + } + + /** + * Obtiene el valor de la propiedad interleave. + * + * @return + * possible object is + * {@link Long } + * + */ + public Long getInterleave() { + return interleave; + } + + /** + * Define el valor de la propiedad interleave. + * + * @param value + * allowed object is + * {@link Long } + * + */ + public void setInterleave(Long value) { + this.interleave = value; + } + + /** + * Obtiene el valor de la propiedad manufacturer. + * + * @return + * possible object is + * {@link String } + * + */ + public String getManufacturer() { + return manufacturer; + } + + /** + * Define el valor de la propiedad manufacturer. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setManufacturer(String value) { + this.manufacturer = value; + } + + /** + * Obtiene el valor de la propiedad model. + * + * @return + * possible object is + * {@link String } + * + */ + public String getModel() { + return model; + } + + /** + * Define el valor de la propiedad model. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setModel(String value) { + this.model = value; + } + + /** + * Obtiene el valor de la propiedad package. + * + * @return + * possible object is + * {@link String } + * + */ + public String getPackage() { + return _package; + } + + /** + * Define el valor de la propiedad package. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setPackage(String value) { + this._package = value; + } + + /** + * Obtiene el valor de la propiedad interface. + * + * @return + * possible object is + * {@link String } + * + */ + public String getInterface() { + return _interface; + } + + /** + * Define el valor de la propiedad interface. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setInterface(String value) { + this._interface = value; + } + + /** + * Obtiene el valor de la propiedad dimensions. + * + * @return + * possible object is + * {@link DimensionsType } + * + */ + public DimensionsType getDimensions() { + return dimensions; + } + + /** + * Define el valor de la propiedad dimensions. + * + * @param value + * allowed object is + * {@link DimensionsType } + * + */ + public void setDimensions(DimensionsType value) { + this.dimensions = value; + } + + /** + * Obtiene el valor de la propiedad scans. + * + * @return + * possible object is + * {@link ScansType } + * + */ + public ScansType getScans() { + return scans; + } + + /** + * Define el valor de la propiedad scans. + * + * @param value + * allowed object is + * {@link ScansType } + * + */ + public void setScans(ScansType value) { + this.scans = value; + } + + /** + * Obtiene el valor de la propiedad dumpHardwareArray. + * + * @return + * possible object is + * {@link DumpHardwareArrayType } + * + */ + public DumpHardwareArrayType getDumpHardwareArray() { + return dumpHardwareArray; + } + + /** + * Define el valor de la propiedad dumpHardwareArray. + * + * @param value + * allowed object is + * {@link DumpHardwareArrayType } + * + */ + public void setDumpHardwareArray(DumpHardwareArrayType value) { + this.dumpHardwareArray = value; + } + + /** + * Obtiene el valor de la propiedad pcmcia. + * + * @return + * possible object is + * {@link PCMCIAType } + * + */ + public PCMCIAType getPCMCIA() { + return pcmcia; + } + + /** + * Define el valor de la propiedad pcmcia. + * + * @param value + * allowed object is + * {@link PCMCIAType } + * + */ + public void setPCMCIA(PCMCIAType value) { + this.pcmcia = value; + } + + /** + * Obtiene el valor de la propiedad copyProtection. + * + * @return + * possible object is + * {@link String } + * + */ + public String getCopyProtection() { + return copyProtection; + } + + /** + * Define el valor de la propiedad copyProtection. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setCopyProtection(String value) { + this.copyProtection = value; + } + +} diff --git a/CICMMetadata/java/generated/MagazineType.java b/CICMMetadata/java/generated/MagazineType.java new file mode 100644 index 000000000..3d4f9fdbf --- /dev/null +++ b/CICMMetadata/java/generated/MagazineType.java @@ -0,0 +1,326 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; +import javax.xml.datatype.XMLGregorianCalendar; + + +/** + *

Clase Java para MagazineType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="MagazineType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Barcodes" type="{}BarcodesType" minOccurs="0"/>
+ *         <element name="Cover" type="{}CoverType" minOccurs="0"/>
+ *         <element name="Name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Editorial" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="PublicationDate" type="{http://www.w3.org/2001/XMLSchema}date" minOccurs="0"/>
+ *         <element name="Number" type="{http://www.w3.org/2001/XMLSchema}unsignedInt" minOccurs="0"/>
+ *         <element name="Language" type="{}LanguagesType" minOccurs="0"/>
+ *         <element name="Pages" type="{http://www.w3.org/2001/XMLSchema}unsignedInt" minOccurs="0"/>
+ *         <element name="PageSize" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Scan" type="{}ScanType" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "MagazineType", propOrder = { + "barcodes", + "cover", + "name", + "editorial", + "publicationDate", + "number", + "language", + "pages", + "pageSize", + "scan" +}) +public class MagazineType { + + @XmlElement(name = "Barcodes") + protected BarcodesType barcodes; + @XmlElement(name = "Cover") + protected CoverType cover; + @XmlElement(name = "Name", required = true) + protected String name; + @XmlElement(name = "Editorial") + protected String editorial; + @XmlElement(name = "PublicationDate") + @XmlSchemaType(name = "date") + protected XMLGregorianCalendar publicationDate; + @XmlElement(name = "Number") + @XmlSchemaType(name = "unsignedInt") + protected Long number; + @XmlElement(name = "Language") + protected LanguagesType language; + @XmlElement(name = "Pages") + @XmlSchemaType(name = "unsignedInt") + protected Long pages; + @XmlElement(name = "PageSize") + protected String pageSize; + @XmlElement(name = "Scan") + protected ScanType scan; + + /** + * Obtiene el valor de la propiedad barcodes. + * + * @return + * possible object is + * {@link BarcodesType } + * + */ + public BarcodesType getBarcodes() { + return barcodes; + } + + /** + * Define el valor de la propiedad barcodes. + * + * @param value + * allowed object is + * {@link BarcodesType } + * + */ + public void setBarcodes(BarcodesType value) { + this.barcodes = value; + } + + /** + * Obtiene el valor de la propiedad cover. + * + * @return + * possible object is + * {@link CoverType } + * + */ + public CoverType getCover() { + return cover; + } + + /** + * Define el valor de la propiedad cover. + * + * @param value + * allowed object is + * {@link CoverType } + * + */ + public void setCover(CoverType value) { + this.cover = value; + } + + /** + * Obtiene el valor de la propiedad name. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Define el valor de la propiedad name. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + /** + * Obtiene el valor de la propiedad editorial. + * + * @return + * possible object is + * {@link String } + * + */ + public String getEditorial() { + return editorial; + } + + /** + * Define el valor de la propiedad editorial. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setEditorial(String value) { + this.editorial = value; + } + + /** + * Obtiene el valor de la propiedad publicationDate. + * + * @return + * possible object is + * {@link XMLGregorianCalendar } + * + */ + public XMLGregorianCalendar getPublicationDate() { + return publicationDate; + } + + /** + * Define el valor de la propiedad publicationDate. + * + * @param value + * allowed object is + * {@link XMLGregorianCalendar } + * + */ + public void setPublicationDate(XMLGregorianCalendar value) { + this.publicationDate = value; + } + + /** + * Obtiene el valor de la propiedad number. + * + * @return + * possible object is + * {@link Long } + * + */ + public Long getNumber() { + return number; + } + + /** + * Define el valor de la propiedad number. + * + * @param value + * allowed object is + * {@link Long } + * + */ + public void setNumber(Long value) { + this.number = value; + } + + /** + * Obtiene el valor de la propiedad language. + * + * @return + * possible object is + * {@link LanguagesType } + * + */ + public LanguagesType getLanguage() { + return language; + } + + /** + * Define el valor de la propiedad language. + * + * @param value + * allowed object is + * {@link LanguagesType } + * + */ + public void setLanguage(LanguagesType value) { + this.language = value; + } + + /** + * Obtiene el valor de la propiedad pages. + * + * @return + * possible object is + * {@link Long } + * + */ + public Long getPages() { + return pages; + } + + /** + * Define el valor de la propiedad pages. + * + * @param value + * allowed object is + * {@link Long } + * + */ + public void setPages(Long value) { + this.pages = value; + } + + /** + * Obtiene el valor de la propiedad pageSize. + * + * @return + * possible object is + * {@link String } + * + */ + public String getPageSize() { + return pageSize; + } + + /** + * Define el valor de la propiedad pageSize. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setPageSize(String value) { + this.pageSize = value; + } + + /** + * Obtiene el valor de la propiedad scan. + * + * @return + * possible object is + * {@link ScanType } + * + */ + public ScanType getScan() { + return scan; + } + + /** + * Define el valor de la propiedad scan. + * + * @param value + * allowed object is + * {@link ScanType } + * + */ + public void setScan(ScanType value) { + this.scan = value; + } + +} diff --git a/CICMMetadata/java/generated/MediaScanType.java b/CICMMetadata/java/generated/MediaScanType.java new file mode 100644 index 000000000..3fb421399 --- /dev/null +++ b/CICMMetadata/java/generated/MediaScanType.java @@ -0,0 +1,108 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para MediaScanType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="MediaScanType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="MediaScanElement">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ *               <enumeration value="up"/>
+ *               <enumeration value="down"/>
+ *               <enumeration value="front"/>
+ *               <enumeration value="back"/>
+ *               <enumeration value="left"/>
+ *               <enumeration value="right"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *         <element name="Scan" type="{}ScanType"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "MediaScanType", propOrder = { + "mediaScanElement", + "scan" +}) +public class MediaScanType { + + @XmlElement(name = "MediaScanElement", required = true) + protected String mediaScanElement; + @XmlElement(name = "Scan", required = true) + protected ScanType scan; + + /** + * Obtiene el valor de la propiedad mediaScanElement. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMediaScanElement() { + return mediaScanElement; + } + + /** + * Define el valor de la propiedad mediaScanElement. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMediaScanElement(String value) { + this.mediaScanElement = value; + } + + /** + * Obtiene el valor de la propiedad scan. + * + * @return + * possible object is + * {@link ScanType } + * + */ + public ScanType getScan() { + return scan; + } + + /** + * Define el valor de la propiedad scan. + * + * @param value + * allowed object is + * {@link ScanType } + * + */ + public void setScan(ScanType value) { + this.scan = value; + } + +} diff --git a/CICMMetadata/java/generated/MultiMediaCardType.java b/CICMMetadata/java/generated/MultiMediaCardType.java new file mode 100644 index 000000000..e5d73d55d --- /dev/null +++ b/CICMMetadata/java/generated/MultiMediaCardType.java @@ -0,0 +1,155 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * Contains MultiMediaCard device information + * + *

Clase Java para MultiMediaCardType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="MultiMediaCardType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="CID" type="{}DumpType"/>
+ *         <element name="CSD" type="{}DumpType" minOccurs="0"/>
+ *         <element name="ExtendedCSD" type="{}DumpType" minOccurs="0"/>
+ *         <element name="OCR" type="{}DumpType" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "MultiMediaCardType", propOrder = { + "cid", + "csd", + "extendedCSD", + "ocr" +}) +public class MultiMediaCardType { + + @XmlElement(name = "CID", required = true) + protected DumpType cid; + @XmlElement(name = "CSD") + protected DumpType csd; + @XmlElement(name = "ExtendedCSD") + protected DumpType extendedCSD; + @XmlElement(name = "OCR") + protected DumpType ocr; + + /** + * Obtiene el valor de la propiedad cid. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getCID() { + return cid; + } + + /** + * Define el valor de la propiedad cid. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setCID(DumpType value) { + this.cid = value; + } + + /** + * Obtiene el valor de la propiedad csd. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getCSD() { + return csd; + } + + /** + * Define el valor de la propiedad csd. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setCSD(DumpType value) { + this.csd = value; + } + + /** + * Obtiene el valor de la propiedad extendedCSD. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getExtendedCSD() { + return extendedCSD; + } + + /** + * Define el valor de la propiedad extendedCSD. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setExtendedCSD(DumpType value) { + this.extendedCSD = value; + } + + /** + * Obtiene el valor de la propiedad ocr. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getOCR() { + return ocr; + } + + /** + * Define el valor de la propiedad ocr. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setOCR(DumpType value) { + this.ocr = value; + } + +} diff --git a/CICMMetadata/java/generated/OCRType.java b/CICMMetadata/java/generated/OCRType.java new file mode 100644 index 000000000..f98aabffe --- /dev/null +++ b/CICMMetadata/java/generated/OCRType.java @@ -0,0 +1,153 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para OCRType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="OCRType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Author" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Software" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="SoftwareVersion" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Language" type="{}LanguagesType"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "OCRType", propOrder = { + "author", + "software", + "softwareVersion", + "language" +}) +public class OCRType { + + @XmlElement(name = "Author", required = true) + protected String author; + @XmlElement(name = "Software", required = true) + protected String software; + @XmlElement(name = "SoftwareVersion", required = true) + protected String softwareVersion; + @XmlElement(name = "Language", required = true) + protected LanguagesType language; + + /** + * Obtiene el valor de la propiedad author. + * + * @return + * possible object is + * {@link String } + * + */ + public String getAuthor() { + return author; + } + + /** + * Define el valor de la propiedad author. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setAuthor(String value) { + this.author = value; + } + + /** + * Obtiene el valor de la propiedad software. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSoftware() { + return software; + } + + /** + * Define el valor de la propiedad software. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSoftware(String value) { + this.software = value; + } + + /** + * Obtiene el valor de la propiedad softwareVersion. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSoftwareVersion() { + return softwareVersion; + } + + /** + * Define el valor de la propiedad softwareVersion. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSoftwareVersion(String value) { + this.softwareVersion = value; + } + + /** + * Obtiene el valor de la propiedad language. + * + * @return + * possible object is + * {@link LanguagesType } + * + */ + public LanguagesType getLanguage() { + return language; + } + + /** + * Define el valor de la propiedad language. + * + * @param value + * allowed object is + * {@link LanguagesType } + * + */ + public void setLanguage(LanguagesType value) { + this.language = value; + } + +} diff --git a/CICMMetadata/java/generated/ObjectFactory.java b/CICMMetadata/java/generated/ObjectFactory.java new file mode 100644 index 000000000..3659c1363 --- /dev/null +++ b/CICMMetadata/java/generated/ObjectFactory.java @@ -0,0 +1,716 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.JAXBElement; +import javax.xml.bind.annotation.XmlElementDecl; +import javax.xml.bind.annotation.XmlRegistry; +import javax.xml.namespace.QName; + + +/** + * This object contains factory methods for each + * Java content interface and Java element interface + * generated in the generated package. + *

An ObjectFactory allows you to programatically + * construct new instances of the Java representation + * for XML content. The Java representation of XML + * content can consist of schema derived interfaces + * and classes representing the binding of schema + * type definitions, element declarations and model + * groups. Factory methods for each of these are + * provided in this class. + * + */ +@XmlRegistry +public class ObjectFactory { + + private final static QName _CICMMetadata_QNAME = new QName("", "CICMMetadata"); + + /** + * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: generated + * + */ + public ObjectFactory() { + } + + /** + * Create an instance of {@link CICMMetadataType } + * + */ + public CICMMetadataType createCICMMetadataType() { + return new CICMMetadataType(); + } + + /** + * Create an instance of {@link VideoTracksType } + * + */ + public VideoTracksType createVideoTracksType() { + return new VideoTracksType(); + } + + /** + * Create an instance of {@link CoverType } + * + */ + public CoverType createCoverType() { + return new CoverType(); + } + + /** + * Create an instance of {@link ExtentsType } + * + */ + public ExtentsType createExtentsType() { + return new ExtentsType(); + } + + /** + * Create an instance of {@link FileSystemInformationType } + * + */ + public FileSystemInformationType createFileSystemInformationType() { + return new FileSystemInformationType(); + } + + /** + * Create an instance of {@link SecuritySectorsType } + * + */ + public SecuritySectorsType createSecuritySectorsType() { + return new SecuritySectorsType(); + } + + /** + * Create an instance of {@link DumpHardwareType } + * + */ + public DumpHardwareType createDumpHardwareType() { + return new DumpHardwareType(); + } + + /** + * Create an instance of {@link ArchitecturesType } + * + */ + public ArchitecturesType createArchitecturesType() { + return new ArchitecturesType(); + } + + /** + * Create an instance of {@link FileSystemsType } + * + */ + public FileSystemsType createFileSystemsType() { + return new FileSystemsType(); + } + + /** + * Create an instance of {@link ChecksumType } + * + */ + public ChecksumType createChecksumType() { + return new ChecksumType(); + } + + /** + * Create an instance of {@link SoftwareType } + * + */ + public SoftwareType createSoftwareType() { + return new SoftwareType(); + } + + /** + * Create an instance of {@link ImageType } + * + */ + public ImageType createImageType() { + return new ImageType(); + } + + /** + * Create an instance of {@link SubtitleTracksType } + * + */ + public SubtitleTracksType createSubtitleTracksType() { + return new SubtitleTracksType(); + } + + /** + * Create an instance of {@link DirectoryType } + * + */ + public DirectoryType createDirectoryType() { + return new DirectoryType(); + } + + /** + * Create an instance of {@link TrackIndexesType } + * + */ + public TrackIndexesType createTrackIndexesType() { + return new TrackIndexesType(); + } + + /** + * Create an instance of {@link DumpHardwareArrayType } + * + */ + public DumpHardwareArrayType createDumpHardwareArrayType() { + return new DumpHardwareArrayType(); + } + + /** + * Create an instance of {@link SubChannelType } + * + */ + public SubChannelType createSubChannelType() { + return new SubChannelType(); + } + + /** + * Create an instance of {@link MediaScanType } + * + */ + public MediaScanType createMediaScanType() { + return new MediaScanType(); + } + + /** + * Create an instance of {@link SCSIType } + * + */ + public SCSIType createSCSIType() { + return new SCSIType(); + } + + /** + * Create an instance of {@link ScanProcessingType } + * + */ + public ScanProcessingType createScanProcessingType() { + return new ScanProcessingType(); + } + + /** + * Create an instance of {@link RecordingType } + * + */ + public RecordingType createRecordingType() { + return new RecordingType(); + } + + /** + * Create an instance of {@link LinearMediaType } + * + */ + public LinearMediaType createLinearMediaType() { + return new LinearMediaType(); + } + + /** + * Create an instance of {@link FilesystemContentsType } + * + */ + public FilesystemContentsType createFilesystemContentsType() { + return new FilesystemContentsType(); + } + + /** + * Create an instance of {@link RequiredOperatingSystemType } + * + */ + public RequiredOperatingSystemType createRequiredOperatingSystemType() { + return new RequiredOperatingSystemType(); + } + + /** + * Create an instance of {@link RequiredOperatingSystemsType } + * + */ + public RequiredOperatingSystemsType createRequiredOperatingSystemsType() { + return new RequiredOperatingSystemsType(); + } + + /** + * Create an instance of {@link SecureDigitalType } + * + */ + public SecureDigitalType createSecureDigitalType() { + return new SecureDigitalType(); + } + + /** + * Create an instance of {@link TapeInformationType } + * + */ + public TapeInformationType createTapeInformationType() { + return new TapeInformationType(); + } + + /** + * Create an instance of {@link TrackIndexType } + * + */ + public TrackIndexType createTrackIndexType() { + return new TrackIndexType(); + } + + /** + * Create an instance of {@link VariableBlockSizeType } + * + */ + public VariableBlockSizeType createVariableBlockSizeType() { + return new VariableBlockSizeType(); + } + + /** + * Create an instance of {@link BlockTrackType } + * + */ + public BlockTrackType createBlockTrackType() { + return new BlockTrackType(); + } + + /** + * Create an instance of {@link SystemsType } + * + */ + public SystemsType createSystemsType() { + return new SystemsType(); + } + + /** + * Create an instance of {@link TrackSequenceType } + * + */ + public TrackSequenceType createTrackSequenceType() { + return new TrackSequenceType(); + } + + /** + * Create an instance of {@link TapePartitionType } + * + */ + public TapePartitionType createTapePartitionType() { + return new TapePartitionType(); + } + + /** + * Create an instance of {@link PartitionType } + * + */ + public PartitionType createPartitionType() { + return new PartitionType(); + } + + /** + * Create an instance of {@link CaseScanType } + * + */ + public CaseScanType createCaseScanType() { + return new CaseScanType(); + } + + /** + * Create an instance of {@link TapeFileType } + * + */ + public TapeFileType createTapeFileType() { + return new TapeFileType(); + } + + /** + * Create an instance of {@link ScanType } + * + */ + public ScanType createScanType() { + return new ScanType(); + } + + /** + * Create an instance of {@link KeywordsType } + * + */ + public KeywordsType createKeywordsType() { + return new KeywordsType(); + } + + /** + * Create an instance of {@link BookType } + * + */ + public BookType createBookType() { + return new BookType(); + } + + /** + * Create an instance of {@link SubcategoriesType } + * + */ + public SubcategoriesType createSubcategoriesType() { + return new SubcategoriesType(); + } + + /** + * Create an instance of {@link CaseType } + * + */ + public CaseType createCaseType() { + return new CaseType(); + } + + /** + * Create an instance of {@link MagazineType } + * + */ + public MagazineType createMagazineType() { + return new MagazineType(); + } + + /** + * Create an instance of {@link DumpType } + * + */ + public DumpType createDumpType() { + return new DumpType(); + } + + /** + * Create an instance of {@link TrackFlagsType } + * + */ + public TrackFlagsType createTrackFlagsType() { + return new TrackFlagsType(); + } + + /** + * Create an instance of {@link LayersType } + * + */ + public LayersType createLayersType() { + return new LayersType(); + } + + /** + * Create an instance of {@link CategoriesType } + * + */ + public CategoriesType createCategoriesType() { + return new CategoriesType(); + } + + /** + * Create an instance of {@link BarcodeType } + * + */ + public BarcodeType createBarcodeType() { + return new BarcodeType(); + } + + /** + * Create an instance of {@link BorderType } + * + */ + public BorderType createBorderType() { + return new BorderType(); + } + + /** + * Create an instance of {@link ATAType } + * + */ + public ATAType createATAType() { + return new ATAType(); + } + + /** + * Create an instance of {@link LanguagesType } + * + */ + public LanguagesType createLanguagesType() { + return new LanguagesType(); + } + + /** + * Create an instance of {@link ChecksumsType } + * + */ + public ChecksumsType createChecksumsType() { + return new ChecksumsType(); + } + + /** + * Create an instance of {@link ScannerType } + * + */ + public ScannerType createScannerType() { + return new ScannerType(); + } + + /** + * Create an instance of {@link SequenceType } + * + */ + public SequenceType createSequenceType() { + return new SequenceType(); + } + + /** + * Create an instance of {@link EVPDType } + * + */ + public EVPDType createEVPDType() { + return new EVPDType(); + } + + /** + * Create an instance of {@link BlockSizeType } + * + */ + public BlockSizeType createBlockSizeType() { + return new BlockSizeType(); + } + + /** + * Create an instance of {@link OpticalDiscType } + * + */ + public OpticalDiscType createOpticalDiscType() { + return new OpticalDiscType(); + } + + /** + * Create an instance of {@link OCRType } + * + */ + public OCRType createOCRType() { + return new OCRType(); + } + + /** + * Create an instance of {@link ExtentType } + * + */ + public ExtentType createExtentType() { + return new ExtentType(); + } + + /** + * Create an instance of {@link ExtendedAttributeType } + * + */ + public ExtendedAttributeType createExtendedAttributeType() { + return new ExtendedAttributeType(); + } + + /** + * Create an instance of {@link XboxSecuritySectorsType } + * + */ + public XboxSecuritySectorsType createXboxSecuritySectorsType() { + return new XboxSecuritySectorsType(); + } + + /** + * Create an instance of {@link PCMCIAType } + * + */ + public PCMCIAType createPCMCIAType() { + return new PCMCIAType(); + } + + /** + * Create an instance of {@link ScansType } + * + */ + public ScansType createScansType() { + return new ScansType(); + } + + /** + * Create an instance of {@link PCIType } + * + */ + public PCIType createPCIType() { + return new PCIType(); + } + + /** + * Create an instance of {@link USBType } + * + */ + public USBType createUSBType() { + return new USBType(); + } + + /** + * Create an instance of {@link MultiMediaCardType } + * + */ + public MultiMediaCardType createMultiMediaCardType() { + return new MultiMediaCardType(); + } + + /** + * Create an instance of {@link UserManualType } + * + */ + public UserManualType createUserManualType() { + return new UserManualType(); + } + + /** + * Create an instance of {@link AdvertisementType } + * + */ + public AdvertisementType createAdvertisementType() { + return new AdvertisementType(); + } + + /** + * Create an instance of {@link BarcodesType } + * + */ + public BarcodesType createBarcodesType() { + return new BarcodesType(); + } + + /** + * Create an instance of {@link AudioMediaType } + * + */ + public AudioMediaType createAudioMediaType() { + return new AudioMediaType(); + } + + /** + * Create an instance of {@link ExtendedAttributesType } + * + */ + public ExtendedAttributesType createExtendedAttributesType() { + return new ExtendedAttributesType(); + } + + /** + * Create an instance of {@link CoordinatesType } + * + */ + public CoordinatesType createCoordinatesType() { + return new CoordinatesType(); + } + + /** + * Create an instance of {@link ContentsFileType } + * + */ + public ContentsFileType createContentsFileType() { + return new ContentsFileType(); + } + + /** + * Create an instance of {@link SectorsType } + * + */ + public SectorsType createSectorsType() { + return new SectorsType(); + } + + /** + * Create an instance of {@link AudioTracksType } + * + */ + public AudioTracksType createAudioTracksType() { + return new AudioTracksType(); + } + + /** + * Create an instance of {@link LayeredTextType } + * + */ + public LayeredTextType createLayeredTextType() { + return new LayeredTextType(); + } + + /** + * Create an instance of {@link BlockMediaType } + * + */ + public BlockMediaType createBlockMediaType() { + return new BlockMediaType(); + } + + /** + * Create an instance of {@link FileType } + * + */ + public FileType createFileType() { + return new FileType(); + } + + /** + * Create an instance of {@link DimensionsType } + * + */ + public DimensionsType createDimensionsType() { + return new DimensionsType(); + } + + /** + * Create an instance of {@link TrackType } + * + */ + public TrackType createTrackType() { + return new TrackType(); + } + + /** + * Create an instance of {@link FileSystemType } + * + */ + public FileSystemType createFileSystemType() { + return new FileSystemType(); + } + + /** + * Create an instance of {@link XboxType } + * + */ + public XboxType createXboxType() { + return new XboxType(); + } + + /** + * Create an instance of {@link PS3EncryptionType } + * + */ + public PS3EncryptionType createPS3EncryptionType() { + return new PS3EncryptionType(); + } + + /** + * Create an instance of {@link AudioBlockType } + * + */ + public AudioBlockType createAudioBlockType() { + return new AudioBlockType(); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link CICMMetadataType }{@code >}} + * + */ + @XmlElementDecl(namespace = "", name = "CICMMetadata") + public JAXBElement createCICMMetadata(CICMMetadataType value) { + return new JAXBElement(_CICMMetadata_QNAME, CICMMetadataType.class, null, value); + } + +} diff --git a/CICMMetadata/java/generated/OpticalDiscType.java b/CICMMetadata/java/generated/OpticalDiscType.java new file mode 100644 index 000000000..4084b01dd --- /dev/null +++ b/CICMMetadata/java/generated/OpticalDiscType.java @@ -0,0 +1,1406 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para OpticalDiscType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="OpticalDiscType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Image" type="{}ImageType"/>
+ *         <element name="Size" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="Sequence" type="{}SequenceType"/>
+ *         <element name="Layers" type="{}LayersType" minOccurs="0"/>
+ *         <element name="Checksums" type="{}ChecksumsType"/>
+ *         <element name="PartNumber" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="SerialNumber" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="RingCode" type="{}LayeredTextType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="MasteringSID" type="{}LayeredTextType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="Toolstamp" type="{}LayeredTextType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="MouldSID" type="{}LayeredTextType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="MouldText" type="{}LayeredTextType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="DiscType" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="DiscSubType" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Offset" type="{http://www.w3.org/2001/XMLSchema}int" minOccurs="0"/>
+ *         <element name="Tracks" type="{http://www.w3.org/2001/XMLSchema}unsignedInt" maxOccurs="unbounded"/>
+ *         <element name="Sessions" type="{http://www.w3.org/2001/XMLSchema}unsignedInt"/>
+ *         <element name="CopyProtection" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Dimensions" type="{}DimensionsType"/>
+ *         <element name="Case" type="{}CaseType" minOccurs="0"/>
+ *         <element name="Scans" type="{}ScansType" minOccurs="0"/>
+ *         <element name="PFI" type="{}DumpType" minOccurs="0"/>
+ *         <element name="DMI" type="{}DumpType" minOccurs="0"/>
+ *         <element name="CMI" type="{}DumpType" minOccurs="0"/>
+ *         <element name="BCA" type="{}DumpType" minOccurs="0"/>
+ *         <element name="ATIP" type="{}DumpType" minOccurs="0"/>
+ *         <element name="ADIP" type="{}DumpType" minOccurs="0"/>
+ *         <element name="PMA" type="{}DumpType" minOccurs="0"/>
+ *         <element name="DDS" type="{}DumpType" minOccurs="0"/>
+ *         <element name="SAI" type="{}DumpType" minOccurs="0"/>
+ *         <element name="LastRMD" type="{}DumpType" minOccurs="0"/>
+ *         <element name="PRI" type="{}DumpType" minOccurs="0"/>
+ *         <element name="MediaID" type="{}DumpType" minOccurs="0"/>
+ *         <element name="PFIR" type="{}DumpType" minOccurs="0"/>
+ *         <element name="DCB" type="{}DumpType" minOccurs="0"/>
+ *         <element name="DI" type="{}DumpType" minOccurs="0"/>
+ *         <element name="PAC" type="{}DumpType" minOccurs="0"/>
+ *         <element name="TOC" type="{}DumpType" minOccurs="0"/>
+ *         <element name="LeadInCdText" type="{}DumpType" minOccurs="0"/>
+ *         <element name="FirstTrackPregrap" type="{}BorderType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="LeadIn" type="{}BorderType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="LeadOut" type="{}BorderType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="Xbox" type="{}XboxType" minOccurs="0"/>
+ *         <element name="PS3Encryption" type="{}PS3EncryptionType" minOccurs="0"/>
+ *         <element name="MediaCatalogueNumber" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Track" type="{}TrackType" maxOccurs="unbounded"/>
+ *         <element name="DumpHardwareArray" type="{}DumpHardwareArrayType" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "OpticalDiscType", propOrder = { + "image", + "size", + "sequence", + "layers", + "checksums", + "partNumber", + "serialNumber", + "ringCode", + "masteringSID", + "toolstamp", + "mouldSID", + "mouldText", + "discType", + "discSubType", + "offset", + "tracks", + "sessions", + "copyProtection", + "dimensions", + "_case", + "scans", + "pfi", + "dmi", + "cmi", + "bca", + "atip", + "adip", + "pma", + "dds", + "sai", + "lastRMD", + "pri", + "mediaID", + "pfir", + "dcb", + "di", + "pac", + "toc", + "leadInCdText", + "firstTrackPregrap", + "leadIn", + "leadOut", + "xbox", + "ps3Encryption", + "mediaCatalogueNumber", + "track", + "dumpHardwareArray" +}) +public class OpticalDiscType { + + @XmlElement(name = "Image", required = true) + protected ImageType image; + @XmlElement(name = "Size", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger size; + @XmlElement(name = "Sequence", required = true) + protected SequenceType sequence; + @XmlElement(name = "Layers") + protected LayersType layers; + @XmlElement(name = "Checksums", required = true) + protected ChecksumsType checksums; + @XmlElement(name = "PartNumber") + protected String partNumber; + @XmlElement(name = "SerialNumber") + protected String serialNumber; + @XmlElement(name = "RingCode") + protected List ringCode; + @XmlElement(name = "MasteringSID") + protected List masteringSID; + @XmlElement(name = "Toolstamp") + protected List toolstamp; + @XmlElement(name = "MouldSID") + protected List mouldSID; + @XmlElement(name = "MouldText") + protected List mouldText; + @XmlElement(name = "DiscType", required = true) + protected String discType; + @XmlElement(name = "DiscSubType", required = true) + protected String discSubType; + @XmlElement(name = "Offset") + protected Integer offset; + @XmlElement(name = "Tracks", type = Long.class) + @XmlSchemaType(name = "unsignedInt") + protected List tracks; + @XmlElement(name = "Sessions") + @XmlSchemaType(name = "unsignedInt") + protected long sessions; + @XmlElement(name = "CopyProtection") + protected String copyProtection; + @XmlElement(name = "Dimensions", required = true) + protected DimensionsType dimensions; + @XmlElement(name = "Case") + protected CaseType _case; + @XmlElement(name = "Scans") + protected ScansType scans; + @XmlElement(name = "PFI") + protected DumpType pfi; + @XmlElement(name = "DMI") + protected DumpType dmi; + @XmlElement(name = "CMI") + protected DumpType cmi; + @XmlElement(name = "BCA") + protected DumpType bca; + @XmlElement(name = "ATIP") + protected DumpType atip; + @XmlElement(name = "ADIP") + protected DumpType adip; + @XmlElement(name = "PMA") + protected DumpType pma; + @XmlElement(name = "DDS") + protected DumpType dds; + @XmlElement(name = "SAI") + protected DumpType sai; + @XmlElement(name = "LastRMD") + protected DumpType lastRMD; + @XmlElement(name = "PRI") + protected DumpType pri; + @XmlElement(name = "MediaID") + protected DumpType mediaID; + @XmlElement(name = "PFIR") + protected DumpType pfir; + @XmlElement(name = "DCB") + protected DumpType dcb; + @XmlElement(name = "DI") + protected DumpType di; + @XmlElement(name = "PAC") + protected DumpType pac; + @XmlElement(name = "TOC") + protected DumpType toc; + @XmlElement(name = "LeadInCdText") + protected DumpType leadInCdText; + @XmlElement(name = "FirstTrackPregrap") + protected List firstTrackPregrap; + @XmlElement(name = "LeadIn") + protected List leadIn; + @XmlElement(name = "LeadOut") + protected List leadOut; + @XmlElement(name = "Xbox") + protected XboxType xbox; + @XmlElement(name = "PS3Encryption") + protected PS3EncryptionType ps3Encryption; + @XmlElement(name = "MediaCatalogueNumber") + protected String mediaCatalogueNumber; + @XmlElement(name = "Track", required = true) + protected List track; + @XmlElement(name = "DumpHardwareArray") + protected DumpHardwareArrayType dumpHardwareArray; + + /** + * Obtiene el valor de la propiedad image. + * + * @return + * possible object is + * {@link ImageType } + * + */ + public ImageType getImage() { + return image; + } + + /** + * Define el valor de la propiedad image. + * + * @param value + * allowed object is + * {@link ImageType } + * + */ + public void setImage(ImageType value) { + this.image = value; + } + + /** + * Obtiene el valor de la propiedad size. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getSize() { + return size; + } + + /** + * Define el valor de la propiedad size. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setSize(BigInteger value) { + this.size = value; + } + + /** + * Obtiene el valor de la propiedad sequence. + * + * @return + * possible object is + * {@link SequenceType } + * + */ + public SequenceType getSequence() { + return sequence; + } + + /** + * Define el valor de la propiedad sequence. + * + * @param value + * allowed object is + * {@link SequenceType } + * + */ + public void setSequence(SequenceType value) { + this.sequence = value; + } + + /** + * Obtiene el valor de la propiedad layers. + * + * @return + * possible object is + * {@link LayersType } + * + */ + public LayersType getLayers() { + return layers; + } + + /** + * Define el valor de la propiedad layers. + * + * @param value + * allowed object is + * {@link LayersType } + * + */ + public void setLayers(LayersType value) { + this.layers = value; + } + + /** + * Obtiene el valor de la propiedad checksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getChecksums() { + return checksums; + } + + /** + * Define el valor de la propiedad checksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setChecksums(ChecksumsType value) { + this.checksums = value; + } + + /** + * Obtiene el valor de la propiedad partNumber. + * + * @return + * possible object is + * {@link String } + * + */ + public String getPartNumber() { + return partNumber; + } + + /** + * Define el valor de la propiedad partNumber. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setPartNumber(String value) { + this.partNumber = value; + } + + /** + * Obtiene el valor de la propiedad serialNumber. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSerialNumber() { + return serialNumber; + } + + /** + * Define el valor de la propiedad serialNumber. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSerialNumber(String value) { + this.serialNumber = value; + } + + /** + * Gets the value of the ringCode property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the ringCode property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getRingCode().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link LayeredTextType } + * + * + */ + public List getRingCode() { + if (ringCode == null) { + ringCode = new ArrayList(); + } + return this.ringCode; + } + + /** + * Gets the value of the masteringSID property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the masteringSID property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getMasteringSID().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link LayeredTextType } + * + * + */ + public List getMasteringSID() { + if (masteringSID == null) { + masteringSID = new ArrayList(); + } + return this.masteringSID; + } + + /** + * Gets the value of the toolstamp property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the toolstamp property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getToolstamp().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link LayeredTextType } + * + * + */ + public List getToolstamp() { + if (toolstamp == null) { + toolstamp = new ArrayList(); + } + return this.toolstamp; + } + + /** + * Gets the value of the mouldSID property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the mouldSID property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getMouldSID().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link LayeredTextType } + * + * + */ + public List getMouldSID() { + if (mouldSID == null) { + mouldSID = new ArrayList(); + } + return this.mouldSID; + } + + /** + * Gets the value of the mouldText property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the mouldText property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getMouldText().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link LayeredTextType } + * + * + */ + public List getMouldText() { + if (mouldText == null) { + mouldText = new ArrayList(); + } + return this.mouldText; + } + + /** + * Obtiene el valor de la propiedad discType. + * + * @return + * possible object is + * {@link String } + * + */ + public String getDiscType() { + return discType; + } + + /** + * Define el valor de la propiedad discType. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setDiscType(String value) { + this.discType = value; + } + + /** + * Obtiene el valor de la propiedad discSubType. + * + * @return + * possible object is + * {@link String } + * + */ + public String getDiscSubType() { + return discSubType; + } + + /** + * Define el valor de la propiedad discSubType. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setDiscSubType(String value) { + this.discSubType = value; + } + + /** + * Obtiene el valor de la propiedad offset. + * + * @return + * possible object is + * {@link Integer } + * + */ + public Integer getOffset() { + return offset; + } + + /** + * Define el valor de la propiedad offset. + * + * @param value + * allowed object is + * {@link Integer } + * + */ + public void setOffset(Integer value) { + this.offset = value; + } + + /** + * Gets the value of the tracks property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the tracks property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getTracks().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link Long } + * + * + */ + public List getTracks() { + if (tracks == null) { + tracks = new ArrayList(); + } + return this.tracks; + } + + /** + * Obtiene el valor de la propiedad sessions. + * + */ + public long getSessions() { + return sessions; + } + + /** + * Define el valor de la propiedad sessions. + * + */ + public void setSessions(long value) { + this.sessions = value; + } + + /** + * Obtiene el valor de la propiedad copyProtection. + * + * @return + * possible object is + * {@link String } + * + */ + public String getCopyProtection() { + return copyProtection; + } + + /** + * Define el valor de la propiedad copyProtection. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setCopyProtection(String value) { + this.copyProtection = value; + } + + /** + * Obtiene el valor de la propiedad dimensions. + * + * @return + * possible object is + * {@link DimensionsType } + * + */ + public DimensionsType getDimensions() { + return dimensions; + } + + /** + * Define el valor de la propiedad dimensions. + * + * @param value + * allowed object is + * {@link DimensionsType } + * + */ + public void setDimensions(DimensionsType value) { + this.dimensions = value; + } + + /** + * Obtiene el valor de la propiedad case. + * + * @return + * possible object is + * {@link CaseType } + * + */ + public CaseType getCase() { + return _case; + } + + /** + * Define el valor de la propiedad case. + * + * @param value + * allowed object is + * {@link CaseType } + * + */ + public void setCase(CaseType value) { + this._case = value; + } + + /** + * Obtiene el valor de la propiedad scans. + * + * @return + * possible object is + * {@link ScansType } + * + */ + public ScansType getScans() { + return scans; + } + + /** + * Define el valor de la propiedad scans. + * + * @param value + * allowed object is + * {@link ScansType } + * + */ + public void setScans(ScansType value) { + this.scans = value; + } + + /** + * Obtiene el valor de la propiedad pfi. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getPFI() { + return pfi; + } + + /** + * Define el valor de la propiedad pfi. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setPFI(DumpType value) { + this.pfi = value; + } + + /** + * Obtiene el valor de la propiedad dmi. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getDMI() { + return dmi; + } + + /** + * Define el valor de la propiedad dmi. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setDMI(DumpType value) { + this.dmi = value; + } + + /** + * Obtiene el valor de la propiedad cmi. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getCMI() { + return cmi; + } + + /** + * Define el valor de la propiedad cmi. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setCMI(DumpType value) { + this.cmi = value; + } + + /** + * Obtiene el valor de la propiedad bca. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getBCA() { + return bca; + } + + /** + * Define el valor de la propiedad bca. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setBCA(DumpType value) { + this.bca = value; + } + + /** + * Obtiene el valor de la propiedad atip. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getATIP() { + return atip; + } + + /** + * Define el valor de la propiedad atip. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setATIP(DumpType value) { + this.atip = value; + } + + /** + * Obtiene el valor de la propiedad adip. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getADIP() { + return adip; + } + + /** + * Define el valor de la propiedad adip. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setADIP(DumpType value) { + this.adip = value; + } + + /** + * Obtiene el valor de la propiedad pma. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getPMA() { + return pma; + } + + /** + * Define el valor de la propiedad pma. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setPMA(DumpType value) { + this.pma = value; + } + + /** + * Obtiene el valor de la propiedad dds. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getDDS() { + return dds; + } + + /** + * Define el valor de la propiedad dds. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setDDS(DumpType value) { + this.dds = value; + } + + /** + * Obtiene el valor de la propiedad sai. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getSAI() { + return sai; + } + + /** + * Define el valor de la propiedad sai. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setSAI(DumpType value) { + this.sai = value; + } + + /** + * Obtiene el valor de la propiedad lastRMD. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getLastRMD() { + return lastRMD; + } + + /** + * Define el valor de la propiedad lastRMD. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setLastRMD(DumpType value) { + this.lastRMD = value; + } + + /** + * Obtiene el valor de la propiedad pri. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getPRI() { + return pri; + } + + /** + * Define el valor de la propiedad pri. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setPRI(DumpType value) { + this.pri = value; + } + + /** + * Obtiene el valor de la propiedad mediaID. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getMediaID() { + return mediaID; + } + + /** + * Define el valor de la propiedad mediaID. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setMediaID(DumpType value) { + this.mediaID = value; + } + + /** + * Obtiene el valor de la propiedad pfir. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getPFIR() { + return pfir; + } + + /** + * Define el valor de la propiedad pfir. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setPFIR(DumpType value) { + this.pfir = value; + } + + /** + * Obtiene el valor de la propiedad dcb. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getDCB() { + return dcb; + } + + /** + * Define el valor de la propiedad dcb. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setDCB(DumpType value) { + this.dcb = value; + } + + /** + * Obtiene el valor de la propiedad di. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getDI() { + return di; + } + + /** + * Define el valor de la propiedad di. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setDI(DumpType value) { + this.di = value; + } + + /** + * Obtiene el valor de la propiedad pac. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getPAC() { + return pac; + } + + /** + * Define el valor de la propiedad pac. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setPAC(DumpType value) { + this.pac = value; + } + + /** + * Obtiene el valor de la propiedad toc. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getTOC() { + return toc; + } + + /** + * Define el valor de la propiedad toc. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setTOC(DumpType value) { + this.toc = value; + } + + /** + * Obtiene el valor de la propiedad leadInCdText. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getLeadInCdText() { + return leadInCdText; + } + + /** + * Define el valor de la propiedad leadInCdText. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setLeadInCdText(DumpType value) { + this.leadInCdText = value; + } + + /** + * Gets the value of the firstTrackPregrap property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the firstTrackPregrap property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getFirstTrackPregrap().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link BorderType } + * + * + */ + public List getFirstTrackPregrap() { + if (firstTrackPregrap == null) { + firstTrackPregrap = new ArrayList(); + } + return this.firstTrackPregrap; + } + + /** + * Gets the value of the leadIn property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the leadIn property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getLeadIn().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link BorderType } + * + * + */ + public List getLeadIn() { + if (leadIn == null) { + leadIn = new ArrayList(); + } + return this.leadIn; + } + + /** + * Gets the value of the leadOut property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the leadOut property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getLeadOut().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link BorderType } + * + * + */ + public List getLeadOut() { + if (leadOut == null) { + leadOut = new ArrayList(); + } + return this.leadOut; + } + + /** + * Obtiene el valor de la propiedad xbox. + * + * @return + * possible object is + * {@link XboxType } + * + */ + public XboxType getXbox() { + return xbox; + } + + /** + * Define el valor de la propiedad xbox. + * + * @param value + * allowed object is + * {@link XboxType } + * + */ + public void setXbox(XboxType value) { + this.xbox = value; + } + + /** + * Obtiene el valor de la propiedad ps3Encryption. + * + * @return + * possible object is + * {@link PS3EncryptionType } + * + */ + public PS3EncryptionType getPS3Encryption() { + return ps3Encryption; + } + + /** + * Define el valor de la propiedad ps3Encryption. + * + * @param value + * allowed object is + * {@link PS3EncryptionType } + * + */ + public void setPS3Encryption(PS3EncryptionType value) { + this.ps3Encryption = value; + } + + /** + * Obtiene el valor de la propiedad mediaCatalogueNumber. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMediaCatalogueNumber() { + return mediaCatalogueNumber; + } + + /** + * Define el valor de la propiedad mediaCatalogueNumber. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMediaCatalogueNumber(String value) { + this.mediaCatalogueNumber = value; + } + + /** + * Gets the value of the track property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the track property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getTrack().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link TrackType } + * + * + */ + public List getTrack() { + if (track == null) { + track = new ArrayList(); + } + return this.track; + } + + /** + * Obtiene el valor de la propiedad dumpHardwareArray. + * + * @return + * possible object is + * {@link DumpHardwareArrayType } + * + */ + public DumpHardwareArrayType getDumpHardwareArray() { + return dumpHardwareArray; + } + + /** + * Define el valor de la propiedad dumpHardwareArray. + * + * @param value + * allowed object is + * {@link DumpHardwareArrayType } + * + */ + public void setDumpHardwareArray(DumpHardwareArrayType value) { + this.dumpHardwareArray = value; + } + +} diff --git a/CICMMetadata/java/generated/PCIType.java b/CICMMetadata/java/generated/PCIType.java new file mode 100644 index 000000000..c1063054d --- /dev/null +++ b/CICMMetadata/java/generated/PCIType.java @@ -0,0 +1,153 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * Contains PCI/PCI-X/PCIe card information + * + *

Clase Java para PCIType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="PCIType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="VendorID">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}unsignedShort">
+ *               <minInclusive value="1"/>
+ *               <maxInclusive value="65534"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *         <element name="DeviceID">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}unsignedShort">
+ *               <minInclusive value="1"/>
+ *               <maxInclusive value="65534"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *         <element name="Configuration" type="{}DumpType" minOccurs="0"/>
+ *         <element name="ExpansionROM" type="{}LinearMediaType" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "PCIType", propOrder = { + "vendorID", + "deviceID", + "configuration", + "expansionROM" +}) +public class PCIType { + + @XmlElement(name = "VendorID") + protected int vendorID; + @XmlElement(name = "DeviceID") + protected int deviceID; + @XmlElement(name = "Configuration") + protected DumpType configuration; + @XmlElement(name = "ExpansionROM") + protected LinearMediaType expansionROM; + + /** + * Obtiene el valor de la propiedad vendorID. + * + */ + public int getVendorID() { + return vendorID; + } + + /** + * Define el valor de la propiedad vendorID. + * + */ + public void setVendorID(int value) { + this.vendorID = value; + } + + /** + * Obtiene el valor de la propiedad deviceID. + * + */ + public int getDeviceID() { + return deviceID; + } + + /** + * Define el valor de la propiedad deviceID. + * + */ + public void setDeviceID(int value) { + this.deviceID = value; + } + + /** + * Obtiene el valor de la propiedad configuration. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getConfiguration() { + return configuration; + } + + /** + * Define el valor de la propiedad configuration. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setConfiguration(DumpType value) { + this.configuration = value; + } + + /** + * Obtiene el valor de la propiedad expansionROM. + * + * @return + * possible object is + * {@link LinearMediaType } + * + */ + public LinearMediaType getExpansionROM() { + return expansionROM; + } + + /** + * Define el valor de la propiedad expansionROM. + * + * @param value + * allowed object is + * {@link LinearMediaType } + * + */ + public void setExpansionROM(LinearMediaType value) { + this.expansionROM = value; + } + +} diff --git a/CICMMetadata/java/generated/PCMCIAType.java b/CICMMetadata/java/generated/PCMCIAType.java new file mode 100644 index 000000000..0b40c6bcb --- /dev/null +++ b/CICMMetadata/java/generated/PCMCIAType.java @@ -0,0 +1,249 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * Contains PCMCIA card information + * + *

Clase Java para PCMCIAType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="PCMCIAType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="CIS" type="{}DumpType"/>
+ *         <element name="Compliance" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="ManufacturerCode" type="{http://www.w3.org/2001/XMLSchema}unsignedShort" minOccurs="0"/>
+ *         <element name="CardCode" type="{http://www.w3.org/2001/XMLSchema}unsignedShort" minOccurs="0"/>
+ *         <element name="Manufacturer" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="ProductName" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="AdditionalInformation" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "PCMCIAType", propOrder = { + "cis", + "compliance", + "manufacturerCode", + "cardCode", + "manufacturer", + "productName", + "additionalInformation" +}) +public class PCMCIAType { + + @XmlElement(name = "CIS", required = true) + protected DumpType cis; + @XmlElement(name = "Compliance") + protected String compliance; + @XmlElement(name = "ManufacturerCode") + @XmlSchemaType(name = "unsignedShort") + protected Integer manufacturerCode; + @XmlElement(name = "CardCode") + @XmlSchemaType(name = "unsignedShort") + protected Integer cardCode; + @XmlElement(name = "Manufacturer") + protected String manufacturer; + @XmlElement(name = "ProductName") + protected String productName; + @XmlElement(name = "AdditionalInformation") + protected List additionalInformation; + + /** + * Obtiene el valor de la propiedad cis. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getCIS() { + return cis; + } + + /** + * Define el valor de la propiedad cis. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setCIS(DumpType value) { + this.cis = value; + } + + /** + * Obtiene el valor de la propiedad compliance. + * + * @return + * possible object is + * {@link String } + * + */ + public String getCompliance() { + return compliance; + } + + /** + * Define el valor de la propiedad compliance. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setCompliance(String value) { + this.compliance = value; + } + + /** + * Obtiene el valor de la propiedad manufacturerCode. + * + * @return + * possible object is + * {@link Integer } + * + */ + public Integer getManufacturerCode() { + return manufacturerCode; + } + + /** + * Define el valor de la propiedad manufacturerCode. + * + * @param value + * allowed object is + * {@link Integer } + * + */ + public void setManufacturerCode(Integer value) { + this.manufacturerCode = value; + } + + /** + * Obtiene el valor de la propiedad cardCode. + * + * @return + * possible object is + * {@link Integer } + * + */ + public Integer getCardCode() { + return cardCode; + } + + /** + * Define el valor de la propiedad cardCode. + * + * @param value + * allowed object is + * {@link Integer } + * + */ + public void setCardCode(Integer value) { + this.cardCode = value; + } + + /** + * Obtiene el valor de la propiedad manufacturer. + * + * @return + * possible object is + * {@link String } + * + */ + public String getManufacturer() { + return manufacturer; + } + + /** + * Define el valor de la propiedad manufacturer. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setManufacturer(String value) { + this.manufacturer = value; + } + + /** + * Obtiene el valor de la propiedad productName. + * + * @return + * possible object is + * {@link String } + * + */ + public String getProductName() { + return productName; + } + + /** + * Define el valor de la propiedad productName. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setProductName(String value) { + this.productName = value; + } + + /** + * Gets the value of the additionalInformation property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the additionalInformation property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getAdditionalInformation().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link String } + * + * + */ + public List getAdditionalInformation() { + if (additionalInformation == null) { + additionalInformation = new ArrayList(); + } + return this.additionalInformation; + } + +} diff --git a/CICMMetadata/java/generated/PS3EncryptionType.java b/CICMMetadata/java/generated/PS3EncryptionType.java new file mode 100644 index 000000000..22c10cf64 --- /dev/null +++ b/CICMMetadata/java/generated/PS3EncryptionType.java @@ -0,0 +1,97 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para PS3EncryptionType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="PS3EncryptionType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Key" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Serial" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "PS3EncryptionType", propOrder = { + "key", + "serial" +}) +public class PS3EncryptionType { + + @XmlElement(name = "Key", required = true) + protected String key; + @XmlElement(name = "Serial", required = true) + protected String serial; + + /** + * Obtiene el valor de la propiedad key. + * + * @return + * possible object is + * {@link String } + * + */ + public String getKey() { + return key; + } + + /** + * Define el valor de la propiedad key. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setKey(String value) { + this.key = value; + } + + /** + * Obtiene el valor de la propiedad serial. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSerial() { + return serial; + } + + /** + * Define el valor de la propiedad serial. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSerial(String value) { + this.serial = value; + } + +} diff --git a/CICMMetadata/java/generated/PartitionType.java b/CICMMetadata/java/generated/PartitionType.java new file mode 100644 index 000000000..a876b9e77 --- /dev/null +++ b/CICMMetadata/java/generated/PartitionType.java @@ -0,0 +1,239 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para PartitionType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="PartitionType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Sequence">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}unsignedInt">
+ *               <minInclusive value="1"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *         <element name="Name" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Type" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="StartSector" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="EndSector" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="Description" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="FileSystems" type="{}FileSystemsType"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "PartitionType", propOrder = { + "sequence", + "name", + "type", + "startSector", + "endSector", + "description", + "fileSystems" +}) +public class PartitionType { + + @XmlElement(name = "Sequence") + protected long sequence; + @XmlElement(name = "Name") + protected String name; + @XmlElement(name = "Type") + protected String type; + @XmlElement(name = "StartSector", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger startSector; + @XmlElement(name = "EndSector", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger endSector; + @XmlElement(name = "Description") + protected String description; + @XmlElement(name = "FileSystems", required = true) + protected FileSystemsType fileSystems; + + /** + * Obtiene el valor de la propiedad sequence. + * + */ + public long getSequence() { + return sequence; + } + + /** + * Define el valor de la propiedad sequence. + * + */ + public void setSequence(long value) { + this.sequence = value; + } + + /** + * Obtiene el valor de la propiedad name. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Define el valor de la propiedad name. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + /** + * Obtiene el valor de la propiedad type. + * + * @return + * possible object is + * {@link String } + * + */ + public String getType() { + return type; + } + + /** + * Define el valor de la propiedad type. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setType(String value) { + this.type = value; + } + + /** + * Obtiene el valor de la propiedad startSector. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getStartSector() { + return startSector; + } + + /** + * Define el valor de la propiedad startSector. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setStartSector(BigInteger value) { + this.startSector = value; + } + + /** + * Obtiene el valor de la propiedad endSector. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getEndSector() { + return endSector; + } + + /** + * Define el valor de la propiedad endSector. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setEndSector(BigInteger value) { + this.endSector = value; + } + + /** + * Obtiene el valor de la propiedad description. + * + * @return + * possible object is + * {@link String } + * + */ + public String getDescription() { + return description; + } + + /** + * Define el valor de la propiedad description. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setDescription(String value) { + this.description = value; + } + + /** + * Obtiene el valor de la propiedad fileSystems. + * + * @return + * possible object is + * {@link FileSystemsType } + * + */ + public FileSystemsType getFileSystems() { + return fileSystems; + } + + /** + * Define el valor de la propiedad fileSystems. + * + * @param value + * allowed object is + * {@link FileSystemsType } + * + */ + public void setFileSystems(FileSystemsType value) { + this.fileSystems = value; + } + +} diff --git a/CICMMetadata/java/generated/RecordingType.java b/CICMMetadata/java/generated/RecordingType.java new file mode 100644 index 000000000..1267e5d0d --- /dev/null +++ b/CICMMetadata/java/generated/RecordingType.java @@ -0,0 +1,292 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; +import javax.xml.datatype.XMLGregorianCalendar; + + +/** + *

Clase Java para RecordingType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="RecordingType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Broadcaster" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="BroadcastPlatform" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="SourceFormat">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ *               <enumeration value="ITU-A"/>
+ *               <enumeration value="ITU-B"/>
+ *               <enumeration value="ITU-C"/>
+ *               <enumeration value="ITU-D"/>
+ *               <enumeration value="ITU-E"/>
+ *               <enumeration value="ITU-F"/>
+ *               <enumeration value="ITU-G"/>
+ *               <enumeration value="ITU-H"/>
+ *               <enumeration value="ITU-I"/>
+ *               <enumeration value="ITU-J"/>
+ *               <enumeration value="ITU-K"/>
+ *               <enumeration value="ITU-L"/>
+ *               <enumeration value="ITU-M"/>
+ *               <enumeration value="ITU-N"/>
+ *               <enumeration value="PAL-B"/>
+ *               <enumeration value="SECAM-B"/>
+ *               <enumeration value="PAL-D"/>
+ *               <enumeration value="SECAM-D"/>
+ *               <enumeration value="PAL-G"/>
+ *               <enumeration value="SECAM-G"/>
+ *               <enumeration value="PAL-H"/>
+ *               <enumeration value="PAL-I"/>
+ *               <enumeration value="PAL-K"/>
+ *               <enumeration value="SECAM-K"/>
+ *               <enumeration value="NTSC-M"/>
+ *               <enumeration value="PAL-N"/>
+ *               <enumeration value="PAL-M"/>
+ *               <enumeration value="SECAM-M"/>
+ *               <enumeration value="MUSE"/>
+ *               <enumeration value="PALplus"/>
+ *               <enumeration value="FM"/>
+ *               <enumeration value="AM"/>
+ *               <enumeration value="COFDM"/>
+ *               <enumeration value="CAM-D"/>
+ *               <enumeration value="DAB"/>
+ *               <enumeration value="DAB+"/>
+ *               <enumeration value="DRM"/>
+ *               <enumeration value="DRM+"/>
+ *               <enumeration value="FMeXtra"/>
+ *               <enumeration value="ATSC"/>
+ *               <enumeration value="ATSC2"/>
+ *               <enumeration value="ATSC3"/>
+ *               <enumeration value="ATSC-M/H"/>
+ *               <enumeration value="DVB-T"/>
+ *               <enumeration value="DVB-T2"/>
+ *               <enumeration value="DVB-S"/>
+ *               <enumeration value="DVB-S2"/>
+ *               <enumeration value="DVB-S2X"/>
+ *               <enumeration value="DVB-C"/>
+ *               <enumeration value="DVB-C2"/>
+ *               <enumeration value="DVB-H"/>
+ *               <enumeration value="DVB-NGH"/>
+ *               <enumeration value="DVB-SH"/>
+ *               <enumeration value="ISDB-T"/>
+ *               <enumeration value="ISDB-Tb"/>
+ *               <enumeration value="ISDB-S"/>
+ *               <enumeration value="ISDB-C"/>
+ *               <enumeration value="1seg"/>
+ *               <enumeration value="DTMB"/>
+ *               <enumeration value="CCMB"/>
+ *               <enumeration value="T-DMB"/>
+ *               <enumeration value="S-DMB"/>
+ *               <enumeration value="IPTV"/>
+ *               <enumeration value="DVB-MT"/>
+ *               <enumeration value="DVB-MC"/>
+ *               <enumeration value="DVB-MS"/>
+ *               <enumeration value="ADR"/>
+ *               <enumeration value="SDR"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *         <element name="Timestamp" type="{http://www.w3.org/2001/XMLSchema}dateTime"/>
+ *         <element name="Software" type="{}SoftwareType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="Coordinates" type="{}CoordinatesType" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "RecordingType", propOrder = { + "broadcaster", + "broadcastPlatform", + "sourceFormat", + "timestamp", + "software", + "coordinates" +}) +public class RecordingType { + + @XmlElement(name = "Broadcaster") + protected String broadcaster; + @XmlElement(name = "BroadcastPlatform") + protected String broadcastPlatform; + @XmlElement(name = "SourceFormat", required = true) + protected String sourceFormat; + @XmlElement(name = "Timestamp", required = true) + @XmlSchemaType(name = "dateTime") + protected XMLGregorianCalendar timestamp; + @XmlElement(name = "Software") + protected List software; + @XmlElement(name = "Coordinates") + protected CoordinatesType coordinates; + + /** + * Obtiene el valor de la propiedad broadcaster. + * + * @return + * possible object is + * {@link String } + * + */ + public String getBroadcaster() { + return broadcaster; + } + + /** + * Define el valor de la propiedad broadcaster. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setBroadcaster(String value) { + this.broadcaster = value; + } + + /** + * Obtiene el valor de la propiedad broadcastPlatform. + * + * @return + * possible object is + * {@link String } + * + */ + public String getBroadcastPlatform() { + return broadcastPlatform; + } + + /** + * Define el valor de la propiedad broadcastPlatform. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setBroadcastPlatform(String value) { + this.broadcastPlatform = value; + } + + /** + * Obtiene el valor de la propiedad sourceFormat. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSourceFormat() { + return sourceFormat; + } + + /** + * Define el valor de la propiedad sourceFormat. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSourceFormat(String value) { + this.sourceFormat = value; + } + + /** + * Obtiene el valor de la propiedad timestamp. + * + * @return + * possible object is + * {@link XMLGregorianCalendar } + * + */ + public XMLGregorianCalendar getTimestamp() { + return timestamp; + } + + /** + * Define el valor de la propiedad timestamp. + * + * @param value + * allowed object is + * {@link XMLGregorianCalendar } + * + */ + public void setTimestamp(XMLGregorianCalendar value) { + this.timestamp = value; + } + + /** + * Gets the value of the software property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the software property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getSoftware().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link SoftwareType } + * + * + */ + public List getSoftware() { + if (software == null) { + software = new ArrayList(); + } + return this.software; + } + + /** + * Obtiene el valor de la propiedad coordinates. + * + * @return + * possible object is + * {@link CoordinatesType } + * + */ + public CoordinatesType getCoordinates() { + return coordinates; + } + + /** + * Define el valor de la propiedad coordinates. + * + * @param value + * allowed object is + * {@link CoordinatesType } + * + */ + public void setCoordinates(CoordinatesType value) { + this.coordinates = value; + } + +} diff --git a/CICMMetadata/java/generated/RequiredOperatingSystemType.java b/CICMMetadata/java/generated/RequiredOperatingSystemType.java new file mode 100644 index 000000000..7f381d94c --- /dev/null +++ b/CICMMetadata/java/generated/RequiredOperatingSystemType.java @@ -0,0 +1,104 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para RequiredOperatingSystemType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="RequiredOperatingSystemType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Version" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "RequiredOperatingSystemType", propOrder = { + "name", + "version" +}) +public class RequiredOperatingSystemType { + + @XmlElement(name = "Name", required = true) + protected String name; + @XmlElement(name = "Version", required = true) + protected List version; + + /** + * Obtiene el valor de la propiedad name. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Define el valor de la propiedad name. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + /** + * Gets the value of the version property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the version property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getVersion().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link String } + * + * + */ + public List getVersion() { + if (version == null) { + version = new ArrayList(); + } + return this.version; + } + +} diff --git a/CICMMetadata/java/generated/RequiredOperatingSystemsType.java b/CICMMetadata/java/generated/RequiredOperatingSystemsType.java new file mode 100644 index 000000000..7a355e619 --- /dev/null +++ b/CICMMetadata/java/generated/RequiredOperatingSystemsType.java @@ -0,0 +1,76 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para RequiredOperatingSystemsType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="RequiredOperatingSystemsType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="RequiredOperatingSystem" type="{}RequiredOperatingSystemType" maxOccurs="unbounded"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "RequiredOperatingSystemsType", propOrder = { + "requiredOperatingSystem" +}) +public class RequiredOperatingSystemsType { + + @XmlElement(name = "RequiredOperatingSystem", required = true) + protected List requiredOperatingSystem; + + /** + * Gets the value of the requiredOperatingSystem property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the requiredOperatingSystem property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getRequiredOperatingSystem().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link RequiredOperatingSystemType } + * + * + */ + public List getRequiredOperatingSystem() { + if (requiredOperatingSystem == null) { + requiredOperatingSystem = new ArrayList(); + } + return this.requiredOperatingSystem; + } + +} diff --git a/CICMMetadata/java/generated/SCSIType.java b/CICMMetadata/java/generated/SCSIType.java new file mode 100644 index 000000000..6b588a48f --- /dev/null +++ b/CICMMetadata/java/generated/SCSIType.java @@ -0,0 +1,190 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * Contains SCSI device information + * + *

Clase Java para SCSIType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="SCSIType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Inquiry" type="{}DumpType"/>
+ *         <element name="EVPD" type="{}EVPDType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="ModeSense" type="{}DumpType" minOccurs="0"/>
+ *         <element name="ModeSense10" type="{}DumpType" minOccurs="0"/>
+ *         <element name="LogSense" type="{}DumpType" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "SCSIType", propOrder = { + "inquiry", + "evpd", + "modeSense", + "modeSense10", + "logSense" +}) +public class SCSIType { + + @XmlElement(name = "Inquiry", required = true) + protected DumpType inquiry; + @XmlElement(name = "EVPD") + protected List evpd; + @XmlElement(name = "ModeSense") + protected DumpType modeSense; + @XmlElement(name = "ModeSense10") + protected DumpType modeSense10; + @XmlElement(name = "LogSense") + protected DumpType logSense; + + /** + * Obtiene el valor de la propiedad inquiry. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getInquiry() { + return inquiry; + } + + /** + * Define el valor de la propiedad inquiry. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setInquiry(DumpType value) { + this.inquiry = value; + } + + /** + * Gets the value of the evpd property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the evpd property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getEVPD().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link EVPDType } + * + * + */ + public List getEVPD() { + if (evpd == null) { + evpd = new ArrayList(); + } + return this.evpd; + } + + /** + * Obtiene el valor de la propiedad modeSense. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getModeSense() { + return modeSense; + } + + /** + * Define el valor de la propiedad modeSense. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setModeSense(DumpType value) { + this.modeSense = value; + } + + /** + * Obtiene el valor de la propiedad modeSense10. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getModeSense10() { + return modeSense10; + } + + /** + * Define el valor de la propiedad modeSense10. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setModeSense10(DumpType value) { + this.modeSense10 = value; + } + + /** + * Obtiene el valor de la propiedad logSense. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getLogSense() { + return logSense; + } + + /** + * Define el valor de la propiedad logSense. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setLogSense(DumpType value) { + this.logSense = value; + } + +} diff --git a/CICMMetadata/java/generated/ScanProcessingType.java b/CICMMetadata/java/generated/ScanProcessingType.java new file mode 100644 index 000000000..e0f1d8f40 --- /dev/null +++ b/CICMMetadata/java/generated/ScanProcessingType.java @@ -0,0 +1,128 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * Information about any scan processing done + * + * + *

Clase Java para ScanProcessingType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="ScanProcessingType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Author" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Software" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="SoftwareVersion" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ScanProcessingType", propOrder = { + "author", + "software", + "softwareVersion" +}) +public class ScanProcessingType { + + @XmlElement(name = "Author", required = true) + protected String author; + @XmlElement(name = "Software", required = true) + protected String software; + @XmlElement(name = "SoftwareVersion", required = true) + protected String softwareVersion; + + /** + * Obtiene el valor de la propiedad author. + * + * @return + * possible object is + * {@link String } + * + */ + public String getAuthor() { + return author; + } + + /** + * Define el valor de la propiedad author. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setAuthor(String value) { + this.author = value; + } + + /** + * Obtiene el valor de la propiedad software. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSoftware() { + return software; + } + + /** + * Define el valor de la propiedad software. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSoftware(String value) { + this.software = value; + } + + /** + * Obtiene el valor de la propiedad softwareVersion. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSoftwareVersion() { + return softwareVersion; + } + + /** + * Define el valor de la propiedad softwareVersion. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSoftwareVersion(String value) { + this.softwareVersion = value; + } + +} diff --git a/CICMMetadata/java/generated/ScanType.java b/CICMMetadata/java/generated/ScanType.java new file mode 100644 index 000000000..c523ca21a --- /dev/null +++ b/CICMMetadata/java/generated/ScanType.java @@ -0,0 +1,198 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para ScanType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="ScanType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="File" type="{}FileType"/>
+ *         <element name="Checksums" type="{}ChecksumsType"/>
+ *         <element name="Scanner" type="{}ScannerType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="ScanProcessing" type="{}ScanProcessingType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="OCR" type="{}OCRType" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ScanType", propOrder = { + "file", + "checksums", + "scanner", + "scanProcessing", + "ocr" +}) +public class ScanType { + + @XmlElement(name = "File", required = true) + protected FileType file; + @XmlElement(name = "Checksums", required = true) + protected ChecksumsType checksums; + @XmlElement(name = "Scanner") + protected List scanner; + @XmlElement(name = "ScanProcessing") + protected List scanProcessing; + @XmlElement(name = "OCR") + protected List ocr; + + /** + * Obtiene el valor de la propiedad file. + * + * @return + * possible object is + * {@link FileType } + * + */ + public FileType getFile() { + return file; + } + + /** + * Define el valor de la propiedad file. + * + * @param value + * allowed object is + * {@link FileType } + * + */ + public void setFile(FileType value) { + this.file = value; + } + + /** + * Obtiene el valor de la propiedad checksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getChecksums() { + return checksums; + } + + /** + * Define el valor de la propiedad checksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setChecksums(ChecksumsType value) { + this.checksums = value; + } + + /** + * Gets the value of the scanner property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the scanner property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getScanner().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link ScannerType } + * + * + */ + public List getScanner() { + if (scanner == null) { + scanner = new ArrayList(); + } + return this.scanner; + } + + /** + * Gets the value of the scanProcessing property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the scanProcessing property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getScanProcessing().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link ScanProcessingType } + * + * + */ + public List getScanProcessing() { + if (scanProcessing == null) { + scanProcessing = new ArrayList(); + } + return this.scanProcessing; + } + + /** + * Gets the value of the ocr property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the ocr property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getOCR().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link OCRType } + * + * + */ + public List getOCR() { + if (ocr == null) { + ocr = new ArrayList(); + } + return this.ocr; + } + +} diff --git a/CICMMetadata/java/generated/ScannerType.java b/CICMMetadata/java/generated/ScannerType.java new file mode 100644 index 000000000..292a2af9e --- /dev/null +++ b/CICMMetadata/java/generated/ScannerType.java @@ -0,0 +1,211 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * Information about scanning + * + *

Clase Java para ScannerType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="ScannerType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Author" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Manufacturer" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Model" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Serial" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Software" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="SoftwareVersion" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ScannerType", propOrder = { + "author", + "manufacturer", + "model", + "serial", + "software", + "softwareVersion" +}) +public class ScannerType { + + @XmlElement(name = "Author", required = true) + protected String author; + @XmlElement(name = "Manufacturer", required = true) + protected String manufacturer; + @XmlElement(name = "Model", required = true) + protected String model; + @XmlElement(name = "Serial", required = true) + protected String serial; + @XmlElement(name = "Software", required = true) + protected String software; + @XmlElement(name = "SoftwareVersion", required = true) + protected String softwareVersion; + + /** + * Obtiene el valor de la propiedad author. + * + * @return + * possible object is + * {@link String } + * + */ + public String getAuthor() { + return author; + } + + /** + * Define el valor de la propiedad author. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setAuthor(String value) { + this.author = value; + } + + /** + * Obtiene el valor de la propiedad manufacturer. + * + * @return + * possible object is + * {@link String } + * + */ + public String getManufacturer() { + return manufacturer; + } + + /** + * Define el valor de la propiedad manufacturer. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setManufacturer(String value) { + this.manufacturer = value; + } + + /** + * Obtiene el valor de la propiedad model. + * + * @return + * possible object is + * {@link String } + * + */ + public String getModel() { + return model; + } + + /** + * Define el valor de la propiedad model. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setModel(String value) { + this.model = value; + } + + /** + * Obtiene el valor de la propiedad serial. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSerial() { + return serial; + } + + /** + * Define el valor de la propiedad serial. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSerial(String value) { + this.serial = value; + } + + /** + * Obtiene el valor de la propiedad software. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSoftware() { + return software; + } + + /** + * Define el valor de la propiedad software. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSoftware(String value) { + this.software = value; + } + + /** + * Obtiene el valor de la propiedad softwareVersion. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSoftwareVersion() { + return softwareVersion; + } + + /** + * Define el valor de la propiedad softwareVersion. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSoftwareVersion(String value) { + this.softwareVersion = value; + } + +} diff --git a/CICMMetadata/java/generated/ScansType.java b/CICMMetadata/java/generated/ScansType.java new file mode 100644 index 000000000..1833ae259 --- /dev/null +++ b/CICMMetadata/java/generated/ScansType.java @@ -0,0 +1,97 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para ScansType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="ScansType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="CaseScan" type="{}CaseScanType" minOccurs="0"/>
+ *         <element name="Scan" type="{}MediaScanType" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ScansType", propOrder = { + "caseScan", + "scan" +}) +public class ScansType { + + @XmlElement(name = "CaseScan") + protected CaseScanType caseScan; + @XmlElement(name = "Scan") + protected MediaScanType scan; + + /** + * Obtiene el valor de la propiedad caseScan. + * + * @return + * possible object is + * {@link CaseScanType } + * + */ + public CaseScanType getCaseScan() { + return caseScan; + } + + /** + * Define el valor de la propiedad caseScan. + * + * @param value + * allowed object is + * {@link CaseScanType } + * + */ + public void setCaseScan(CaseScanType value) { + this.caseScan = value; + } + + /** + * Obtiene el valor de la propiedad scan. + * + * @return + * possible object is + * {@link MediaScanType } + * + */ + public MediaScanType getScan() { + return scan; + } + + /** + * Define el valor de la propiedad scan. + * + * @param value + * allowed object is + * {@link MediaScanType } + * + */ + public void setScan(MediaScanType value) { + this.scan = value; + } + +} diff --git a/CICMMetadata/java/generated/SectorsType.java b/CICMMetadata/java/generated/SectorsType.java new file mode 100644 index 000000000..3a27ec9f5 --- /dev/null +++ b/CICMMetadata/java/generated/SectorsType.java @@ -0,0 +1,98 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + + +/** + *

Clase Java para SectorsType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="SectorsType">
+ *   <simpleContent>
+ *     <extension base="<http://www.w3.org/2001/XMLSchema>unsignedLong">
+ *       <attribute name="layer" type="{http://www.w3.org/2001/XMLSchema}unsignedInt" />
+ *     </extension>
+ *   </simpleContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "SectorsType", propOrder = { + "value" +}) +public class SectorsType { + + @XmlValue + @XmlSchemaType(name = "unsignedLong") + protected BigInteger value; + @XmlAttribute(name = "layer") + @XmlSchemaType(name = "unsignedInt") + protected Long layer; + + /** + * Obtiene el valor de la propiedad value. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getValue() { + return value; + } + + /** + * Define el valor de la propiedad value. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setValue(BigInteger value) { + this.value = value; + } + + /** + * Obtiene el valor de la propiedad layer. + * + * @return + * possible object is + * {@link Long } + * + */ + public Long getLayer() { + return layer; + } + + /** + * Define el valor de la propiedad layer. + * + * @param value + * allowed object is + * {@link Long } + * + */ + public void setLayer(Long value) { + this.layer = value; + } + +} diff --git a/CICMMetadata/java/generated/SecureDigitalType.java b/CICMMetadata/java/generated/SecureDigitalType.java new file mode 100644 index 000000000..8ab933784 --- /dev/null +++ b/CICMMetadata/java/generated/SecureDigitalType.java @@ -0,0 +1,155 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * Contains SecureDigital device information + * + *

Clase Java para SecureDigitalType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="SecureDigitalType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="CID" type="{}DumpType"/>
+ *         <element name="CSD" type="{}DumpType" minOccurs="0"/>
+ *         <element name="SCR" type="{}DumpType" minOccurs="0"/>
+ *         <element name="OCR" type="{}DumpType" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "SecureDigitalType", propOrder = { + "cid", + "csd", + "scr", + "ocr" +}) +public class SecureDigitalType { + + @XmlElement(name = "CID", required = true) + protected DumpType cid; + @XmlElement(name = "CSD") + protected DumpType csd; + @XmlElement(name = "SCR") + protected DumpType scr; + @XmlElement(name = "OCR") + protected DumpType ocr; + + /** + * Obtiene el valor de la propiedad cid. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getCID() { + return cid; + } + + /** + * Define el valor de la propiedad cid. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setCID(DumpType value) { + this.cid = value; + } + + /** + * Obtiene el valor de la propiedad csd. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getCSD() { + return csd; + } + + /** + * Define el valor de la propiedad csd. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setCSD(DumpType value) { + this.csd = value; + } + + /** + * Obtiene el valor de la propiedad scr. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getSCR() { + return scr; + } + + /** + * Define el valor de la propiedad scr. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setSCR(DumpType value) { + this.scr = value; + } + + /** + * Obtiene el valor de la propiedad ocr. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getOCR() { + return ocr; + } + + /** + * Define el valor de la propiedad ocr. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setOCR(DumpType value) { + this.ocr = value; + } + +} diff --git a/CICMMetadata/java/generated/SecuritySectorsType.java b/CICMMetadata/java/generated/SecuritySectorsType.java new file mode 100644 index 000000000..15017ae71 --- /dev/null +++ b/CICMMetadata/java/generated/SecuritySectorsType.java @@ -0,0 +1,104 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * Start and end of XGD's security sectors + * + * + *

Clase Java para SecuritySectorsType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="SecuritySectorsType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Start" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="End" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "SecuritySectorsType", propOrder = { + "start", + "end" +}) +public class SecuritySectorsType { + + @XmlElement(name = "Start", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger start; + @XmlElement(name = "End", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger end; + + /** + * Obtiene el valor de la propiedad start. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getStart() { + return start; + } + + /** + * Define el valor de la propiedad start. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setStart(BigInteger value) { + this.start = value; + } + + /** + * Obtiene el valor de la propiedad end. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getEnd() { + return end; + } + + /** + * Define el valor de la propiedad end. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setEnd(BigInteger value) { + this.end = value; + } + +} diff --git a/CICMMetadata/java/generated/SequenceType.java b/CICMMetadata/java/generated/SequenceType.java new file mode 100644 index 000000000..f9eec7d2a --- /dev/null +++ b/CICMMetadata/java/generated/SequenceType.java @@ -0,0 +1,190 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * Sequence information about a disc + * + * + *

Clase Java para SequenceType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="SequenceType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="MediaTitle" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="MediaSequence" type="{http://www.w3.org/2001/XMLSchema}unsignedInt"/>
+ *         <element name="TotalMedia">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}unsignedInt">
+ *               <minInclusive value="1"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *         <element name="Side" minOccurs="0">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}unsignedByte">
+ *               <maxInclusive value="2"/>
+ *               <minInclusive value="1"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *         <element name="Layer" minOccurs="0">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}unsignedByte">
+ *               <minInclusive value="0"/>
+ *               <maxInclusive value="1"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "SequenceType", propOrder = { + "mediaTitle", + "mediaSequence", + "totalMedia", + "side", + "layer" +}) +public class SequenceType { + + @XmlElement(name = "MediaTitle") + protected String mediaTitle; + @XmlElement(name = "MediaSequence") + @XmlSchemaType(name = "unsignedInt") + protected long mediaSequence; + @XmlElement(name = "TotalMedia") + protected long totalMedia; + @XmlElement(name = "Side") + protected Short side; + @XmlElement(name = "Layer") + protected Short layer; + + /** + * Obtiene el valor de la propiedad mediaTitle. + * + * @return + * possible object is + * {@link String } + * + */ + public String getMediaTitle() { + return mediaTitle; + } + + /** + * Define el valor de la propiedad mediaTitle. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setMediaTitle(String value) { + this.mediaTitle = value; + } + + /** + * Obtiene el valor de la propiedad mediaSequence. + * + */ + public long getMediaSequence() { + return mediaSequence; + } + + /** + * Define el valor de la propiedad mediaSequence. + * + */ + public void setMediaSequence(long value) { + this.mediaSequence = value; + } + + /** + * Obtiene el valor de la propiedad totalMedia. + * + */ + public long getTotalMedia() { + return totalMedia; + } + + /** + * Define el valor de la propiedad totalMedia. + * + */ + public void setTotalMedia(long value) { + this.totalMedia = value; + } + + /** + * Obtiene el valor de la propiedad side. + * + * @return + * possible object is + * {@link Short } + * + */ + public Short getSide() { + return side; + } + + /** + * Define el valor de la propiedad side. + * + * @param value + * allowed object is + * {@link Short } + * + */ + public void setSide(Short value) { + this.side = value; + } + + /** + * Obtiene el valor de la propiedad layer. + * + * @return + * possible object is + * {@link Short } + * + */ + public Short getLayer() { + return layer; + } + + /** + * Define el valor de la propiedad layer. + * + * @param value + * allowed object is + * {@link Short } + * + */ + public void setLayer(Short value) { + this.layer = value; + } + +} diff --git a/CICMMetadata/java/generated/SoftwareType.java b/CICMMetadata/java/generated/SoftwareType.java new file mode 100644 index 000000000..78649bd2f --- /dev/null +++ b/CICMMetadata/java/generated/SoftwareType.java @@ -0,0 +1,127 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * Software used for disc reading + * + *

Clase Java para SoftwareType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="SoftwareType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Name" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="Version" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="OperatingSystem" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "SoftwareType", propOrder = { + "name", + "version", + "operatingSystem" +}) +public class SoftwareType { + + @XmlElement(name = "Name", required = true) + protected String name; + @XmlElement(name = "Version", required = true) + protected String version; + @XmlElement(name = "OperatingSystem", required = true) + protected String operatingSystem; + + /** + * Obtiene el valor de la propiedad name. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Define el valor de la propiedad name. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + /** + * Obtiene el valor de la propiedad version. + * + * @return + * possible object is + * {@link String } + * + */ + public String getVersion() { + return version; + } + + /** + * Define el valor de la propiedad version. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setVersion(String value) { + this.version = value; + } + + /** + * Obtiene el valor de la propiedad operatingSystem. + * + * @return + * possible object is + * {@link String } + * + */ + public String getOperatingSystem() { + return operatingSystem; + } + + /** + * Define el valor de la propiedad operatingSystem. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setOperatingSystem(String value) { + this.operatingSystem = value; + } + +} diff --git a/CICMMetadata/java/generated/SubChannelType.java b/CICMMetadata/java/generated/SubChannelType.java new file mode 100644 index 000000000..d43affcf2 --- /dev/null +++ b/CICMMetadata/java/generated/SubChannelType.java @@ -0,0 +1,130 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * Track's subchannel information + * + *

Clase Java para SubChannelType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="SubChannelType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Image" type="{}ImageType"/>
+ *         <element name="Size" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="Checksums" type="{}ChecksumsType"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "SubChannelType", propOrder = { + "image", + "size", + "checksums" +}) +public class SubChannelType { + + @XmlElement(name = "Image", required = true) + protected ImageType image; + @XmlElement(name = "Size", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger size; + @XmlElement(name = "Checksums", required = true) + protected ChecksumsType checksums; + + /** + * Obtiene el valor de la propiedad image. + * + * @return + * possible object is + * {@link ImageType } + * + */ + public ImageType getImage() { + return image; + } + + /** + * Define el valor de la propiedad image. + * + * @param value + * allowed object is + * {@link ImageType } + * + */ + public void setImage(ImageType value) { + this.image = value; + } + + /** + * Obtiene el valor de la propiedad size. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getSize() { + return size; + } + + /** + * Define el valor de la propiedad size. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setSize(BigInteger value) { + this.size = value; + } + + /** + * Obtiene el valor de la propiedad checksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getChecksums() { + return checksums; + } + + /** + * Define el valor de la propiedad checksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setChecksums(ChecksumsType value) { + this.checksums = value; + } + +} diff --git a/CICMMetadata/java/generated/SubcategoriesType.java b/CICMMetadata/java/generated/SubcategoriesType.java new file mode 100644 index 000000000..6a334b56f --- /dev/null +++ b/CICMMetadata/java/generated/SubcategoriesType.java @@ -0,0 +1,76 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para SubcategoriesType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="SubcategoriesType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Subcategory" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "SubcategoriesType", propOrder = { + "subcategory" +}) +public class SubcategoriesType { + + @XmlElement(name = "Subcategory", required = true) + protected List subcategory; + + /** + * Gets the value of the subcategory property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the subcategory property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getSubcategory().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link String } + * + * + */ + public List getSubcategory() { + if (subcategory == null) { + subcategory = new ArrayList(); + } + return this.subcategory; + } + +} diff --git a/CICMMetadata/java/generated/SubtitleTracksType.java b/CICMMetadata/java/generated/SubtitleTracksType.java new file mode 100644 index 000000000..17616fe3a --- /dev/null +++ b/CICMMetadata/java/generated/SubtitleTracksType.java @@ -0,0 +1,122 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para SubtitleTracksType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="SubtitleTracksType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Languages" type="{}LanguagesType" minOccurs="0"/>
+ *       </sequence>
+ *       <attribute name="TrackNumber" use="required">
+ *         <simpleType>
+ *           <restriction base="{http://www.w3.org/2001/XMLSchema}unsignedInt">
+ *             <minInclusive value="1"/>
+ *           </restriction>
+ *         </simpleType>
+ *       </attribute>
+ *       <attribute name="Codec" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "SubtitleTracksType", propOrder = { + "languages" +}) +public class SubtitleTracksType { + + @XmlElement(name = "Languages") + protected LanguagesType languages; + @XmlAttribute(name = "TrackNumber", required = true) + protected long trackNumber; + @XmlAttribute(name = "Codec", required = true) + protected String codec; + + /** + * Obtiene el valor de la propiedad languages. + * + * @return + * possible object is + * {@link LanguagesType } + * + */ + public LanguagesType getLanguages() { + return languages; + } + + /** + * Define el valor de la propiedad languages. + * + * @param value + * allowed object is + * {@link LanguagesType } + * + */ + public void setLanguages(LanguagesType value) { + this.languages = value; + } + + /** + * Obtiene el valor de la propiedad trackNumber. + * + */ + public long getTrackNumber() { + return trackNumber; + } + + /** + * Define el valor de la propiedad trackNumber. + * + */ + public void setTrackNumber(long value) { + this.trackNumber = value; + } + + /** + * Obtiene el valor de la propiedad codec. + * + * @return + * possible object is + * {@link String } + * + */ + public String getCodec() { + return codec; + } + + /** + * Define el valor de la propiedad codec. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setCodec(String value) { + this.codec = value; + } + +} diff --git a/CICMMetadata/java/generated/SystemsType.java b/CICMMetadata/java/generated/SystemsType.java new file mode 100644 index 000000000..0dc9d85e6 --- /dev/null +++ b/CICMMetadata/java/generated/SystemsType.java @@ -0,0 +1,76 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para SystemsType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="SystemsType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="System" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "SystemsType", propOrder = { + "system" +}) +public class SystemsType { + + @XmlElement(name = "System") + protected List system; + + /** + * Gets the value of the system property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the system property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getSystem().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link String } + * + * + */ + public List getSystem() { + if (system == null) { + system = new ArrayList(); + } + return this.system; + } + +} diff --git a/CICMMetadata/java/generated/TapeFileType.java b/CICMMetadata/java/generated/TapeFileType.java new file mode 100644 index 000000000..ec401babf --- /dev/null +++ b/CICMMetadata/java/generated/TapeFileType.java @@ -0,0 +1,246 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * Tape file information + * + *

Clase Java para TapeFileType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="TapeFileType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Image" type="{}ImageType"/>
+ *         <element name="Size" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="Sequence" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="BlockSize" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="StartBlock" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="EndBlock" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="Checksums" type="{}ChecksumsType"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "TapeFileType", propOrder = { + "image", + "size", + "sequence", + "blockSize", + "startBlock", + "endBlock", + "checksums" +}) +public class TapeFileType { + + @XmlElement(name = "Image", required = true) + protected ImageType image; + @XmlElement(name = "Size", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger size; + @XmlElement(name = "Sequence", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger sequence; + @XmlElement(name = "BlockSize", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger blockSize; + @XmlElement(name = "StartBlock", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger startBlock; + @XmlElement(name = "EndBlock", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger endBlock; + @XmlElement(name = "Checksums", required = true) + protected ChecksumsType checksums; + + /** + * Obtiene el valor de la propiedad image. + * + * @return + * possible object is + * {@link ImageType } + * + */ + public ImageType getImage() { + return image; + } + + /** + * Define el valor de la propiedad image. + * + * @param value + * allowed object is + * {@link ImageType } + * + */ + public void setImage(ImageType value) { + this.image = value; + } + + /** + * Obtiene el valor de la propiedad size. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getSize() { + return size; + } + + /** + * Define el valor de la propiedad size. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setSize(BigInteger value) { + this.size = value; + } + + /** + * Obtiene el valor de la propiedad sequence. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getSequence() { + return sequence; + } + + /** + * Define el valor de la propiedad sequence. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setSequence(BigInteger value) { + this.sequence = value; + } + + /** + * Obtiene el valor de la propiedad blockSize. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getBlockSize() { + return blockSize; + } + + /** + * Define el valor de la propiedad blockSize. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setBlockSize(BigInteger value) { + this.blockSize = value; + } + + /** + * Obtiene el valor de la propiedad startBlock. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getStartBlock() { + return startBlock; + } + + /** + * Define el valor de la propiedad startBlock. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setStartBlock(BigInteger value) { + this.startBlock = value; + } + + /** + * Obtiene el valor de la propiedad endBlock. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getEndBlock() { + return endBlock; + } + + /** + * Define el valor de la propiedad endBlock. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setEndBlock(BigInteger value) { + this.endBlock = value; + } + + /** + * Obtiene el valor de la propiedad checksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getChecksums() { + return checksums; + } + + /** + * Define el valor de la propiedad checksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setChecksums(ChecksumsType value) { + this.checksums = value; + } + +} diff --git a/CICMMetadata/java/generated/TapeInformationType.java b/CICMMetadata/java/generated/TapeInformationType.java new file mode 100644 index 000000000..556cd860c --- /dev/null +++ b/CICMMetadata/java/generated/TapeInformationType.java @@ -0,0 +1,76 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para TapeInformationType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="TapeInformationType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Partition" type="{}TapePartitionType" maxOccurs="unbounded"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "TapeInformationType", propOrder = { + "partition" +}) +public class TapeInformationType { + + @XmlElement(name = "Partition", required = true) + protected List partition; + + /** + * Gets the value of the partition property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the partition property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getPartition().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link TapePartitionType } + * + * + */ + public List getPartition() { + if (partition == null) { + partition = new ArrayList(); + } + return this.partition; + } + +} diff --git a/CICMMetadata/java/generated/TapePartitionType.java b/CICMMetadata/java/generated/TapePartitionType.java new file mode 100644 index 000000000..570dad038 --- /dev/null +++ b/CICMMetadata/java/generated/TapePartitionType.java @@ -0,0 +1,254 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * Partition information + * + *

Clase Java para TapePartitionType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="TapePartitionType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Image" type="{}ImageType"/>
+ *         <element name="Size" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="Sequence" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="StartBlock" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="EndBlock" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="Checksums" type="{}ChecksumsType"/>
+ *         <sequence>
+ *           <element name="File" type="{}TapeFileType" maxOccurs="unbounded"/>
+ *         </sequence>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "TapePartitionType", propOrder = { + "image", + "size", + "sequence", + "startBlock", + "endBlock", + "checksums", + "file" +}) +public class TapePartitionType { + + @XmlElement(name = "Image", required = true) + protected ImageType image; + @XmlElement(name = "Size", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger size; + @XmlElement(name = "Sequence", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger sequence; + @XmlElement(name = "StartBlock", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger startBlock; + @XmlElement(name = "EndBlock", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger endBlock; + @XmlElement(name = "Checksums", required = true) + protected ChecksumsType checksums; + @XmlElement(name = "File", required = true) + protected List file; + + /** + * Obtiene el valor de la propiedad image. + * + * @return + * possible object is + * {@link ImageType } + * + */ + public ImageType getImage() { + return image; + } + + /** + * Define el valor de la propiedad image. + * + * @param value + * allowed object is + * {@link ImageType } + * + */ + public void setImage(ImageType value) { + this.image = value; + } + + /** + * Obtiene el valor de la propiedad size. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getSize() { + return size; + } + + /** + * Define el valor de la propiedad size. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setSize(BigInteger value) { + this.size = value; + } + + /** + * Obtiene el valor de la propiedad sequence. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getSequence() { + return sequence; + } + + /** + * Define el valor de la propiedad sequence. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setSequence(BigInteger value) { + this.sequence = value; + } + + /** + * Obtiene el valor de la propiedad startBlock. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getStartBlock() { + return startBlock; + } + + /** + * Define el valor de la propiedad startBlock. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setStartBlock(BigInteger value) { + this.startBlock = value; + } + + /** + * Obtiene el valor de la propiedad endBlock. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getEndBlock() { + return endBlock; + } + + /** + * Define el valor de la propiedad endBlock. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setEndBlock(BigInteger value) { + this.endBlock = value; + } + + /** + * Obtiene el valor de la propiedad checksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getChecksums() { + return checksums; + } + + /** + * Define el valor de la propiedad checksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setChecksums(ChecksumsType value) { + this.checksums = value; + } + + /** + * Gets the value of the file property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the file property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getFile().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link TapeFileType } + * + * + */ + public List getFile() { + if (file == null) { + file = new ArrayList(); + } + return this.file; + } + +} diff --git a/CICMMetadata/java/generated/TrackFlagsType.java b/CICMMetadata/java/generated/TrackFlagsType.java new file mode 100644 index 000000000..964a86728 --- /dev/null +++ b/CICMMetadata/java/generated/TrackFlagsType.java @@ -0,0 +1,141 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para TrackFlagsType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="TrackFlagsType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Quadraphonic">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}boolean">
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *         <element name="Data">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}boolean">
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *         <element name="CopyPermitted">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}boolean">
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *         <element name="PreEmphasis">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}boolean">
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "TrackFlagsType", propOrder = { + "quadraphonic", + "data", + "copyPermitted", + "preEmphasis" +}) +public class TrackFlagsType { + + @XmlElement(name = "Quadraphonic") + protected boolean quadraphonic; + @XmlElement(name = "Data") + protected boolean data; + @XmlElement(name = "CopyPermitted") + protected boolean copyPermitted; + @XmlElement(name = "PreEmphasis") + protected boolean preEmphasis; + + /** + * Obtiene el valor de la propiedad quadraphonic. + * + */ + public boolean isQuadraphonic() { + return quadraphonic; + } + + /** + * Define el valor de la propiedad quadraphonic. + * + */ + public void setQuadraphonic(boolean value) { + this.quadraphonic = value; + } + + /** + * Obtiene el valor de la propiedad data. + * + */ + public boolean isData() { + return data; + } + + /** + * Define el valor de la propiedad data. + * + */ + public void setData(boolean value) { + this.data = value; + } + + /** + * Obtiene el valor de la propiedad copyPermitted. + * + */ + public boolean isCopyPermitted() { + return copyPermitted; + } + + /** + * Define el valor de la propiedad copyPermitted. + * + */ + public void setCopyPermitted(boolean value) { + this.copyPermitted = value; + } + + /** + * Obtiene el valor de la propiedad preEmphasis. + * + */ + public boolean isPreEmphasis() { + return preEmphasis; + } + + /** + * Define el valor de la propiedad preEmphasis. + * + */ + public void setPreEmphasis(boolean value) { + this.preEmphasis = value; + } + +} diff --git a/CICMMetadata/java/generated/TrackIndexType.java b/CICMMetadata/java/generated/TrackIndexType.java new file mode 100644 index 000000000..b6c4ecb58 --- /dev/null +++ b/CICMMetadata/java/generated/TrackIndexType.java @@ -0,0 +1,80 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + + +/** + *

Clase Java para TrackIndexType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="TrackIndexType">
+ *   <simpleContent>
+ *     <extension base="<http://www.w3.org/2001/XMLSchema>int">
+ *       <attribute name="index" use="required" type="{http://www.w3.org/2001/XMLSchema}unsignedShort" />
+ *     </extension>
+ *   </simpleContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "TrackIndexType", propOrder = { + "value" +}) +public class TrackIndexType { + + @XmlValue + protected int value; + @XmlAttribute(name = "index", required = true) + @XmlSchemaType(name = "unsignedShort") + protected int index; + + /** + * Obtiene el valor de la propiedad value. + * + */ + public int getValue() { + return value; + } + + /** + * Define el valor de la propiedad value. + * + */ + public void setValue(int value) { + this.value = value; + } + + /** + * Obtiene el valor de la propiedad index. + * + */ + public int getIndex() { + return index; + } + + /** + * Define el valor de la propiedad index. + * + */ + public void setIndex(int value) { + this.index = value; + } + +} diff --git a/CICMMetadata/java/generated/TrackIndexesType.java b/CICMMetadata/java/generated/TrackIndexesType.java new file mode 100644 index 000000000..52ab2a1eb --- /dev/null +++ b/CICMMetadata/java/generated/TrackIndexesType.java @@ -0,0 +1,76 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para TrackIndexesType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="TrackIndexesType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Index" type="{}TrackIndexType" maxOccurs="unbounded"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "TrackIndexesType", propOrder = { + "index" +}) +public class TrackIndexesType { + + @XmlElement(name = "Index", required = true) + protected List index; + + /** + * Gets the value of the index property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the index property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getIndex().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link TrackIndexType } + * + * + */ + public List getIndex() { + if (index == null) { + index = new ArrayList(); + } + return this.index; + } + +} diff --git a/CICMMetadata/java/generated/TrackSequenceType.java b/CICMMetadata/java/generated/TrackSequenceType.java new file mode 100644 index 000000000..83fc43c16 --- /dev/null +++ b/CICMMetadata/java/generated/TrackSequenceType.java @@ -0,0 +1,92 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * Sequence information about a track + * + * + *

Clase Java para TrackSequenceType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="TrackSequenceType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="TrackNumber" type="{http://www.w3.org/2001/XMLSchema}unsignedInt"/>
+ *         <element name="Session">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}unsignedInt">
+ *               <minInclusive value="1"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "TrackSequenceType", propOrder = { + "trackNumber", + "session" +}) +public class TrackSequenceType { + + @XmlElement(name = "TrackNumber") + @XmlSchemaType(name = "unsignedInt") + protected long trackNumber; + @XmlElement(name = "Session") + protected long session; + + /** + * Obtiene el valor de la propiedad trackNumber. + * + */ + public long getTrackNumber() { + return trackNumber; + } + + /** + * Define el valor de la propiedad trackNumber. + * + */ + public void setTrackNumber(long value) { + this.trackNumber = value; + } + + /** + * Obtiene el valor de la propiedad session. + * + */ + public long getSession() { + return session; + } + + /** + * Define el valor de la propiedad session. + * + */ + public void setSession(long value) { + this.session = value; + } + +} diff --git a/CICMMetadata/java/generated/TrackType.java b/CICMMetadata/java/generated/TrackType.java new file mode 100644 index 000000000..f69657a74 --- /dev/null +++ b/CICMMetadata/java/generated/TrackType.java @@ -0,0 +1,504 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.math.BigInteger; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * Track information + * + *

Clase Java para TrackType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="TrackType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Image" type="{}ImageType"/>
+ *         <element name="Size" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="Sequence" type="{}TrackSequenceType"/>
+ *         <element name="StartMSF" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="EndMSF" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="StartSector" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="EndSector" type="{http://www.w3.org/2001/XMLSchema}unsignedLong"/>
+ *         <element name="Indexes" type="{}TrackIndexesType" minOccurs="0"/>
+ *         <element name="Flags" type="{}TrackFlagsType" minOccurs="0"/>
+ *         <element name="ISRC" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="TrackType">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ *               <enumeration value="audio"/>
+ *               <enumeration value="mode0"/>
+ *               <enumeration value="mode1"/>
+ *               <enumeration value="mode2"/>
+ *               <enumeration value="m2f1"/>
+ *               <enumeration value="m2f2"/>
+ *               <enumeration value="dvd"/>
+ *               <enumeration value="hddvd"/>
+ *               <enumeration value="bluray"/>
+ *               <enumeration value="ddcd"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *         <element name="BytesPerSector" type="{http://www.w3.org/2001/XMLSchema}unsignedInt"/>
+ *         <element name="AccoustID" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Checksums" type="{}ChecksumsType"/>
+ *         <element name="SubChannel" type="{}SubChannelType" minOccurs="0"/>
+ *         <element name="FileSystemInformation" type="{}FileSystemInformationType" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "TrackType", propOrder = { + "image", + "size", + "sequence", + "startMSF", + "endMSF", + "startSector", + "endSector", + "indexes", + "flags", + "isrc", + "trackType", + "bytesPerSector", + "accoustID", + "checksums", + "subChannel", + "fileSystemInformation" +}) +public class TrackType { + + @XmlElement(name = "Image", required = true) + protected ImageType image; + @XmlElement(name = "Size", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger size; + @XmlElement(name = "Sequence", required = true) + protected TrackSequenceType sequence; + @XmlElement(name = "StartMSF") + protected String startMSF; + @XmlElement(name = "EndMSF") + protected String endMSF; + @XmlElement(name = "StartSector", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger startSector; + @XmlElement(name = "EndSector", required = true) + @XmlSchemaType(name = "unsignedLong") + protected BigInteger endSector; + @XmlElement(name = "Indexes") + protected TrackIndexesType indexes; + @XmlElement(name = "Flags") + protected TrackFlagsType flags; + @XmlElement(name = "ISRC") + protected String isrc; + @XmlElement(name = "TrackType", required = true) + protected String trackType; + @XmlElement(name = "BytesPerSector") + @XmlSchemaType(name = "unsignedInt") + protected long bytesPerSector; + @XmlElement(name = "AccoustID") + protected String accoustID; + @XmlElement(name = "Checksums", required = true) + protected ChecksumsType checksums; + @XmlElement(name = "SubChannel") + protected SubChannelType subChannel; + @XmlElement(name = "FileSystemInformation") + protected FileSystemInformationType fileSystemInformation; + + /** + * Obtiene el valor de la propiedad image. + * + * @return + * possible object is + * {@link ImageType } + * + */ + public ImageType getImage() { + return image; + } + + /** + * Define el valor de la propiedad image. + * + * @param value + * allowed object is + * {@link ImageType } + * + */ + public void setImage(ImageType value) { + this.image = value; + } + + /** + * Obtiene el valor de la propiedad size. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getSize() { + return size; + } + + /** + * Define el valor de la propiedad size. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setSize(BigInteger value) { + this.size = value; + } + + /** + * Obtiene el valor de la propiedad sequence. + * + * @return + * possible object is + * {@link TrackSequenceType } + * + */ + public TrackSequenceType getSequence() { + return sequence; + } + + /** + * Define el valor de la propiedad sequence. + * + * @param value + * allowed object is + * {@link TrackSequenceType } + * + */ + public void setSequence(TrackSequenceType value) { + this.sequence = value; + } + + /** + * Obtiene el valor de la propiedad startMSF. + * + * @return + * possible object is + * {@link String } + * + */ + public String getStartMSF() { + return startMSF; + } + + /** + * Define el valor de la propiedad startMSF. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setStartMSF(String value) { + this.startMSF = value; + } + + /** + * Obtiene el valor de la propiedad endMSF. + * + * @return + * possible object is + * {@link String } + * + */ + public String getEndMSF() { + return endMSF; + } + + /** + * Define el valor de la propiedad endMSF. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setEndMSF(String value) { + this.endMSF = value; + } + + /** + * Obtiene el valor de la propiedad startSector. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getStartSector() { + return startSector; + } + + /** + * Define el valor de la propiedad startSector. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setStartSector(BigInteger value) { + this.startSector = value; + } + + /** + * Obtiene el valor de la propiedad endSector. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getEndSector() { + return endSector; + } + + /** + * Define el valor de la propiedad endSector. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setEndSector(BigInteger value) { + this.endSector = value; + } + + /** + * Obtiene el valor de la propiedad indexes. + * + * @return + * possible object is + * {@link TrackIndexesType } + * + */ + public TrackIndexesType getIndexes() { + return indexes; + } + + /** + * Define el valor de la propiedad indexes. + * + * @param value + * allowed object is + * {@link TrackIndexesType } + * + */ + public void setIndexes(TrackIndexesType value) { + this.indexes = value; + } + + /** + * Obtiene el valor de la propiedad flags. + * + * @return + * possible object is + * {@link TrackFlagsType } + * + */ + public TrackFlagsType getFlags() { + return flags; + } + + /** + * Define el valor de la propiedad flags. + * + * @param value + * allowed object is + * {@link TrackFlagsType } + * + */ + public void setFlags(TrackFlagsType value) { + this.flags = value; + } + + /** + * Obtiene el valor de la propiedad isrc. + * + * @return + * possible object is + * {@link String } + * + */ + public String getISRC() { + return isrc; + } + + /** + * Define el valor de la propiedad isrc. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setISRC(String value) { + this.isrc = value; + } + + /** + * Obtiene el valor de la propiedad trackType. + * + * @return + * possible object is + * {@link String } + * + */ + public String getTrackType() { + return trackType; + } + + /** + * Define el valor de la propiedad trackType. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setTrackType(String value) { + this.trackType = value; + } + + /** + * Obtiene el valor de la propiedad bytesPerSector. + * + */ + public long getBytesPerSector() { + return bytesPerSector; + } + + /** + * Define el valor de la propiedad bytesPerSector. + * + */ + public void setBytesPerSector(long value) { + this.bytesPerSector = value; + } + + /** + * Obtiene el valor de la propiedad accoustID. + * + * @return + * possible object is + * {@link String } + * + */ + public String getAccoustID() { + return accoustID; + } + + /** + * Define el valor de la propiedad accoustID. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setAccoustID(String value) { + this.accoustID = value; + } + + /** + * Obtiene el valor de la propiedad checksums. + * + * @return + * possible object is + * {@link ChecksumsType } + * + */ + public ChecksumsType getChecksums() { + return checksums; + } + + /** + * Define el valor de la propiedad checksums. + * + * @param value + * allowed object is + * {@link ChecksumsType } + * + */ + public void setChecksums(ChecksumsType value) { + this.checksums = value; + } + + /** + * Obtiene el valor de la propiedad subChannel. + * + * @return + * possible object is + * {@link SubChannelType } + * + */ + public SubChannelType getSubChannel() { + return subChannel; + } + + /** + * Define el valor de la propiedad subChannel. + * + * @param value + * allowed object is + * {@link SubChannelType } + * + */ + public void setSubChannel(SubChannelType value) { + this.subChannel = value; + } + + /** + * Obtiene el valor de la propiedad fileSystemInformation. + * + * @return + * possible object is + * {@link FileSystemInformationType } + * + */ + public FileSystemInformationType getFileSystemInformation() { + return fileSystemInformation; + } + + /** + * Define el valor de la propiedad fileSystemInformation. + * + * @param value + * allowed object is + * {@link FileSystemInformationType } + * + */ + public void setFileSystemInformation(FileSystemInformationType value) { + this.fileSystemInformation = value; + } + +} diff --git a/CICMMetadata/java/generated/USBType.java b/CICMMetadata/java/generated/USBType.java new file mode 100644 index 000000000..66c515958 --- /dev/null +++ b/CICMMetadata/java/generated/USBType.java @@ -0,0 +1,125 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * Contains USB device information + * + *

Clase Java para USBType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="USBType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="VendorID">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}unsignedShort">
+ *               <minInclusive value="1"/>
+ *               <maxInclusive value="65534"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *         <element name="ProductID">
+ *           <simpleType>
+ *             <restriction base="{http://www.w3.org/2001/XMLSchema}unsignedShort">
+ *               <minInclusive value="1"/>
+ *               <maxInclusive value="65534"/>
+ *             </restriction>
+ *           </simpleType>
+ *         </element>
+ *         <element name="Descriptors" type="{}DumpType" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "USBType", propOrder = { + "vendorID", + "productID", + "descriptors" +}) +public class USBType { + + @XmlElement(name = "VendorID") + protected int vendorID; + @XmlElement(name = "ProductID") + protected int productID; + @XmlElement(name = "Descriptors") + protected DumpType descriptors; + + /** + * Obtiene el valor de la propiedad vendorID. + * + */ + public int getVendorID() { + return vendorID; + } + + /** + * Define el valor de la propiedad vendorID. + * + */ + public void setVendorID(int value) { + this.vendorID = value; + } + + /** + * Obtiene el valor de la propiedad productID. + * + */ + public int getProductID() { + return productID; + } + + /** + * Define el valor de la propiedad productID. + * + */ + public void setProductID(int value) { + this.productID = value; + } + + /** + * Obtiene el valor de la propiedad descriptors. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getDescriptors() { + return descriptors; + } + + /** + * Define el valor de la propiedad descriptors. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setDescriptors(DumpType value) { + this.descriptors = value; + } + +} diff --git a/CICMMetadata/java/generated/UserManualType.java b/CICMMetadata/java/generated/UserManualType.java new file mode 100644 index 000000000..ab538b0be --- /dev/null +++ b/CICMMetadata/java/generated/UserManualType.java @@ -0,0 +1,150 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * User manual or user guide accompanying this set. Can be more than one. + * + * + *

Clase Java para UserManualType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="UserManualType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Language" type="{}LanguagesType" minOccurs="0"/>
+ *         <element name="Pages" type="{http://www.w3.org/2001/XMLSchema}unsignedInt"/>
+ *         <element name="PageSize" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="Scan" type="{}ScanType" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "UserManualType", propOrder = { + "language", + "pages", + "pageSize", + "scan" +}) +public class UserManualType { + + @XmlElement(name = "Language") + protected LanguagesType language; + @XmlElement(name = "Pages") + @XmlSchemaType(name = "unsignedInt") + protected long pages; + @XmlElement(name = "PageSize") + protected String pageSize; + @XmlElement(name = "Scan") + protected ScanType scan; + + /** + * Obtiene el valor de la propiedad language. + * + * @return + * possible object is + * {@link LanguagesType } + * + */ + public LanguagesType getLanguage() { + return language; + } + + /** + * Define el valor de la propiedad language. + * + * @param value + * allowed object is + * {@link LanguagesType } + * + */ + public void setLanguage(LanguagesType value) { + this.language = value; + } + + /** + * Obtiene el valor de la propiedad pages. + * + */ + public long getPages() { + return pages; + } + + /** + * Define el valor de la propiedad pages. + * + */ + public void setPages(long value) { + this.pages = value; + } + + /** + * Obtiene el valor de la propiedad pageSize. + * + * @return + * possible object is + * {@link String } + * + */ + public String getPageSize() { + return pageSize; + } + + /** + * Define el valor de la propiedad pageSize. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setPageSize(String value) { + this.pageSize = value; + } + + /** + * Obtiene el valor de la propiedad scan. + * + * @return + * possible object is + * {@link ScanType } + * + */ + public ScanType getScan() { + return scan; + } + + /** + * Define el valor de la propiedad scan. + * + * @param value + * allowed object is + * {@link ScanType } + * + */ + public void setScan(ScanType value) { + this.scan = value; + } + +} diff --git a/CICMMetadata/java/generated/VariableBlockSizeType.java b/CICMMetadata/java/generated/VariableBlockSizeType.java new file mode 100644 index 000000000..e458a0144 --- /dev/null +++ b/CICMMetadata/java/generated/VariableBlockSizeType.java @@ -0,0 +1,76 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para VariableBlockSizeType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="VariableBlockSizeType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="BlockSize" type="{}BlockSizeType" maxOccurs="unbounded"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "VariableBlockSizeType", propOrder = { + "blockSize" +}) +public class VariableBlockSizeType { + + @XmlElement(name = "BlockSize", required = true) + protected List blockSize; + + /** + * Gets the value of the blockSize property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the blockSize property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getBlockSize().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link BlockSizeType } + * + * + */ + public List getBlockSize() { + if (blockSize == null) { + blockSize = new ArrayList(); + } + return this.blockSize; + } + +} diff --git a/CICMMetadata/java/generated/VideoTracksType.java b/CICMMetadata/java/generated/VideoTracksType.java new file mode 100644 index 000000000..4cd675f86 --- /dev/null +++ b/CICMMetadata/java/generated/VideoTracksType.java @@ -0,0 +1,201 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para VideoTracksType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="VideoTracksType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="Languages" type="{}LanguagesType" minOccurs="0"/>
+ *       </sequence>
+ *       <attribute name="TrackNumber" use="required">
+ *         <simpleType>
+ *           <restriction base="{http://www.w3.org/2001/XMLSchema}unsignedInt">
+ *             <minInclusive value="1"/>
+ *           </restriction>
+ *         </simpleType>
+ *       </attribute>
+ *       <attribute name="Codec" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="Horizontal" use="required" type="{http://www.w3.org/2001/XMLSchema}unsignedInt" />
+ *       <attribute name="Vertical" use="required" type="{http://www.w3.org/2001/XMLSchema}unsignedInt" />
+ *       <attribute name="MeanBitrate" use="required" type="{http://www.w3.org/2001/XMLSchema}long" />
+ *       <attribute name="ThreeD" use="required" type="{http://www.w3.org/2001/XMLSchema}boolean" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "VideoTracksType", propOrder = { + "languages" +}) +public class VideoTracksType { + + @XmlElement(name = "Languages") + protected LanguagesType languages; + @XmlAttribute(name = "TrackNumber", required = true) + protected long trackNumber; + @XmlAttribute(name = "Codec", required = true) + protected String codec; + @XmlAttribute(name = "Horizontal", required = true) + @XmlSchemaType(name = "unsignedInt") + protected long horizontal; + @XmlAttribute(name = "Vertical", required = true) + @XmlSchemaType(name = "unsignedInt") + protected long vertical; + @XmlAttribute(name = "MeanBitrate", required = true) + protected long meanBitrate; + @XmlAttribute(name = "ThreeD", required = true) + protected boolean threeD; + + /** + * Obtiene el valor de la propiedad languages. + * + * @return + * possible object is + * {@link LanguagesType } + * + */ + public LanguagesType getLanguages() { + return languages; + } + + /** + * Define el valor de la propiedad languages. + * + * @param value + * allowed object is + * {@link LanguagesType } + * + */ + public void setLanguages(LanguagesType value) { + this.languages = value; + } + + /** + * Obtiene el valor de la propiedad trackNumber. + * + */ + public long getTrackNumber() { + return trackNumber; + } + + /** + * Define el valor de la propiedad trackNumber. + * + */ + public void setTrackNumber(long value) { + this.trackNumber = value; + } + + /** + * Obtiene el valor de la propiedad codec. + * + * @return + * possible object is + * {@link String } + * + */ + public String getCodec() { + return codec; + } + + /** + * Define el valor de la propiedad codec. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setCodec(String value) { + this.codec = value; + } + + /** + * Obtiene el valor de la propiedad horizontal. + * + */ + public long getHorizontal() { + return horizontal; + } + + /** + * Define el valor de la propiedad horizontal. + * + */ + public void setHorizontal(long value) { + this.horizontal = value; + } + + /** + * Obtiene el valor de la propiedad vertical. + * + */ + public long getVertical() { + return vertical; + } + + /** + * Define el valor de la propiedad vertical. + * + */ + public void setVertical(long value) { + this.vertical = value; + } + + /** + * Obtiene el valor de la propiedad meanBitrate. + * + */ + public long getMeanBitrate() { + return meanBitrate; + } + + /** + * Define el valor de la propiedad meanBitrate. + * + */ + public void setMeanBitrate(long value) { + this.meanBitrate = value; + } + + /** + * Obtiene el valor de la propiedad threeD. + * + */ + public boolean isThreeD() { + return threeD; + } + + /** + * Define el valor de la propiedad threeD. + * + */ + public void setThreeD(boolean value) { + this.threeD = value; + } + +} diff --git a/CICMMetadata/java/generated/XboxSecuritySectorsType.java b/CICMMetadata/java/generated/XboxSecuritySectorsType.java new file mode 100644 index 000000000..2e541dcb5 --- /dev/null +++ b/CICMMetadata/java/generated/XboxSecuritySectorsType.java @@ -0,0 +1,112 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para XboxSecuritySectorsType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="XboxSecuritySectorsType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="RequestVersion" type="{http://www.w3.org/2001/XMLSchema}unsignedInt"/>
+ *         <element name="RequestNumber" type="{http://www.w3.org/2001/XMLSchema}unsignedInt"/>
+ *         <element name="SecuritySectors" type="{}DumpType"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "XboxSecuritySectorsType", propOrder = { + "requestVersion", + "requestNumber", + "securitySectors" +}) +public class XboxSecuritySectorsType { + + @XmlElement(name = "RequestVersion") + @XmlSchemaType(name = "unsignedInt") + protected long requestVersion; + @XmlElement(name = "RequestNumber") + @XmlSchemaType(name = "unsignedInt") + protected long requestNumber; + @XmlElement(name = "SecuritySectors", required = true) + protected DumpType securitySectors; + + /** + * Obtiene el valor de la propiedad requestVersion. + * + */ + public long getRequestVersion() { + return requestVersion; + } + + /** + * Define el valor de la propiedad requestVersion. + * + */ + public void setRequestVersion(long value) { + this.requestVersion = value; + } + + /** + * Obtiene el valor de la propiedad requestNumber. + * + */ + public long getRequestNumber() { + return requestNumber; + } + + /** + * Define el valor de la propiedad requestNumber. + * + */ + public void setRequestNumber(long value) { + this.requestNumber = value; + } + + /** + * Obtiene el valor de la propiedad securitySectors. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getSecuritySectors() { + return securitySectors; + } + + /** + * Define el valor de la propiedad securitySectors. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setSecuritySectors(DumpType value) { + this.securitySectors = value; + } + +} diff --git a/CICMMetadata/java/generated/XboxType.java b/CICMMetadata/java/generated/XboxType.java new file mode 100644 index 000000000..fcc3a1474 --- /dev/null +++ b/CICMMetadata/java/generated/XboxType.java @@ -0,0 +1,132 @@ +// +// Este archivo ha sido generado por la arquitectura JavaTM para la implantación de la referencia de enlace (JAXB) XML v2.2.8-b130911.1802 +// Visite http://java.sun.com/xml/jaxb +// Todas las modificaciones realizadas en este archivo se perderán si se vuelve a compilar el esquema de origen. +// Generado el: 2020.07.12 a las 10:42:39 PM WEST +// + + +package generated; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Clase Java para XboxType complex type. + * + *

El siguiente fragmento de esquema especifica el contenido que se espera que haya en esta clase. + * + *

+ * <complexType name="XboxType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="PFI" type="{}DumpType"/>
+ *         <element name="DMI" type="{}DumpType"/>
+ *         <element name="SecuritySectors" type="{}XboxSecuritySectorsType" maxOccurs="unbounded"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "XboxType", propOrder = { + "pfi", + "dmi", + "securitySectors" +}) +public class XboxType { + + @XmlElement(name = "PFI", required = true) + protected DumpType pfi; + @XmlElement(name = "DMI", required = true) + protected DumpType dmi; + @XmlElement(name = "SecuritySectors", required = true) + protected List securitySectors; + + /** + * Obtiene el valor de la propiedad pfi. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getPFI() { + return pfi; + } + + /** + * Define el valor de la propiedad pfi. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setPFI(DumpType value) { + this.pfi = value; + } + + /** + * Obtiene el valor de la propiedad dmi. + * + * @return + * possible object is + * {@link DumpType } + * + */ + public DumpType getDMI() { + return dmi; + } + + /** + * Define el valor de la propiedad dmi. + * + * @param value + * allowed object is + * {@link DumpType } + * + */ + public void setDMI(DumpType value) { + this.dmi = value; + } + + /** + * Gets the value of the securitySectors property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the securitySectors property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getSecuritySectors().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link XboxSecuritySectorsType } + * + * + */ + public List getSecuritySectors() { + if (securitySectors == null) { + securitySectors = new ArrayList(); + } + return this.securitySectors; + } + +} diff --git a/CICMMetadata/samples/advertisement.xml b/CICMMetadata/samples/advertisement.xml new file mode 100644 index 000000000..1587e8edd --- /dev/null +++ b/CICMMetadata/samples/advertisement.xml @@ -0,0 +1,56 @@ + + + Nintendo + Luigi's Mansion 2 + + advertising + nintendo + 3DS + + + Game + + + Platformer + + + spa + + + System + + + Nintendo + Luigi's Mansion 2 + luigi_mansion2_ad.ts + 8509632 + 501 + 20 + 25 + + 8818e1db + bdc169fd31d3142067c532013e7c2446 + 521709692e8551748f0d14c791fba823d268cef3 + d28bf7829846cdcc633699f51e551b332bb10ef3f596bdf8948ec0b390f4f3e0 + 8b4aaa13b8f417482a8e37293aa33235a1236582fefd63e9 + 5ac087379b37afb22f65b0f6f2208c2e44708ea0bec0c233ab3ee5b85312fa4e656cc092e160f8626343033937aec90eadd674ee3e714f1243ff9e47285f8fae + 196608:KPzYb83jgXvTbe8Z48I5qKki6VaBK+qxLrP:szYbOjovTjvjKWV5xX + + + + + Xplora + DVB-T + 2013-04-02T07:15:00 + + ArgusTV + 2.0 + Windows 8 Professional + + + 28.1666667 + 15.4166667 + + + + diff --git a/CICMMetadata/samples/floppy_and_cd.xml b/CICMMetadata/samples/floppy_and_cd.xml new file mode 100644 index 000000000..e200ab353 --- /dev/null +++ b/CICMMetadata/samples/floppy_and_cd.xml @@ -0,0 +1,241 @@ + + + Be + BeOS + R4 + Retail + 1998-11-04 + + BeOS + + + Operating System + + + eng + + + i686 + Gestalt 67 + Gestalt 58 + Gestalt 69 + Gestalt 68 + Gestalt 108 + Gestalt 109 + Gestalt 514 + + + ia32 + ppc + + + BeOS R4 (Retail).cue + 174 + + 1 + 1 + + + c7e095e1fc98e98b36b8cde5b003f08d + 4f5a6b4e11bf644b1f77566b8149acab15db4276 + d7eba58afdc121da4fb47418c9d328393670bb58095baf035ca6c29d33300ccf + e5c5f17baa5dfcc6793808321b90ca8a2a396acdf5ea950d + f1902ad54a53c45a535b5ae456f000980463ddeef51e4b1510f1a5e0b79f6fa4e1460eb2d97253b7d68b83995003f6a6faeae7b5faf097fa9604441428b9c28c + + CD + CD-ROM + 3 + 1 + + 120 + 1.2 + + + jewel + + + + BeOS R4 (Retail).bin + 6967296 + + 1 + 1 + + 00:00:00 + 00:45:26 + 0 + 3401 + mode1 + 2048 + + 0xa66c658c + 0x9e60 + 0x26d3d260 + 0xfaf6cd8f8534541e + 9c3facd2d33cc29b4d80850c3387230a + 2800a377d2b9c2afe85ea2327f691f91f9b6600f + 9cf4335ca0b8b12fd343f46e69fc1e183d011456 + 44e780def14f136f082ab4ddfb8f1c3af0d58089edeaab706040eb2642335000 + 7c37209d84239d4c65eca58dcab9f4940731711b4d35725f15e464fd1dfb1729269b298ae16a6e7bd4f4a98cb9368b1c + a803a4d28aa6604db9c09b5cf7ce2937cce422311607f6d34b3560be07bb1634814a912cb94581305d2ffef3236b47941501a30909f11c236dd0e35ebb2a4d12 + 98304:Qddx6TKP6TK4oRdrcHcUTvwoRdrcHjkF4xGbUd8LtV1yV:Qddxb7I38k2xGYdzV + + + + 1 + 0 + 3401 + + + HFS + 1998-11-12T18:11:46 + 1998-11-12T18:11:46 + 2048 + 3251 + 53 + false + BEOS_TOOLS + false + + + ISO9660 + 1998-11-12T18:11:46 + 1998-11-12T18:11:46 + 2001-12-31T12:00:00 + 2048 + 3402 + false + BEOS_TOOLS + false + 1998-11-12T18:11:46 + LINUX + + + + + + + BeOS R4 (Retail).bin + 321093632 + + 2 + 1 + + 00:45:27 + 35:35:61 + 3402 + 160185 + mode1 + 2048 + + 0x37a31ed0 + 0x5eeb + 0x0c662ba1 + 0x4b5b4492dc1cc3f8 + f80c9ca884734c09af0f47b2d1d7651c + 05e62ddecaee1bcd11698420c4543f7c41cbbe95 + 153fe34de33d95b07d7a9be4cd3db9f4be1c31ae + b58f269bb7fbb7cf2a9bb65c05d64c9ec9179b63217ba9fe940198f6861e5cfb + 897f8a0beb90748599514fa9c2ae397af955c14d1e1234135ce8a1239cdf839fce17056778b3e2c270dacc000ab1dd0b + 683a79dfbd8c0322060e8758fd25e300276583dcfdbc50eddf039fefc2ce9ee9434d70a41a70a4aa9f24c33e8ffddb0b6012a08370822fdf329f8594c60e9499 + 3145728:3r8ksS8IcP98ENRE9n5HaT0aIYgAd4Rd4Td4BDXr6sN/LG6SVULduen89Jk9:QVYgRE9sTEYghv6sN/L9SURF0Jg + + + + 1 + 3402 + 160185 + + + BeFS + 2048 + 156633 + true + BeOS Intel R4 + 26875 + false + + + + + + + BeOS R4 (Retail).bin + 315621376 + + 3 + 1 + + 35:35:61 + 69:50:47 + 160186 + 314297 + mode1 + 2048 + + 0x668b9c98 + 0x133c + 0xee1fb301 + 0x620f86425be5befb + fa7b1d52ce2ed23368a10ffe2b1fc7a2 + 56cc151dfde1b61f6618bb94b5426b68be44a3a7 + 519a04b69ce217715c0956a2920c5236d6c61f0a + 45029b9e510fe693d19289a42b721e8ff3e42e64b788db039e9fe5d1012337f6 + e9e19e326eac5354a3385d0a9feaa678bf52911e94ddb5fa9aaa6959b9d2413334f4d4175f61154ab8f08ae930e2db30 + b6e81acb40dac35df3024caad103f175fb41df379722d9ae72b6a61076392b08c1269708f2a7068a660b054ad81e4d9687b95f7dc9584dd37c838f2555072cc9 + 3145728:fn9GWd4Rd4Td4Mkw8EIfIaT0aImglUrl6sN/LGxRZeL8dVXLdye:fn9Gy2ZTEmgg6sN/L6awXRJ + + + + 1 + 160186 + 314297 + + + BeFS (big-endian) + 2048 + 154112 + true + BeOS PPC R4 + 33959 + false + + + + + + + + BeOS R4 (Retail).dsk + 1474560 + + 0x80e618cd + 0x9dcc + 0x72d3b76c + 0xc179638a190b4a91 + 49b8f5d1465eca87dcc572143d182f83 + 95b57c12e48484ca47de69a048c895cce3fe1606 + 46ddb1d066270cfff6307b360976846fda0862ad + 899c49eaee12e42b789ecaca0e52297a52fde74072339a0a59e480dd961f265f + dfefa36cb6b91a25387d2230a6704e115c8fa22f3a58475177f20149ac468607044f9a5f6459b183ac3e3c35f9e1b3bf + b23716bfbbdf188a927c63d0ee3b000d452796ff7ec13047c61b501629b42e9f9631caf5bb09a6f7a8e3016f25bf1e098c0b8b6373f6fb5850c720e37654fccf + 6144:RAfUvvrKRWRe3PrBZZpPV4rnJP8W93Fh8Vg3k+0jN1rGs+gaAeCeV1:NvjKpTB38F0gwV+n0jj+zmeV1 + + + 1 + 1 + + 512 + 512 + 2880 + + 2 + 80 + 18 + + 93.7 + 90.0 + 3.3 + + + diff --git a/CICMMetadata/samples/mixedcd.xml b/CICMMetadata/samples/mixedcd.xml new file mode 100644 index 000000000..1e684ffe7 --- /dev/null +++ b/CICMMetadata/samples/mixedcd.xml @@ -0,0 +1,258 @@ + + + id Software + Quake + 1.10 + Retail + 1996-06-22 + + Games + + + First-person shooter + + + eng + + + i486 + + + ia32 + + + Image + 1082 + + 1 + 1 + + + a8ddf932 + a7cc48685663e781d6e4500bae9ddeb7 + def9f25a68bfe05c7e3bc352ca70438abd1411bf + + CD + CD-ROM + 11 + 1 + + 93.7 + 90.0 + 3.3 + + + jewel + + + + + cdrom (Track 01).bin + 39010272 + + 1 + 1 + + 0 + 16585 + mode2 + 2352 + + 124b015f + c36160718b39c97bf02fd3dcf94dfc2a + 0654a3a9f8f6ba09b6cca9a1bd00ad67c7603fd3 + 786432:spNjXNBnlKQ4jYf6YN1t6gCQss+fyPra7JBCpRk3qxlIVWnuL4D+9YbYXZje:spdMQ4UXCq+6ProIRk3qxaVWnuLzJje, + + + + cdrom (Track 02).bin + 54818064 + + 2 + 1 + + 16586 + 39892 + audio + 2352 + AQADtEkUhVEURVKA4_gPHfgLLc-OC02mCF2YoZ9wMTr4F-eO9ESPPoXB_OiN1LnBQx9BZfhwHt20xMKlHD_uoA8axhUOvTnSXLiW40YzJxT6zPhyDT_6FM2LHLo6hE8sPGdRkcKL2heaEU-GMKUiIlHI6Ph049JRheHRVMGPH9fYCCEHfUiTJhYYLpPxp8JFD-VDNIyOPLGhZT9CSce1DE2eoxSJJ8dx6QhTZcmhq4jF49uH6ikeFV-GRN8RZtJxZTE20UX1oKmYIzwFfQku6uiD5_g1-Mck64Mu46MO6RZ-MsM5CebxQZ_h_YidXLg2NBF1oS_OCznaZYeWMyGOT4qHbnVQWQqOMz1ERmCXXMh9OHqOT8Gbo4l81EmOS8fR5_CLnPgYaE-CmxcuEtmPJkfIJfxwIuG-Bs-Db0eTxAmLXniGJ0TyC2EoEeVxH8_ENDgFZJegM8mFvKgUBb8x8gt89NLxJviFPsmRy4f6Y2eIfDxsKailCS9u1DvCUDp4EVp2FSGZHZ9yootgR0f1VsOFX3jUI8uPD-otNCKDnFGOU-hDNIyIPNDegwnDHXeUIVwoNOHxBPmLC30GVwwu_GrRVTfOHCdRmRe0HF_Q80KT5oee7WjkDKGoCZ-OWkd6HHpU5IfTxMRPNI9S3MOF7EgqBs9onHmG6jP8RBdq4fiLS9nR0zjDDA-YzwiPxqXwC3oO87jD4oSY5niPb8oRJiT6Feg_AX6IvHB1QU_g7Aj3Dt9FNHHRhza-LEhvPDnuHZoi7fCIkrmMXHiEMM-CnniPT7KgV8FX_EOYo-Iu5Ao0Gw0f5E2OSxr6F67yoheOXFkcnNCk5bC0GBXFUHgDqWzRp0g5jJISWHxx6oOfIaQP5czQ3saV44Frgs9i_IdIbNrR44qL9kcTqsh3PDycHVdyvEHj6BKq78jVCdCPehHMo5c6PJJyPMWOG_SPidJxpUQNvYrx9WgUoWpyXBKuox0FLVWWGscbHZ04Dro-VI_QhzAf1Ar6I0x-4Q-6SIHTCHUtPEGuF9-hKyzynagSHk2-DN-D08gn6EoQShosKYcj-Tj8oMeHq0GdJMeRZoe2W7iObw72RXgDHuER5uDRQ8txKgpC_fBY9CJKwuiHagqDMHcD2UGYo_iFvkezF090hLlRWYK-RDiqjfC3oqSO4guLL0d64b3QL0duHIdz_LiooIlvhMcl7agEl3ERPtCv4DeypMpClNlRNZkpfDf6DZyP-II-EdGDJ8lxHV0P_yjyjviHp0apfWjGEl-gPEYpHQfTcdtwMDm0oz3CHI8a4mi6HP3xCR-FF9Uj_Mi14YrhHNqPo_lRjUXI7_DRHf-FkIetGfoOf8jx0MUtHTluHjo14Ucu-Cx6CsyPNHUObTqLGyELW8GHHsxVOFrCI9c3HOKYpfCJ58EtCd8hJlOU4qIQzZXxfMGHX_DKI7TxXNB8_Di2yCouLqAP_5Cv4xy-IMdX_MORn1itBzr8IjeOej36HfmEy_jxJMRWyyiu49fQN3iK_tCPHo1-TJtwwT_s4JF0fDlc4E18uMKP3zj8HYd7PBR-KB_8GFePXAif4KrQH1NenMR7QTt8C8J__DCPFz4N4RssSugjBhcKv8GH_viaHOEueD-qEznR7MeJ9yjJ44rxHHmUox985IwkPDnS4EbQqDR-5MgT6JSKloh2rsEBV1txTYimjfgm6B92w__RJ7gIXQXZo1cR7cfx5vAzD_nR31DwLbiPLMWHK7hwscLGo8ePcBc-ZTh1-MQjfCfEE31xhDz84_i2HOl34RCv4cYbGofO43kDv9DxC76M8A-e4xe6RvCN_jhFow-OyzoeuCGNi7h7_EB4XBm0Mdg5pP3h8zgF1zJ6XGiOyPgDLcd340d_iL_wDz7qo2oOQ3uHR8jxIjfKJxceC_4hZtyLl8jDw-fRE0XzFWdwI993fMehY9Jx5fAlTN5xsg7y4EFTMSF6XMcr4UlwlJEOTza-4wvCPbiFv9B3XMiL_8d1ND_6HeFlNDz0B2eOMGLdIK-GD-J5XEd-D9_xHDnsQruQ8zhOEc0TC11u5EQrRYE4_GgeB0fjHqWGH_2Nk4mhHfuJLE9xXhh_PMeV43ik40qJJmyoCPmH4zoe5agf6Mcf-Bq640mG89izGH0pNFVu_MjyDl6ObdaF-vgOf8dz9Dsa9cN__OvQXEXXDBeNS8h3HIcelBph0ciPw6804VXgrSeO44Gp8Lh8-EePXzhyH9ojeCPCS8d5ATeuojr8o8e1BydR6UeYQz_yF79wdGhq8fgO_Gh2_PjhbD36TPjRB3Y45McPPQiPHz18_LC2dArC406Q4Mfl-OgRBn9x6yv0Scd1oYd-pDp6TsN_5EN9NMd76IWWcAz6IQ9yHSjJ9GgeC9-hZYzToQ-uyACSlAIEOYTEANAAQ4AERDBAiGPIIESBcsYYYYAgCAoBCEKAMKCUEcAQIgwjAgAkDBIACCEUEMUgYQQwjiFBgDQGESaUQUIJoQQRADDpgBBACEIEKAAEx4AxTBgjJBFEmCGBYQAAQQwCDDEDjGAgOAoAoIQYIQgBgiEigDDAAAMEo0YBogwBABFjEAEKEAGUAsAAppQgggEAmDEAOAEIEEARAZ4QVBABoCcCACEgQAQI4YRhCBEEmDRIKAIIIEIBgwQwiAEgBAAFCKAEAI4gQQAAACgg2GGCIAGMFQYgowgQAAAEABMKCCYEAMIgA4ERAAGAoAKAKUoYCMgJAIAgBhjAjCCKEGWAA8whQEDVkDhmCARGKIyhI1YQYQhAAABhGFFACEIcAMAIAqBjxikhBCAIEcEEIEYgRBhRiAiAlCIMGXGRJUQAogQxDDAFFFbAEgQAJEAAKYxEDBAAgDHACaGAAYApIQAAiBkEETCKM4OUIBRYJAASgBlQmHHCCaGkIgQocIWxAimhFCCQEEERYAAABQAwwAEjlELOKURAkMQpIxRSwghmhAJMISAQIQIIwYghTjkDlVJEAoYAg8QgAsiiikiAAEIGCcYYUEAJghAwIiIFzCREAQMocgSQIhgkSgBGLKACCaIMEUQB5QhUxAHFiKAUAMkEAsIAoYWiRJBhmDEGAUEBR8IpIAYQAACCCBCEKCgEMIggwAhQRIilnIAMcOAcQxISxggAwChBBDIEIaKUAwApQYSyilmiHDFCOYKoEkQBwo1STAgECXKEIMgEJIYYhoxDQBBiDECMSMgAgQAQToRBwghiiDGORCeEGEaAQhlxwDAqEFBAEEOskkIyJShBCEjAHBEFCEIcs8gJoZhyRAhhEFOWSEsMIMAQJIAQSGDiIBESeIAJkJI6QAxwygE + + 9b64e30b + 4770ac46843190af09bd1a77b54c06f5 + 5bcb4bdd387aad4c8836b6151e57dac945a13ace + 786432:9062IpIjKxEtfyWPRVLLHjUcvmjoozcIInI0fLYcYqVuwI:906/Wo8fyERTIcujvzcjrT8Uy + + + + cdrom (Track 03).bin + 26137776 + + 3 + 1 + + 39893 + 51005 + audio + 2352 + AQADtFEShVEURYlw4PmL_EDQ5LmhIxcaaeuO7gp-vOHQH7Y840ZOSLqOsNTw4ZyFc8N5hD9EHjmXwz3CP3hu6B36E3Hi4_zAI1eTQteEEL-GxxHaollx8ciFpyJ0VGKCnXhwHn-aQKcNH72GFz-D_mjWIT-aH9PpCP2RUzn6Q018ZFHTo0Gt8PCHx3DEFuGRPMp09Dn8o1YufMwxP0NoHlrSMBvy8EHFIwxHQJz241-C3MJ3tCR89NSDaz--E6nyHHeGjzOa8YHMI09QNQz-40d0XNohZUWa4x-oSKrRHmeC5j2SnchxoTr8DH1D9MglnkieHD2u4NoxH3U5IU0jZXjeQ10gDmiO3ArxR7imUMh_9IJvlDfiP7h0NGMWPDAniQm-E2m8Q3wYhKJxYYzLCD94DSH0I2RGJ-B53CHCoUkTltCZHKGVBT4OJ81ShD90ok4S5Uh5oo0ePAr2HKhIIxV7qBQNHeaDBj8uXUK-zMG1IrwKj0I_mcQfPPnhZ8eHcskc-LjRNctx4Rpm9dAvPOnR5IHWH4_xSId3HJUzQ9RzXAoNnzoejXgI8eJgjkf4LLiOPceTI3fQQ0yq1Tic44c-2JdRHvmJEzvO4Ea6FzzaHc2HH1qcHI-NoORxHzdxRXuEuIf2I62EHr2DZgSP68ihH5Gswzf8o9-Rx4KuIM-OZ8f1BX2QN4I9aPKOnMrxDOeF8ETzUNB-pERfPBJ-PEOzH_3RH9ulHGV3_FEKhtkjIcf2DDd6nA9-hFoUo5EcHI9k9EGDHxH0IPw04x9q_eAp9EJKaCdKuUmMn3CVoWeGQ3l6vMdnQxMaDnlw_PiT48sR5mQNTWKLZ8VzVHck-FKgw1zQB70Ojzk8MuiN73jS5MGPSLlQHjf-5Gh3hDn0I1dxB73h_IgTBvp0_ES-HHlkKoF-PGjOILrU4iq-JEeVHOnZQDv-HMGHl8LrHD1X-Ai5SPgfqMllNHXQUsGlCM3pIMdzXEMvHE-PfISeF9GFSxLxHDdRb0eYC4eeg_tR5YYd6Dk8hF2GcxeOK0d_o9mDRydySJGzFM1l7MoNXD1xQdPloA_aLLB91PtxVNvRJC2u5ei1QEv140N4-GiaBqd4PNWDiDv0a0j74mpxwcd1_Lii4xfC9EEf4zeqNEJ4_LiSXMGTB3ngE8oT5PiOanmQJrGIH-IVhMEnXMenUUH4HeLR54euIs5RmanQXDn6CQ3XBiGvQjyPPEPzAE-P-8R5JBcRHT_-EL3ho89xBMdz3BF6Kbh0tEqWKtD1IIef4Qr24tGLWHohlxRCHd5Rmzh_PMfzIAxVSXgGjaQH9cd_hDoaZ8nxoo0yw3vw5bgyIeSaC190yGKOvB-aP8iFK4fmhC7K5GiiN3gU7EFTRZPwMHAXHYfzGVU6HbmGS9mRJ7mCB3qwvUeObzyupA-qnIJ39FmQG9-hIwyV7EE-4zx09Mfz4L-g5UuOdokQsjOaBz2uow--6HhE4U4s_Gg4HeHx59AtF1eOFB-m_LiWGUZ_hEoawfEEjZTwJMuDJ7bwB30w5dB1PEmE_M9R5TqaGBcuJ8h56EeYZxwe4Tla4vtxHc8Pn5ZxomRg9vjhVYefHJUsJJ4Q28QfOBZ-fNKIOy_S5cFN6MX0R3AVJYdODsadGU1SRTh0bUee5AoeNMd0HHmyIBn1oEku8fhx4lTwH3mQ7MoT-MyEH2eJysfz44fnHUfD1UTpFT3xHD1zxInx6cL3QEfIW0NTHvlxMjgfeDp0Yc83-FFinD7CdQ8c58KF5sEVHc87nE_Q50SYCzoVRFYyfM_R7EaVoySqxUEOPT_eBs2DdjmeGz9iPXiO5rnRZ8EllNIiBr7x5EMuMYem9viEWFfwB5dy9A-a-shjosyOZhJTKM-KKxfCWEKt0KiOOD0e5ehx5ngSerieQA_EE3twQZ1m4Yl6NN-hHb9wPOuRo5UW43GRHtqDH89__DAzCaegPQ_sycXRZzny8XiE-MdP6NmhZb6GXjlO5vh2lFKO5niOKUe9xdB04amOZ-gjnD30JNlxPXjgIzpy4VpeqIk-NLGO_viPWzjxPDm0j0LjaNA5EX9kHH8gJs9xCjl3eAwb3EV_PEH54BOPpwnyKBd-Bc2M_sGdQw8fNOPRF9dkROtxqfiNJ8eTo2eQ89CTJHOC0E7RB82JPbiIXDySKZF4Dj4nVD9e4tKRC1-OZNec45F1nIc59Hhu4XoceNSOo-HCBqVX9Dmeo2-Oi0OuQl10oUcz6tAjXB_x8PAfHIeidB_Chyh5XEeVDjkT4Qz0JFmqIJcdHH7wYRZy8YUq8QhXUmjy48fj4DnyHM8DkWOKT8cvxDp-VL_gD89hKyvatUEpLTL8IL1yaErkI5aS4MevoBfS54Fm53iUIOQZNG-B6UIYh1ClJsZ7VNehSzmOPNFR6h3-BH0Q5lB-PEmEXK1Q5YGD8sKZIyf01Aiv_LBDKvB5-Efx43l-NJfRh0dDHv1RmkifD5-gZcej6Th-CvmHkFouNLvwHyVzND1OKMrRL0MzGZUPNY1i9AODADDMCKIAYIYpgBghSAAGjABEKIEYEQAYYIgQyFAEJBWHGkgEEkIAhYBSBggAiGBAEGABEwYoIowBwAEiBSHIOUMFAAooIQAAhikCDDMcEMOMIAAIhigQTAhDMGICCgFIg4QQIQAQBDDHCCCAQQEAFQAAgoEySBDEHAEQOIoEkQAACgAQxFAAgAEIAUKEkIY4ZgQBBjDEBHFEMmEQAQYQBBkxrVGojgDFGAAwEQAJa5VDTipnGAKGQKYIMcQoaYAggAmlHDFKU2EQsAQYoRDgCKFioADKGgiBIwgwRBQQBACghHTMIAUMA0xAApS1AHBjAAAAUGQYMIJwQ7UQCBBlhCCKAUOAgcARwZBTgpgghCPAM8QUAEYrgQgRDADlBCIGEQLEEkoIgkAiiCAhCDGAZGIAAqAJgASQTACFFBPEIaSYU8AIpgghSgFnCFLMEgQCMUIAQyAQjgAgFAIGACIUcIgAxoRBFEAgiAJKASgIEpwYYJRixAkioDCAOCaQAEoIQACDgglnFICAKCIEAgkwQwQARAhjMAXICaQggEAIwChYSBEEAGKCGwAAMlAAIgwChBmhiCUCAMAEJMQaBpQFDBAgACDAESoUAsQ5hQBhCgADELBACAQGI0QBAQRBBiEFBFDOYAEIoIwBhoQAxCAlEEPECOQMAAAIAhFBBhAjGCLGAAGaEcghoBgRDkAjhEHMCCGEcoIZRARCBgFtmDEEGaIQcAQIAEwB2DDxTAAGAAKQI4IwAYQBQjAhjCCEAAOMYgAIIJghQBDCGIDCACMUIoQhowwgghkCCGGECCUUE8AAQphQAgFADHPMAQUAU0IRIIAjBACBDGHQGASAEk6gQABgDijmgADAYAEKIAQYC4IwQAomBAOQACIkwcZRpJwgigkwJAGEUUCEcIQJYQQgBkihAECAEgSYEcpYIqBgziAghBDAAgkEEEQAKhBATAAEDGFAUCMAQVYQZQA + + b390a7f7 + c97130e7c689edfa0d031572c7f37982 + b7f9d5076028f94eef095c6e680c55d085594382 + 786432:TCbF/70nHyRynTGUpO3cf1xqHeedPBbF0f0U5kcDaOU4:TGFgH/TGUpscedPxF0f0UKcv5 + + + + cdrom (Track 04).bin + 88625712 + + 4 + 1 + + 51006 + 88686 + audio + 2352 + AQADtEmSKFIURRGDBznwB8fRPAbSLJo23IFO5D-aZ2NQCz_CHL1y49CLnsdxAccNAxYu4ADgHMYPAMDxHjgu4LhhANZxHADw4zgA4HgPHBdw3DAACxcOAPhxHABwvAeO4zhgGYCFCwcA_DgOADh-HAcu4LAMwMKFAwCcw_gBAPjx4sAFHDcMGDeOA4BzGMcBAMd74DiO44YBWMdxAMCP4wCA4z1wXAAOywAsXDgA4MdxAMDx4zhwAYdlABYuHADgHMYPAMCPFwcu4LAMwLgFHACcw_gBAPjx4sAFHDcMwDqOAwB-HAcAHO-B4ziOGwZgHccBAD-OAwCO98BxATgsA7Bw4QCAH8cBAMeP48CFA5YBWLhwAIBzGD8AAD9eHLiA44YB4xZwAHAO4wcA4HgPHBdw3DCOwzqOA8BxHAcAHO-BH8eBH_4BWLhwADgOHAcA_DiO4zh--IBxXDgA4MeN4wdwHD8O3LhwwMcBH8cPHIAPB8cB5PjxIy8OXNBx40aKw8ctBIeAI_5x_AhgAD7yHgcuHEeqFz-An_BVHNBhHM6PA8BxHHIPHBeAm4KPA9ZxHQcA_DgOADh-HMcFHLB8HId1XDgAwDmMHwCAHy8OXMBxwzh83AIOAM5h_MAB4C9eHMeBH4dxWDiAGzdw4MAPwz9w4DhuHIdz_IAP4IcPwAcOHMeBu8AB_MBhHDDi48dx4PhxHAGE4MWPH_gEBOKD-0gPHK8GxIeB4DisCzgA_wjeBz6OA4eo44Bx4_hxAM7h4xCA4zjeA8cFHLfhQ4fxdzgOAMKPHwCA4z3w4ziOw8DhH8e143ih47C06HjhQw8OvHhwHA9-HG-A93gD-JPwGPCLH8cL5_Dx47jh4_DxCzeO4zF-vLgPHz8OP7hHHD8eCd8JH98By_GE4zieZviFH3ePc8bxD74U_HiOMzgPHzpx4g78Gj9eWD10HMd_nBQ-XMfxCyd-XMJ__PCFAz4uvC8ufPgpnFzx4wtOOD4Oy8SJEydwHCcO4-txmCSO4zSs4vBD4T5--LhrHFaL4zgeHG9x43h4-PjxDT6DEy_xhcJx4_AHfTzuSLB66McJhCEhCQlIhAAKKSBIEcRJKxwAgjkhmLRCOACA4E4IJq1wAADBnRBMWusAAII7wRiT1gEgmAOCSSuEBEBwJwST1grhAACCOyGYtA4AILgTjDFpHQCCOSCYtAIAwRwQTFohHABAcCcEk9YK4QAAgjshmLQOACC4E4wxaR0AgjkgmLRCACCYE4JJKzgXDgAnuBOCMSuFEcoBBwR3QFjJmDBCOACwMMEBx4QAEijHJABYCK4YcgAwia7gUAARDBtMAMGkuNIBoQTwLADBmBNMCsuZEwAAwZ1gjElrRGcOAMEcEExawaEAQDDzgLBMCuOkA8AJBwRwwgLJkFPGKaWEeWYAQBwGmkjxAOPCCcYQU8JA4QhwSAwjALDSMickcOwJwZgTgkkrLBbCAQAEc0IwJqx1UgkngGiKCaYQY0xYJo0VTAjAAACMASAMc8AKYYCzDDAmFBDKAmAZYwYIIJhlggkCgDAiAMCEI4wBpJgBTjGmLDUAGOoEFcIY5wQBlBinnBDSAGYooE4wxpyTjhkhunkSAMCQAOYxy5gQkgnEkANaGGCZEAQgxBw + + 84352eee + 6a63b7fe799e37c708773c2d84139c90 + b8f0cb2272b819eb039462f2683c279a81168d26 + 1572864:QlPHeSEsqc+CJsfmp+lkRZTNElwARxBkvnbuDoFw3ymsWiOkRhh36I0w9K:Q5eIJs5lG/ElwWBkvbeH3s7OgJnk + + + + cdrom (Track 05).bin + 64835232 + + 5 + 1 + + 88687 + 116252 + audio + 2352 + AQADtEmSKIyiKJKCXHiCHzcePMefDxfxCG7CMCt4EvBRS3h2VNzxMMORPyi0HeY0hBd6C46JkzgP-IePcIWOF0dX-NwkfCN0H1fx4zv8oE-G_DrawWvRHx9-JDfySqik40_xsfDdHN_xcDD8nuhJ4DseXcihaT-sakYu3IJj4hlRHYV_-AhXHHqBHu6y4ztwDbmU44eP8JnxoyQhS8LVccKPTD96lML2Ff2PnoOrociLQz1y4j6HX-gdNMeP_jDlFZ_g35hOvPhxpyEy_NCm8khf4zycC2eONjsq_PCRqqihFyj84lHiAscVGjkP6-ijDnGj4XugdRnSwR8H_-jxorfwHj07HD9yvDy0H3mLe4W5HNfxDW98mGRwHodPmuiD4zh1IccPTUeqUsXxq_CZo82OCocPq0doCC8KH8-yFcdxhsh1-Oh35Ek2dIG-DJc2ZB981MdQ7ofbw5fQH3-RD2p4xHgn9C-aejhq6sYHUyrhEucxecOFHncaZH9QQWsPqw1y4oJj4sRz_PDhI1yh4wWa41l2_MCFXAoNH9XxbEN8dCGh87g6bgh89EcJH9d0XDma4ztiHIn7EMdJDfXww8yJ_7iPB8cXHT1r4IrwxUJ-HPrRqCLy41bhmDiP5zh8-EdeaMYLdD18C1-O9_BBncd5-Bc08tgTUgir9Iaf4Ud__MihScjpLqj8Eb_Ri0Zz3OjFw_Yz1JsW4dERST5ERkXIHVcCXmEa9AuL8Mc_PMqRa4V_3LmCrySez7iPE5HCOCH0HdMRUkpwKbDDHWWVo4epJEf540uNE6icIxVz4ofOHF6-IU-iw0e_48d_lM3RVTpiCLlGo4-M73CV48SLmzmOH9dwHI-Ono2EHD-0qYffHDluFY6Jj8MH-PARrtDxAj0sZ8dH4niKizlyZDr6XNClacLU-Ug3HT9-9D6uF0e5IxR5PH0GXd8R5kQ_4T_64HJGPB-F68UjeDLcX-jDA9MPH7cQtxB3wyqFXMfhtMcX4jwOwzXCFYfuQkdXbKeFPPrx45lw9B96pE9mtDv6w2OOP0MPFfmFLpbh8HgCV5fQN8Wpo__hCteOD1-J1i9-_IihKNJEhDZ6C1RatAtxviiOI1yh4wV6-Nnx6MA15FIOB71waYhRkpATCVc4HJmKoj6MiXMt9IOroceP_DPUDznelBm-oxf8D6XZFS_aT8Y79MdeEn1hnEGmy1AvWEf4ENdRaYdPPOPw4_CRqqih40dBOYXO4znw0NClwz8UrYmHq4h1tEoG74I_-Dj6yMTZHnmhnUWOn0A3HR9-oc2Ot3gquNNxvIQZFe9gSjt-odaM4YucCbmIH1JupGl4vDBuJkK1DD2uw4dVhIZeoPDxKNkKHJdC5IePPjoebQgXGV_AdlA_-Bjqo98Pdxc8aejx48fzEqqJkDphpyFq9Ib_4z0eTcZz_Bz8Hn3w48EvRGR16GAWpBe-wznxhcOJH4aPcBOgF0dznBY-GSeu4szhHMwzPNkGlUdJIk-IkRuHEz5-nIKdDxfcET3xf8aP-7iOIw8fJGfRVoR_oi9-9Dn844ePHyfe486BHPo0RKsl3HBMXMT34jiOLJtwSHcBbYWPfTly3PiI74J9PBw-wT6F58N_FEclWMd5wr-G_kg-FmE8tD-u4ybaozH-FX3w4oB_VEegaIoEP8gpwTke5mh5MOJx-EhV1NBxFD7O7LiO41N45DyMUN6FJxv0B-0ypIM_LvBR5_jxU2CW_phkHseRR9AcLTDSo5dwRSPx5-j3wglO9Dw-HT-O53jRI5-h3UJ87EcvDjQu3ALCTQT04tBmmNMOTUfPwVaOoAS_CeGFH-LmDHm4Y-fxosc1HE9-hD169IcvHi-P61B-pI90eBPa4wOPB0dv-BsqlPyGVPFwiIwqhCcuom_QkC9OFNbhH_mh4T2uoYitXUir4MdV9BkpHNrRXMjDHu0Or0WPf0fuDyqPnCR6_EpwUjtcESf6BBeO63h0occP_wj3Q4-KoIfzor5RjbgLH5ZHVNSQQ3_wI4txCR_xH66IB88O_3iC7BE8DnpOOOqMTEf_4Jgo1bDV41YPk0Jv_MgJ7S9i_ERV4xfRNzCPh7hwoccX4ieuozoH4xuiiaEOkRzCDw8eA3QQIxEAYBA2jCsCKDNQKmGAIQgRKgYgAjnGhBVKCOYcgAoYBhAAxjBAhIEMSCEkM44ghKAQRjBhADYEOIAgEdYAJIhJHgCiCEOgKOGQYIopAxAAjCgmAEQIAgORgFYQJxQw2RArADdYEAIUoAg5RJgwQDF1gDRSMKCAABAxCgyDxCAtBBKAEqEAEEIgSQ4DShNriRLGCaKwMwZggggFRjDBhCaOCwWoEVYKJwA2DABmAXGEMMGYgQIxg4CQEjAnjAEEEUCRMgAwIABBRggDABFCMuwAcQAgYxAAXFCOBAAEEaSAAQYKAJRRRDBEHBHCUWQABoYgoIRwFAAChCFGMe2UcBQZhhgSBiACgGQIEESoEIYqYAwRBhgKDQIGISWJBAQAgQFSAhEnDPAAASEEgEARTAyAUBEviADAKieQBgIgioBSAiohDBDCKIMYcIoCAQykhAohjGDCYOcAI6gyAwgAhCBklCDKGeAJMYARAgzAEEFlhFKCAWgMslBAEYhgAgbHHECIKSEfcw4ZY4gBAgiGEAQGEoW0EMo4LAEBgCmNHCBGKAAIMAgRAhghzDFDJCHKGAARgiI4gxAxGDAKwFaICDCAAAIBgRhIQDGBDAMKQKQEM5QJYIBgCiAEqQIKKA0QE4oZwARhhGEAgCCGAOcMAwgIZgWjSmElAIQIemAEElAYgQQDVCjFDVDCEE6KEIghAAQjzCBkBCPCEOaEAAhAKwAhjkAhnFEMNQAAQkwYQYiDxAEllGUKKiC8gAIwiYABgjBhIBJSASUEA0AAQQRnwggmKHPIGAwMYQgIogBUHAKmnAECMeEAYlYAKBAFRghLHCDCMcG4QpAwJIwzEBimAA + + f8cfa40c + edb23ca81238eada2e14a77f12d7bca1 + 03aaf7341b3c9933e4aef8146fb42b452c2548b9 + 1572864:VCCL1nhYju6Pkyh89Kj6ykfggUo2Vy1SdSK9ZjZGC5afvPh4PheAKf:VXL1nhYjuykK8Uj6Fwo2AnK9ZjZGrfvPhaKP + + + + cdrom (Track 06).bin + 78806112 + + 6 + 1 + + 116253 + 149758 + audio + 2352 + AQADtIqiLFEURVKAH2eRQ8jxMAE4t8OnIN-8QXVwGLhD-MfxHP5xHOKJH9BpuMB1WA2BwzxeAScN48MPH8dh_MSDf_Dxw-eA4zC_4cfhE9D3ws_xQ4floz0qCs9xGCec48fh58APHx9wLYdfHD984niPBz5-CodzHA_8GvjhEzh-mPnx47rghzge-Mdx-DigE-KNF28OxzVa1MPh4-EK_4iPI_fh43gOv8Oh4wsN97hyPIRP6Dj84V9xw6cFvMcd-Dic4zhu-MPxw-eAG-JpHA8OywQOczl044WP38K3DJeEE34Ov7jxwz_eHMcPf3iGH88hVh2OHz4PyD384AZ-WMfxHcaHf_CJ48YP98dx1YLVAHfg4yIOPzihRoPqXHCPC8_hbD2KKsYP_3g4HA7-4z_c48edwa_xmfgH-MSPf7Bu_PjhHj8--KHx4w3E48YP8bjw44Mv4_jhhzgu6Bl84jjE4zh-uCfeHX6I48SXwcdf-MRxvJHhH8fhEz9-_PDx4xEcT8B9iD0O_fAJHId747gOP8Tx4Dt84IcPHD98Co9gFcdzfIcv_LgP5weeAT4ewn_x4IfjHD8Od8Mf4_igCz50WA2OH3d0uMePHz7wHI6PGz984MMvuLiGK4ffA2_gH7qIwzKO4xB54RXeHI5r4MThfnjh5_jx4yoc9jj-wyd-nCJx5fDxHj5-yDgPMTeOHz6NH5-OO4Nx4oePnzjMGy8e-DSODz98Cj9--PihL_BrHIco06iOdsEllTB-PIRz_MdzuPpw_PAV9Bna44Zv4QF8JUbR7zh-4_BDw4fwCeaCF4e5EDo-BSfc4_BxHPdh4ieewy-OH18O9zgO68Z9fMxx-LjDFf6BGx98nPjhE8cDxzUEfbjhAz9cXLgOVyFqdM1xHz5-OMdxHOaNt_hhLjSOO7jgE_CFHz9O-MaPw6fR6UTFHYeP97gDC8fPwb2BwzmNEy_xwDmBw8ePy7COAz98HN9h_MYPH8cDf8dx-MSB8xCP4zrMhejRZ9AHX8KLK8rh48Nx-MVD-Dh-uAp-HD8NHz8OkfkmQIdPCz_xKTjh47gP48JzPIKl44dPALcEMweu5fCL48Ph4xbE_DiOj4fYWzhu-KHRnUU1DudhPBx-_LB-fIePH1d2-NNQaMcXGu7xQ7YEHz--4fCFw3GOH_rxKB-c4_AvfHGg4x4c_MQDH8d9XNEhHscLPxmOw6GSQz9-wSR6dD2elXCId_ADHIefC8cvnHBu4Ib7DcfhE8IDV4c-HO5odCh--LjwC45DAi--HO6P44d5_Lhx-Hjg49BxLYf1Q8dHGg1QD8hx57gGP8XHI3a4A3fh54d-HM_hajp-_PAhA4dz4IGP44G54zfg48ePqxPc4zh84tB3uMpxHKdhOsB3iD1uvPBDYxJ64cd1fLgzWEevHt8y9DAPf4LVcENxTD8O9_DxSAd06CHc48dpOMdxZYVxHA5-4sE_uMcPHz--4_BlHD-shoC-wD9eAZZIo4fqDD1-5MWd40hvHHc4vDLuwD-6Gy_64YTx4g58_Hhg7sB5iD_-D3cEV3VxQR_8EPhxBz6OK7BaHHrgf_hw4fDx4CqE08aJ33ixD-7h48vheMGPXkf1ZVAX43gCS-uO7keLfdAPH36IC7hx-HhgFXhLPIeZ48txGgYO5xQOWBYOnIcPnJJhAA2g11QYDwARDAAkxRBMIeQcMgIAaR1AjAklhRBOGCmGEMAg4IxgyjssHANACGGFAVwKYYRgFiCHPANSCOEMEAYhBDgDyIphhUJCmMKAEB4AK5gBEhkjGAPQQSOMEAIoD6wX0AopjEBGNCWREAYgDwCAAAMiABVCUEGYMYkJIYB1xlAHrGBCGGeAMAgAyYA1RjIjkAGEceEAAIBRBYAAQFECgLDCAYYAA8gIYBETUhBnEEOAIqSkU94ZB4QBgBmLjOBAAITEEAQYZxRiTABmCRPcAY4Q4IwJ5YxyQipmmTDIICQMEgYyIAAjADEKDHdOIssIEAgBZxQTyAohrDMSGSAEQE5c7xwSwojDgAJOOCcoMEAIApBRSAiADEAIEGGAEMACYIRxAhmBBABKCgCUcAIgaRATzAkAmBIUMaGAUEYQIhAQADDEoGAACSuFMYIZIBgxBkhnEAGAEgCERBY4ozzDQjkjEQIAKSmAFU4gJgRASgAknFHISAEUlUwADwBAgAqGnALESeuMEsgg4ITyDAgrhjBGIYSUQJIJo4BDkAHOiBQIACSIA04YIJjyQkhmjEBMCCYMAEgsCYQVAAAJAEGAMQGEAwhYqhAAwkDjEMBIHGaEQcwAJIUBWCDAgAUECSUGMIxIAYhCjAHOgEAIOSIAEoMhKQGwkhFhDBDSGYGg8IoBi4QxggAKlDAGCACAkMgwg4xASDjEgGXICAGgMA4gMcwQxiLnCFMCAISkMEAagAwAgigWABMIMSGcYcg6YRgTADGBgDDOiMYEQEgJhBRQwjCAABCGEsCAFIIhJxAQhAAvACNAcSQREFY8ZZwwACmElFHCGQAsEwQgxxRAwismmAEAOYfENUYZ + + 83f51b3c + 1c5bee7cd55c07b77ea356aa065032e7 + 0e395e1620ab9b89a1ba9a1a2f8a8e8c772f0d87 + 1572864:ZHQAKEnRnE44EkTdkkJfSPWNsuyuTfAMdk0CMQBA+AHw+NlZSbdsjR+NyNe0:pBKgE44EkTdkHUNOp0ChBHA1Z+sZ + + + + cdrom (Track 07).bin + 91796208 + + 7 + 1 + + 149759 + 188787 + audio + 2352 + AQADtIqiMIqiSBGO__hx_AjKPMcPTf5h5SNOFf5xfCuOH38O7cTTB6F-Da7xo5koo0X64Q4PbT9-obQeuCquwFULPfBR5XhwJvTwB55l6Mc53FnwXUYlGX426EIpJahj-BcOJ12C6idyScLlotQj-HiP8MS9WFBz9EhHwcwy5yhXhFYuiD_6LEf848UlG4-M-sgP_7hzaDt-4ulR6rCTHK5TQc_geOgc4e5wHa3swNOh6yjuCPJx2WiPZnqGPhdcokdzVEmFWwryJLXwozcuNCuP2Lh8_IV2uNJQDk0X9JeGozqJRmGEX3hevMd51NThOOh-qLiN9njyoNQio8_gkUF1vBlxUqlwXWBSp0J4CUceDp-D6xaqH5IuHV90mEkYhD_C7KjMxAHZ6GAkQU8mCllIzTiNo4lzlNKRUX6CNxCjE89x5Ug_xH_wfGh-tJmCS0kZ6Mc74zOFpkMXZsb5GD0PLbPwBeVSuDpK5tAuNEkykjiVCHlc_EHpI-WG6sMjdRq4gxeao1eE60UZDl8QKi3uxHhlPD3CDE_04jo0uXijCz9y-egLdzS-wx2H9KjUQe4RL72CvsR7tA9-NCqNUGJofIKWHf2hKzd2Xmh69MR1NDoq7hrKFe6D_PA4YQtq5XjOBfGHhnF-aFaOB2GmagzyC03kQ27wRUe-o-YF_0G_4IjFsAJ5DmIWHgfLo1eOpmqhZ0cTL-jaIRYT4UlqIfQNQ9fhC03U4Rouy8Iz_GhqQ3OUHe9YPEd8HteE8_hRP_jga-iDeMvxVJCPJq5RD-GjIY2kzLB6aA_uMMclfEeb-zhNwQ-0H_eEHz-aSjpKBkwVHs2k5NDQPMtxEvFvfCcqDR-PC86HPAKz4y96nDy0JjsuG4eWeDm64o9wMRO-o3YKs0LJ444S_Mdla9B6vIansXh6PMGZofrwDqpSBZct_OiNC03UDF-h5tVQ_jh01DmJo0eTH38QS1rQXwibGz9Kwj8qkxq0PfjhscgzwkYp5fgr9ESTiDoiSyTepoIe9MeUkcHHGT2D9R1U-njEHEce4ooSI9_hQVMmZsUzhCqaPWgdeCz-Ix1zdJ-gaYevIl9yhEetWsPx5IO_Q9MifER_-B8uHvk95GHw49Ce4ySRJzNKVUgfXIeooxqRSxd-oi6cIyRxLSMq6fB16Bv8fLgI_ygZCU-C78d94od2uKLRGueO7qkQyiR6pEef4kKtwqPg_MjFGJd0HO5l9EP54-tRansQtRd-aOk_lJLwHI-LfoHjRIYoVD5y5XjyoHzhC33wD3nIDOr6BL-H0GKOxgouIvzw6NCUHB-DXBeuHP0Fv0fIB_9wjSmkXWhOgXkrfDQeuHfw6qiORj0uKTyuHVomrkGPL6h-dGFmfEcvEj6DD4-UwxU9-EHl5chNfJOJKy56C-7hUUPKo3IU6HgutNXRTMqOfNHQxkjXA1riJcd9xExIlDp-_EkLI5S0ERfkX2jCF31mIRfRymgm5chfaDoa9YglpVTQJgWTHX2ONGZwiJqOH3zg46UC89CXmMJ1OA-6VMGJPNfxWagPv-gTEjeD8HDSHToL_0GtFl9y1FfgH3eG96ikhnjUFMeFJlR2dOGFD_2h5T2eaigVykRTEX2Uwzm6Zkcl6UFD4TrCozkuEZVz3Mh_nCr-QI8Kb8mIXEefCv9RJYmCMM7xT9DPHKEIjzw6LTNKHc4Rkj36wYxuPAu-jMhBRT_6gVXSOGBSq0FY_If2JSEcMcPh7LgfgfpkXBGhzzhxh8hYyXCkB632gBWYx0gPx0QXKVD3oJkt9FOO7Bku5KHQ4z9ko5KkD49Q8_Bx_OimjLioCz-apyiZ6HiIH_xy_HheDVcm46jjFD_OwzuqEXJIXHKm4UeYo1WIa8vRH_4S-EKlC7miXBGu9ajxBPdhpUeoDeWDDz6PUouQN0YbHTpJ_KsR7sGFiuFxnId55KjcQJeJI0uiHyeP49pxHjG5DdpCIV4UfEbBH-kJ9UeohMQDFEwYJ0cu5dBspDHuwfmFC8yL6yh8_LiPysRl9Eg_XJEMLcYVVEaj1sYVSJuK0MfxwznK7viEG6E8WdAZ4jHy7cY1OHuK3yilF6GaHPoRHid-ND9qHT9C0dBy5MqF3nBlcA6sIj-qSYdGqQ9yw8GJZ8TLI8U3HlKoLUfPI__hLRna6EN5OD7CTVGy4lJqaMV_IQf1I5aU4To4GhdOXMOLnFvg_sJ_vEQTdiy-w4yD_MeP6rOCZjzk42h4XDm8xYXmEdXRCGeIatGuwNuJHrXg4x0c4w8sOSzuisGjEKJDlFKOHnqFizyuKMK1C81DXE0TcBuaD9oaFn9QNC--o8_hKngPMdGOHpeSCbeF_vBVVGJxzkI34b9AHedxfGHgKiNOw_mET9lxLUfDPDh6ojl-dA3EHN4bfDz00fCWHteKp4HjFuFn1DIeHelk-BaO_2jUzLh0_GhuoWQO5TmaqnhYnMTFwEoiVAyTQhf2oF-QH-lIcfiC5_hj-DjxMHB7OA8eZqis4_bQbw7cF9-Io9NCAEOMQkohDgRxCBCAAFwOAQKQAkoIpQAAhAAJFDLgAcSEIEAohAShAAijCAMEEAYIIgIQKQBhShkAlAWGCEgQIEohBAxgDAiGgEBMMSEIQJgAc4AwQAFihDCEISSIAEYJqoAASACBACGCCMYRA5QogwwCRjigAEIEACAAYgQBQ4EAgiIACGDAIkAMM8IA64RQQikAkABAWikMUUQwAhwBjDAihASAKEYYMEIJBQQliEKAkCAACSMAZQgQKYARACjEQECAAiAQEIggIIhgAggIDBACAEaMUAYQqTRAhhBCLAEAEcWAIAQAhgRjQBClFDKCAEYUKEYICggARSABLDGECAO4ckAIYIBDiDAGgRGUASOIcIAIQBRQAhgCAKBgAYIAIFQgRZBgRBhAEBIAEQGEUhwgghFwAAGAlBJEAAEEMAAwhYQwxCgCEABAEAEQY4QCY4gyAggAgKBIIAUIcAwAIxRDADgDkAJAAECYAhIwQAQRAinjCAAFAGGAMkgBBJwCogECADIGICGgUAJwogAgRikABCAiFAGQAIAJhIQiTCliMCAEOCMMUkQQBRARQDAjiFIACEeIE0JAJABRDDiCFAOAICgAUIYQKgECwjhEFAJEACMIQFAwB4BxmBgEBHIAACGBMcACgBACgiBgmnAMCEAIcUowQQAAwFCAgAAGAaQUMAJJDhBCjBmAgEDACEKAIIgQxwgAxFhhgSHAAAQoMQIAIQQwAAhpABGAAiWQZEQxIABAgiAhAFPACCAQkAQQrIhxwBglAREAIYIABQgAxoQhAClgDDBAMeEIQ0IAxohQwDhjABEIEOIUAwQAboACBDMKIBeMACGBQUwBIwwCwAA + + ce208f21 + 043d474b33f9a4a5abf6bdbc6776329a + 5b67b55f9cb239d6f82bfbf37e23f33011874d3b + 1572864:ROux5XKaLtemPbgKDNiBWdI1zLwRy53zJX3KpCH8g1IyiCxBQPSItEUMQtUp6fW3:8uSa9g74dI1fwRszJX3aZgiEUvfIfFd + + + + cdrom (Track 08).bin + 59637312 + + 8 + 1 + + 188788 + 214143 + audio + 2352 + AQADtEmSKIyiKFICPfiRHzxOGj-cJ8hvNBFf6GqF_EJ_bJSOk3iWYcd3xISvC6cy-IP24-jhoydeXEc_-DD4EEdzHIcGH8yJs9DRHj7E40fx4cXB_GhGPDz-QHBM8Md14WRQ68WLJxfx48UHEZ2Hb8jR_CipBwjD7eg8XMdx4CbCweiPSPChnRWO5lLRHj8uo-ch_jh5-PhhmUfnHUdv-EPLHy_0Q4M__PDRHT_yBxeHo-HREzm94X_QqEXZ3fjRnNAH-Ih_9EbedLgG_eiRFx_e4jg8Hv1ynEJ-9HhN5Dv-XPiLvEVX6MuG_gjzA6eCHz2J9MtxCVpGU8GpHDlTNCNK5jieGj0RhhQuHj3-BL6FD9rxo_3RrByOo2SOhsePHs2Ls5g6wn-MHsePHtYH7ThyfAd-9PDRIz_ugcePH72JD8Z--D20Bz96OD963IwE1ah12DqhkvALa8N9_IOuw_rxx3jx47hx7Ohz6KKIE2yOS0cPv-gBHb0S-BH6H_ODhgt6_EcPnwjv4bjxoVeJBj9a-MjhF7-MPxn64HiPvtDyDa9k5GNQMjr8Imfg7yih8_iTQiNz-JTRfbhwHuctNMcH_caJBz5a6JiCzvOhG7_w4yzeoxf82NCzw-MT9MOP5uiM3ziaSOgPfodeFsjR79hxFc_hrTz64EKe4sePHv3xseiIj_DxH_rxtMOFXpqAnh58_DjhH8fhB98PnSu2ox-Oo-7h84bRCz84H0_xHl3RHG_woD2mqMV7_Ghu_PBxlEd3HIdzBOaOnvhR_fDxIvx0XIf-o0dzEX9xHM0VXKnwD97RB-dxFs2lo-zE4Tv-9Ch5uIN_-AteAZeKaryO0zWm04PPQ8OPD2FkVCf-IDyo72Dw4A603miOZ8dRuYZP_HjAw8IH7ceFHN-B1yh89EN-3Dhwoj-MPysOv9DK40eboTmeDv-hD8177MeJF5UO1A984diPLyZRXJEEMnxC_OibCH6UYzpyG2GWPUSPHz2siQ3MHz_0ToarPcOH42PwHFYO7U9xWYjNEOdxofmPHg-qvQi9o9fho9uP_ngiVTBv_OiH9wm0Mzhu3AnsZCip4-XxJUsM7TDroyfxhBXxCfqH9odcsjhV-Ef440era_AvhHuHH9WhBQ_-o5cAx8VDfTjMMUYpHrUOf0fJ4jfxUDaahxuuHj3eDdeMP9Dew8eNJv7x4Md9NBemhhl0HDq6kKph9MZnFC5kJ0dz5Md14dmRow-cHxrOI7_Bo5aO_-h65LpRXYYJ6IH5QjyO4sUrFUeD6sOPQ8sP5sKP12iO4zgOH9oNBMe34vhR_YOPHtmPPxB4yKXRw_lwCv_h3zh89Dv04yFuHT8eHu-N8-iZgsmPC4eeo6l0dN5xPfjR7Kid40N_2MWPP8R7-Ed5PB-O9h60vLhmXEVz40yIH_5xqgY-6DLuIO_xo_jRHvaHPtGR4zLw40d3BcZu-DiNDzpOPPCNLz-qF72wa8N7aPgiZEmq48aPw89QjUV0C4X8wBlyHulb1Mf34IT2YTv64JAi8gmamPgxovmO_gh__Eh1HD8U_fgR_MePH90NH_xd5MkhV4fxHOfxT4X7QrqP6njwo4NjvC7Cz7jQsnCHw8ePNIfm6RhC_7CPr-iRoyd89PgL7UJz_PgeHFOK_nh19AYTTheO7-gK8Uc9Hv1xH9uNY3oE7chf3OiHn-gN70fl40SO-1B-NDn64M0xRzlO1I4GPzu0HyhJ-Oh340fZwQ_044celOIR_Ud_XD989AwQwut-CEZJyMdxUWiO6riCF1oDx0zRP9B3BT20nMGXHEeD4tNxfNCeHPlxlDwe40dJNP-RLzr-Ak214eKRW7iGc0VarugzQ93QD2HG4kf-FD-0KAzC4_RRDvt4XAh_SEXuo9ex9Smq9UCP9EZNebigRUfv4S3-o1WE5niO_Wiyo29o6H1Q-Zji4MePPoT_o-6hH--RZ9aOXjjFwKLwo2dj3EWuoxbuC9px6OKFO2g-9AZ6G2LnDYePHj_6sDgAgjRxHBpPACBEQAYsYYYAIAwlBhRHrBNIOCscuMS4JpQAIIOhGBLQGCYAI4JRYKlzgxDAKLaMEELEAI5QIowwgEEBCFnECOcINVAYCSSgUBBlAABAMYUN0UIAqIBmVBzCGGRKMCEEMAYIBQAyBBoBmAGKiCqYskIiKxwhyFLKBFfAAUREREoRU7RgDFPBLIAIWCZAogJYpBxiZiAimFCIICYAIpxgJNoByESgsCJoCGGEE0QoBggRRzCDlGBGSMYMYUIQQpQgSBhAgAUNEmSNAFASACQwQCJEBADGEKsQM3AohgBVQFNlkGCEOoCsIAgJAAhhChEikHEGWCodAIpaZ4EQhCljjQACNEIYoswK6pRxgiIqiMGMKCYEUAwYQYmAjghsCAGCESOENEAIQgARAgDvFIFWEEYBcAIER6XWREmyBaOCWWayYABoZaBQDhigBIAIkwsQSQoBAiQAUEijgEMCMQQIoYYZCRgxECEAhEiAAACEIEoIQhUQjhkjCMFIKIkMAAoo4iQAwBimgDROCICcYIIZoAAEiikqBADICMOQIMC1zhwhTBFFkGdAAqGMFgQQIwFRQltrQGBGBIMcYcDBMSix2jIkBCAEAwQVdoQAYRgggCgIDGMEEcKAEJCBoAkUggKHHEFWCKMAEYAREYCiQDCrBEDSOAQMQwIJqKgFzAginOBOIgCEAkIYpChicjjBAIAGYYMEGI4AIQwhUEqQCCEWEISQZYgAIJhEBBIDADAGUSYJEZEpB4QiCGFILEIAUIGUMAQJwQRIBhgmDFAKEO2QIEwxB7BTSClDAEFGAyUUJQAJSwEkDhkFBBUACAIAMAhJx4hBQAEjxDEEISQJUtQAYYAyhAgoRRMKACGMtkABQYwwAhBgiFJCOQAIYIQLJoAxzjIMiAGIIUKEsAAAwRAhhoICFCTACOQIQQA + + f2e1d23d + b16f6bf64d62005e08e01292ef2fcce9 + d39945531f75c0b25e6519420d445b4024db07d3 + 1572864:uG9F/U3AjoCHF1xF/Z76oXmTcDnhEU0V75xi:FswjoCH7fScbhaVb + + + + cdrom (Track 09).bin + 68986512 + + 9 + 1 + + 214144 + 243474 + audio + 2352 + AQADtEoShVEURVJw_PiFQEfgOirOHLxuOOkSC7eR7DnyHk-CyR-ewM-PPrh0_ELytEJ4OBe64sfv48crGf8L4MeP-5h-_AgZPDx05TgRrgz8ox8i8YPjPLgUHH7wFSF__OgN58GRHxZz9Inx41okNHxQ68J7aM_hGj10NF-O8JJx4hVxohGRHzqzHFt8PMKz4zx8PMeJND9KPNTR7zDC5_gDHz_OnPiLMEfYhcdR_WgeyOZxHf0Fj63wuch1_C784MGzHD8Odz8q2sdrHH-C_sefo4gO6AoRXgd-4ERz5MeP6wirLHCk40ffKviOZ0TI_XAf9FmQE8dl4T-mU8fFS-iO8_iBPsKP9IIYOkEkPFdQKQ98_DgOH8-Oh3CoHvfQD1fxHO3hKi2OI72JB3pveEB-_EiLPkMPH5Uv5M2DRuJRScKNPNiO63iG8-gPj9lRphfkozeaBzduaMLho1YW6GiC8MHDHQ9CNNWNR8GNHD5-4slQoYkYHTN5_PiNfzj-o4fPIz2e4_AP7Tt-9DTSXzj8A2fxwzn-41sO-zgu4YR_3EP9I061B9p5hKGOB8dFhPBxHsqOvkdMdN3xH95x6zjhI7xxH4f2wCr26LjhGc-u4MoD10afBflR8_CR5_jhQ5WOTqfQL4fPoz1-RDqeCl5CGZ0vhDf8QxMN5EaP-LB2I5-Cv_BnXPiA9OiZ48JR-Dy-5MAfmIyO6ziPI0R3_GieAC_6G9t19PhyoUdzHjf6DP7R40fYFf4h3sPRLjP6w9yCE-LI42IGfxWhxx6uB-mNHr0GH_9Q_ngTHT_-o83xw-txRPtRqCZudB38C5oeHGUQ5scXBid65MdR9sJ3FedQ_fgEkxl-YtLRG66KHveNHhb6KIeuDz8akUHIKBfOHAhv-OEQPjSO-vCPT3nwInVayOkQaj9-XMeNXkF66MPDB3lvnMHx4MARnng6BZcGRdIvmKM1_IfywykVhMdzfNFRn2ie48ePxiH6hEN1WO2NsjP-C-2RH344fPSQHl-QHtVH9BCd6ahu9Ed6Hbl4HCJ5XDqOszguqJaObg9i4Tn6oDlx4sM-HCUv_DL-4D36_Dhe1Dp8_HBMhMatQ4dGHo3k4w-eCtcNzceUH3uIHz3OGaL-4dTR24SOZjomUbtwHif6wtnQ6zjyByWJfw-uHbfw6sjzA3rww5SOP-iHH0elFfsyiDx-NF-QK9iP_oIfhJ9x9Id4ofPRw_xxSujjQbuRPujxo_MJfxeqrTd-NOiJz2jO7OiPI5cOLTcO__iRJsY7fMihHkdn3EcPv-hPoz-eC_pcnD_SiLiP40cwcoF-InwenMgzE_-gHekjodSD50I_NM-MXAr6vNCh4x9cnNkhfEYY5zhuooQfhGuLY3qN4xWCIkcv6Pge9MeZHBpZmEPIDveLHz1z-IlwGOEafDHG-mjGHn2ODxMPV0WPo4eWWAK-Hmjio-x8_EJ7NB9eozlK4qGhU0YfNGN240eF9NnRdTJ2VIersEOP_vCL6uh5WGFQi0DIy0iyKoO_oGtxPWjhGd_wI9fxCXIzOMoV4w90obYRfnhxmDxCcsd7_EXuY0909HBv9HhuNEefBTn0o1JyWDu-pHg14LyQcse1cLiJLdXwECeeoGcqfMNzXESfo4l9vJmID6F-eIzQf-gN0ZuP_vgv9DvEETduuCp6ASV3Bc4edBGhPtgPLffRFydOofAuwEePozpEtBw-lL_hG52BHj4Of-hxfIdG5ki5CyVzoLnRF4-C5jL648EVhJkO7UIPd0eLmSF-aOeRXnh51HfwIyyh5UfeHd9RHd4Go6-LnkaY70iutMOj40dPI70UaDpy8XiOPjpyp4Oe6AhJVMqNzTn6Fz9yopcA_ULJCP-xfjcKc8WL4y-s76hofOiPZuKDjzn-A-Jn4_gQnrB1lEf1Fs0eE2fxIzwD7xZ6KOovuEdLHb_RchAVFj9-pCf6ybj44ugzwsdV5JzgEzqPH-KPPgvKQ0vwjETlCX47lFKOV9B4-CfqLUVOoz_840Rv3HiOZj_xLccfuCi74PzxVSia78OXHI2eCrUkVB_St8ehpUJ045pRXChD_PiDP3hElIftoj9OnD7y4OHxNMd_7Nlx6jEuVD98yCR2Io2EMhd-FeFnQayD4sjRjDl6AKQwYi4QYjCBQiLADBACGQoMM0AQQQwkCgAJqAIMMCgEMoIJJJxhIhihGFKGOYEQFQAgQhSwaDDBAIMAAGYcIEgxwqQQhABBAPHMEGQcEswAgyBQxBkEDFKEEMgIEEwJIJAAQCAOEBgIQ4MccAw6gRBBQgkFiWEEAIAoksAQpIxwjiLAQGDOAmGBBII55RBQ0hFhjBHGgImYYEAhQoRUCAyqmBDKIKYkIFAJBgVTAjJghAVQKMmIIMAyAgwBykmCBEAAYVEcEQAAICACTRFikADGCOABcUABg4gBgBhkhIICKEIF0kQAwQBihBqlgMcGCICEQZYgZABgiiECpDMMUgWEUMIIYggASgCkhBiGWiwcAEQQhhggzgkHgAAAAciUYZRAIiwByDHhgCNMUAQEEVQpYAgBxFggiFEAkAYYAgwB4pygBnNiBGFUQbAAJ4IIgIgSDiCDBBUEAAkAMEAZYCxTCBukARBIkEIQc9AJR5gFzglojAOEAUKAIAg4ApwywiEqAAPKICaMAcAA84QDBBDBCAAAMEGFVEAY4owBREiCHBWCGEQAIkA5o4QAhChkCQACAEKEA0goNRhiQiHNgCIGKASEQIIpgQywQDiiEBJEOGCBI0wCJYhnABAAkAMAAEYYQcApQgxACgkGAAOCGAMJJQIoAQkUzDOiBDMAkCmwAEAAAJRRzhjDGIHIKEKEElYYYRAGRhkFGDLMMQCUQMIQMZCSTAAlLDJCCUCcAYAICw5wxikkhEMOMZMcIIoQKARoRBmDBKOCMegEM1QIaAkCzgoDiGFWCKEYUQQIAIQgThCDBEOEUMcEMsAQAIhYCCAmDDGCCCEsFNQBIZgRggAABBUMASkIMEIoIIBQDAElBAPIOICUkMIwRikQBBACGQAQAGIIAERERUBwhkgDhXQAMmEMAAgYQggzgBrGEHEeKQ + + c02692e1 + 54f1a5a8a02c56ee3a7bb412b88fabb7 + 75cba3f2871a809732f5b73a2da0891111f2641a + 1572864:3vtCFjJahS9n07BF3YwSbpqz9S2b4pU1s54JfUg:wtsEnvpqz111s54JfUg + + + + cdrom (Track 10).bin + 37876608 + + 10 + 1 + + 243475 + 259578 + audio + 2352 + AQADtEoShVEUZUnw4_hx_cihG2Hy4OUyXJFRNRrhUDqOEL8KfUGesPjBW0YPn6gto3vx5iAujS3yJ_B36DBznDm-GM15_OClQ-_xdwhDKsd04Tx62M2F_IeOrwqs4ulo7Mwhhj7a4hf6oOkr6IhfNC465IeuGj-ipgeqw2dR8sJpfEPr48hzXPhxiD-iSzAfHD-acHiR40O3E0cfVG9x-A_2QDyOPDh-OD5qHz-QG9qbBmn9YMKP3nD2FaVEazgixTU0ssOVREeOHxUfWLEo4SWeHZ1cIseDarugwsx2oWdGfA9-7EMPx8eFi3AeMIc28YG5FeFx52BEDj4eHT_SS1BO9MH34cSP3snhL8d1FTpOengZDr_gFz5x9nCpQzuLkkfz4T0eFnpNNCd-hHmCKzv-oftl-CH6ZCS-I8dvyJFxh0dzGv1xXMmhhzrycLgYCk8UhkZ-9Ggu4s2hSsIvaM-O5oyOO2IOOdtx48ePf-g1C86DPhf-lMJ3NKco_NGhX3Au1DoKi8mH3sSPPt-Q6sRZ5CQ-_AS0S3iNo5IHX8FP9DkeJepwPHiPnpCNH3mD88dxwceuWMhn_MKXLUep5FCuQHu6ojmPD1eH80FHiOSGij-O_HjwKyjSo-KgH2eNXDiOoZuP9MfI6TgRHD98XE8B50bI4g90Cs9xSkfzoMd7HHou9MFZGUgDdO1xnD-C0_hN9A8s_McP_9A3D33R40fT4yIuCzjCX0g14_hh9IT-B_Vm-EeOH01-fGYQRkF_4zxxHn2EJ0O6hUfZ45dxKeij49SIkDh3KEr0NOiPR6KFH6dyfEOPS3sRffBT_ER_xB9x6M3xthn6wHmKXsGPnlXgNMzxHdVfnOhepDzxXcWPO7CL73gunEKoH_iOH6qfoM-PhnizHJegT_CFS0fO42rRP4WNf4jkHerWMziJA_8ERbmC8Dye9sGjEReZ4znCH02cKIeO5w_OC72E5sdPVOrRlUG-45hv9DXCfC--4yeULztOND-KHj6Ff7COEMePHv5xo8cRLvqNElCv4-jxD8f94nB0FM-L7og2-QjPYhqpo_nx49CN_zj0o5wdOEePH5pvOL_R4zl6OD80qsePH-34wId2_Dou3EOP4xOe4z9cNUafefiO8B18HZUZoxeeUPhipOvwrRsUbQ2u4eGFo_zh4_iP7xPcrQr2Hd5x49qhdcUv_MI1C82XDF384xEqdSmaH_nwXpj84Zhi4xmD6xya7ejx413RHD3aEX5RH-EPv-gNPRuAT-gOux6uo8fHo9vx8cCDH0Lt47iG_LhQTUFOfHg96BeaHw-e4xqPPkWz4z2OY_Lh77hw_Nhx6HCQB8cP_-iv4MeR44KeorvhBz3048X148ehyMsK__iH8EfuEeXRnBN08ThahYW_YNx0WD2-4HrwHn_wPniQRlYQcho-4YeekOh57LLw41Er6Mqxo2lD4k-QK_zwXEN5HOlpnAgvHdcJVKeQckuF0yp-9Be6Q8xk9CKuGu0x5bi044cUaXCNXDtwHFcdZFaWQ9_xYjvyLchHlDP-_HiO5nzQB6p4dCKa57iI_fh4DT0ewsej44nwYct95CRhoseP5z3-Bz2e4yhqhYe5oyd-dNQx5R9eD_kFLfURakvxK8fVoMkeoztxKsMvhIcvBX12jMfxP9DyCz2Pwkd16egFkRm34Hjh8-jxD6exV-ihHvsXnDnyDxe-DocrtOfxHEf0zIKe48ErfXguVD2aZ6B1Qj9cx8FJI3x8hIk4PPzw_WjONIL2EB-6cD98UM6PL8cH59Dk43SAphf6E9Uh5uiFnkJDEvrRqD165PtxND3KHx_C7MnRqTp-fHVQUWHh67gIPxJ-dL1Rb4eutHCFD8-FPjpetMvSoTnxC-dxiA_u6mhjC2Ee_MKFdvkQRpehFz9yYpeDy8Ep4y9CndDy4OmQ48Fx5tiD82ieBP_QLOqDBz_6E9sXVNfwI1_Qx_ATkdCShh4-pnh6-A8ephr-CSVj4xch4nqM50gvHNbRFy-O_KgeXEcPdIdlvtB-NO_QA42O3riG49A87MaPH4aO_sh-1NThC48PW8uE0D30ouERngd3CkfTLUc_HH2Wwz-cFn16HDlqvRDPoyeqo1GLH00_od-RX2jOoM88EM2zDqGMX9PRDn9wHT-6LYf0C82Dd0g_9McXFb-OhiRqH_mhF81bIjyYo8l3PNqQ_0FTHcwz6DnwDVem4TJ-nA_CXEG3o70BA5FyhAERjBQIJIGQkEIgg4QxCgDpBENAAAmMAQgIARQGBBDkFFLEEQQ8YkhIQaxAzAFTmEOACwWdpQISB6AiBgGkIAFFMkGQFERIJcQRpDjGGHHgEKGAQQwrhZBQAgiokGWQCCCYYQoIwQwHAggICAPKSAYYAQ4YRIADAgEjyWJAASVEIgZAIIzDRiClhAAGAEIBYoYJYAEgQjAAABEMGiEMAII4YwiTDAwmlDCgASUUEwAQ6qxiRACgrAICMWIAo4SJ4hAggognlCBOKSUIMJJQwwRACiAyGHJOAgAYAAog4IRUgEBzABBQFGIBI0AIBcBDhiACDCIMU2aAcMAw4wRBAiCkjDXEKkkIAcIAgA0RUAiEBKEGIEKJdcAJJZBhSBkBiABEBEWEEcIIggQhiRAggCBAMKWAQkAIYohQUBij4BECGCUUIMgQLRwxyBGsHCUUAALYgsIgYKlDRBCHhHIQHCDAUoYoRoxQThDjCCXMAEoAAUZYspgRQAjhEHGAAgiMYAOYiAAgBFgHCCCOIQUAMQhwYgh1QCAtiEEQOGIUF8o4IQzhwIgwhFGKgSwIAEiQo4BQAiDxnCACAQvFIIICQYVhCjFoCBUKmSCEQiIJ4gQiVgBiBlEOAIKcMsQLYJ0QhgJjkAMGACUgAk4QYpQDhhBikUREOAAUc4gQJAoggADAEBDKIIIYAQBTZASDRighqAEEGCIYosAIAAkQCgjBhIDCASYwEAZzIQQgyhgAMLNAEGaoYBgg4ZhAkASjJDWGMSEgcIAgQwgSDBECgCOAIoGEQcYxIxAxCiFhDRAGCKIAcEwRgAAwwACBpAFCBCaMIQkBhAEIAAHCAMSKOCS8EsMghghBgDJGgBBEEQWMEMIoYJiAQBkBxABwGQCdJgQopQhQYDwBACLAOSOoAUYDIowIRABBiQBMMkGEAQAQpwgQQAjiDFOMEWIUE8IwAQFRwgCFAFQEACOgAQgyYYwAEg + + 7aa314f4 + 712af004d77a3ca1719428ff8850b651 + 9f45738a70bc6d6ef5dac6aff1b792e4fe16383f + 786432:PxICYbz9zb6VilMy8n/5nwCnNeXIXbo4it7ryWCF9bMfdbHQyuvhVgtyGN:PxJQNeiTHSNeXIAhrMF9ceGN + + + + cdrom (Track 11).bin + 56019936 + + 11 + 1 + + 259579 + 283396 + audio + 2352 + AQADtEkUhVEURYnw4zmiswhyHM3W4KGF_3CcxcElHSEXrdBzOC8eOP7xB9_Qu8KVZcVvaOcDf8d3bEpHVFtaMNyLq8Yz9MePUPxhsRc8aYdfhHIOFq9c9BdMJRFCPhP-4P5QpeHh6Ub4Q9cp5BFOBn3gJ8eTd2h-_M8QfkiWLTz-44mIssvRSMd__MSLaxqH8DG0jPRQzocWNcPNQ0PzLN-gGheaHz1DI2KTo0eTh7gU4j_OH2H2Q-eDPtAR6sqOZpFmPD_6pcIUXRV-IZQOfUf8HZsYcyi5KjjSHz-URxf6Y50y4s8h9nhyxA268jhfXD_yjEHzD_-gTCEzVFuOcjl4B5eCPsdnhKJzWOwFT9pxZEl-4GrioqeQUopQPsW_4P7QeTkcijVC-tBPIWdwMkEf-Dkusmj04daHfBDHHnEZ44mIl4elCz_-4z0-jUO4B81-aGSPxoGa5hD83rizQxb6ozlDI26C6UGTh7gU4j_OI-Q_iD965dARXjwcRVqKLj_6WWj0WNi7CLEO7UHERzcsxhxKrsMR5jx66NSFPsenjMIfQj9cJUfcoCuPv7gyIme2oPmFf4d4BpOSLB_6HOwdXEK_4LMRij4sNvCkXeBzpF9RHX9iTDaFlFJQPsW54PowxsvRhGKH8rh2I8e5JNB3owl3dCFDoskdI-yOo42Ywls4VFQ4_MRD3Dv2HNeFsEoOlS-C_2iOHx_eSMctDj2NNLKO82gcLSLuHPIH57j24vgh5qGOnAtuDz8a5SmqawJCnoN45uiV40h2EU00La1w4V2DRs-DvhOuR0j2HPF3XESjLHuEawjzBT0F3UefL7CmzHAe4odY5Ygt9CHuV3iG2HXQv4J_OA6hKcnIYXpy_A48Cf6Cfkco2sYffNmF-4OfhUYoH_Nz1M4EcwlCLsxxKrg-PB6amPkQUs_xHvqP_MIfNA8usoT1odfxB8nyDiFXD_eKR2iULkd7Hg9OXA2HV0KY_UNPC95SvBn-Q8tROcuhHxf8401OIT-a_Ogb4tFy4wj_Q9yPXsnxFzrCRFaOTkpmnEQjs0J_4S8R8oW-4I2IRjm-KuiHJmZC6NvR5NC85ehOBT9cZUF4oaoK6ynaC7HuoB8r-IfjENpCShin5OiLawOfoQ-RxbrwpsQnPhH-wGeIysGN6cGXfEi_QHscfIkLVWSOSXnxHFfR_LiFP4b2BFpidqh_aOEm49g7hHHwhRu6GOh5NGPxDOFlaPGRM6pkvBouBbWKhqOI58jVbriG7jm0nGgc7ei0jND5oDn6LLiGP_AevMmM_Eaz9Qza41SG_IO2tGjKrvikQb_iwNeRM3h-_EYb1fA64-iPHLq0IGeuoslERkG4kOiT5UWT4wqeozKX4YVVlBOP-MG3zMGPMDrRM7Ghf-h-OFq44FVM7IF-8Bk0_ci3ozf-qAkukO2Rh8GPLVeMdl6QL0HzovaD-6hiHp70Fe-R7MiTYCf6wOcx5haal_gQ0iKS5WGHM3jGokuXo8EZEu-P_C4ejdDyGBWqX2gs4tHQoyGXC_fxQ4uOcmGO2PlQ_mhy4uOFU8d_Igzjo8-hT9AR9pngB8fDacVV4peQLxHEc4i3RbD8oY-s4IdPBI-pQvuHZ8p0_BAnHX2OuCl6Hp2P7yJyLhb6a_AWqGlY-BSDPbLxTYnxRBmqf0VeHtOZCl4SBdePK8iz8KiOO8YvGWElHs1kCsclC_GXHM34DIoU5cGVD1eCntDyIN-CD88blDfSH0l0Hf9xJsdnovOJvxqmH_kXJLzxj3jU45-HJqkW9Mne4MuxB2GrGD9UT0d3He8hhyf-wg_OHT86NFxp5Dneo8lDdFJ4_Md5hIf3B9p36KjmEGGURimOZ-jyVHC2i8iZ8tAe5Me35GjEMyirI8yZFb3wE9rzBfKUifiL_0ifrHhTdKVwlhUu8sgL_Rz6MMeWE3EStnhdHLki-EHPCqEPR2uOVD3cH5VzXCfmx2geCj1yZcJVFccTKcsxyWyEtFB0HHlUfMnRrBcusoOFysgHLWMRql3xfXi0aCEaHrWIHz-upcilDt51XD2cjziT4xv8499x9Gh0Ds8RPnzgF-1xXsT3IvwFcaSHfznKQ487hDmPykKfJRQ8khW-w-tz5BnEH6G0I5wYEs2uoFeg5clx6uivBN-GH-Kd48pE5BSuBZ2PKz_yOGisF_oHP8S1kEOu5YjYBx-0D_pxHuWaI79w8WhiBrlyPEdvw4zyo6eF_NlUnCIazTmu49Lxo1cm4TPy5GiO-sUP_cK3IxKc44Ll44yFhiN-IT-0HCEfDsefo9vhZSbC4XxxXP0ELYz4oDy0u3Ca5MUDLeKgqsfZ4bmDZuRRHcGf6Dh3VNYDnzPMMQglLXIE_UK4K_CzDaGOSlxEeBlzdI4rqEZ9BX4qHD7iLS_MiA5g9FuPVw_CQ2yF8HiZoTr2w5oCc8eXB3kylciJPnOQh0yhVYmNtMdNUCR-vAIlxReOhJtu5Lhp4Y9hZx_2JchzNNEN5aeKvDmuH_5x_8iPN5Khx0IoWNhj-BFyMvAXHVp7fMhN9Edz40FffJKJzrrwRy7yRocufEen9QhzOsKXI0ejC_WhP0F-NCf6Bc9xxRmeHs13lB015GkaaHfh6Mij48xxCulz9Ed-3GmCUz96Fs2XNDiDsAoP8QxCise74-1R7RduwtqL_Eh-VHqP60GfHv8s3EOlrEW-HFOGGy_hLytU5DsOxQiRLhlGDGAIIYGAE0QBYYQQwgJEGEOOAAAIEEgIgRgwABkhFCQYICAABIIwAghggDgiGFICAQAAEIgJo40AwBgAhFAAGQEEE4Q4IhgAzilBDBECAaQYE8wQIIAUCAADFVHIAUAsEEQJZIABQjhEsECAAqMFIwA4whBQyAhBgAEAIMUANgIAY4AQShBhDGCCEMQUEGAIBwRAAiAPBHMEKKEAEAAACAhxQjAgPAGCImOcIZIYgpDkAjBAECLKACIUY0AQZAQhAhiFlJCGGSAEU8IoIIhQRhACCGCKAcEAFwIIIJAIBAhCCEACOAIEEYIQgQSQAACKDAAIGGIAEYAhAahggALgABFMHAGAEMAAbJAVSgChkBEAGEMAEIIIxbAhCgAgFHCMACIBAdIQSwgSxiIiDBCAAIAUAUAZQJhRgBIDABDIGALEcEIQZggTBAEEvBAgCKAUEEAoAAAwSglABKlAEUEAkKIhSxAgjghFgDGYCIIQIIAABACyQigAjCBGAGgIEAY4oJgwAgEClDEACAGY4cQIAZBBwgAAiAJEBUEaZYIoAhgTSgigjCNECCQIIsIAQwggAAiihFPAIqKQaIAQRgQUxBADhCTKIGCIAQogQZVQRDACABCEYBAAAYQAYJRBQCwDmGEAGAMUAUQAzwQSQgkBEADAEAMEQIgBAAwASgEBnPLGECsQAAIpYYgzIAgSBQMKaAaEAEMpoYAAAAkDlAFAkHOYAwAAYQAUAgAAgVDCGAIkIkYRBIgARACEABLAAQYkgAIA4AwjBCABmEHCUMEAAUIIBoAykBlDEQKAKSeQoBAxRwhEhBIBLBMOEECEkIgaoCwRxBBhkAGAAoMIJkAAos2TzhlilBLAASAsAIkBIgCQQhgACCCACCOAkgQ6IQAgFAilmDCACAG4EwwgoQQUjBFAAEQGAIKAJYYYjJhgjCCBAAEEAkGAAMAAgKAQRDACBABCOUQAgAo + + 866d4fc3 + 27a3b0f5b0af73daf0fbfe62410f40ce + 162fa75f3621bf0ebb53c649dd01419012945740 + 786432:dQlcqW4q03P92YPsY3Kw6mdcutJb7USKPAldww7dQaFIZrws4B4SuBUCrS:dy3PsYDJ5/bYtPA31JQTZcsZJUCrS + + + + diff --git a/CICMMetadata/samples/multiple_floppies.xml b/CICMMetadata/samples/multiple_floppies.xml new file mode 100644 index 000000000..6f56710fd --- /dev/null +++ b/CICMMetadata/samples/multiple_floppies.xml @@ -0,0 +1,198 @@ + + + id Software + DOOM + 1.2 + Retail + 1994-02-17 + + doom + + + Games + + + First-person shooter + + + eng + + + i386 + + + ia32 + + + Doom v1.2 (1994)(id Software)(Disk 1 of 4).dsk + 1474560 + + 0x367d + 0x749f9b21 + 2729a2775d700d062f0da7ed2b14fc08 + 117637a9e42b59f75ce6b7e17be21370c3ca4ee1 + 24576:vfEFUAvpAvRlGnnyz+7lB1ODidGpZIY53x/9jO6J1sSSLNS87Q8LpeOIU8MeF79G:vfyOvwB1FGnIY5hxNWSHt8LLd8B7MaO + + + 1 + 4 + + 512 + 512 + 2880 + + 2 + 80 + 18 + + 93.7 + 90.0 + 3.3 + + + + 1 + 0 + 2879 + + + FAT12 + 512 + 2880 + false + false + + + + + + + Doom v1.2 (1994)(id Software)(Disk 2 of 4).dsk + 1474560 + + 0x594d + 0x13a68229 + ee087c084194ecd7f0acd2fec259f700 + 5c5b647d42d1b89d9199c6529486f1d52baacf57 + 24576:OPCNu5fOvENtXe/WmeVGeRTsAmExgydvKmaGhr1GYwGAjdCEQQY0kan:OPIuVHNl84PTDRKmNhUYtAjdCzQdkY + + + 2 + 4 + + 512 + 512 + 2880 + + 2 + 80 + 18 + + 93.7 + 90.0 + 3.3 + + + + 1 + 0 + 2879 + + + FAT12 + 512 + 2880 + false + false + + + + + + + Doom v1.2 (1994)(id Software)(Disk 3 of 4).dsk + 1474560 + + 0x124f + 0x70f8d3a0 + 4d5e5f40b12b485d180012fea59b2ba7 + 3fde0fbd3a33c9a5f8ec7cb9fc570bd1ee5adc36 + 24576:CHH7fNNK2sBYoNPjhkz96eEpE3GRjrgtmbNcc9tYLB590THjl1:CHH7fjK/BY8kzYeEptHg8NccI6/ + + + 3 + 4 + + 512 + 512 + 2880 + + 2 + 80 + 18 + + 93.7 + 90.0 + 3.3 + + + + 1 + 0 + 2879 + + + FAT12 + 512 + 2880 + false + false + + + + + + + Doom v1.2 (1994)(id Software)(Disk 4 of 4).dsk + 1474560 + + 0xe123 + 0x43f9330e + 5757c3329058db08f8ecd6108520be83 + 845707cb49faf201e057a19cbb8911b00fe0ea29 + 24576:DlhsgMwAmM1+mK62iQYVJ2K0BxVyaWRnjakQ:3CfaiQYP2VBxVCRnjaH + + + 4 + 4 + + 512 + 512 + 2880 + + 2 + 80 + 18 + + 93.7 + 90.0 + 3.3 + + + + 1 + 0 + 2879 + + + FAT12 + 512 + 2880 + false + false + + + + + + diff --git a/CICMMetadata/samples/pcirom.xml b/CICMMetadata/samples/pcirom.xml new file mode 100644 index 000000000..5b94d5592 --- /dev/null +++ b/CICMMetadata/samples/pcirom.xml @@ -0,0 +1,42 @@ + + + Adaptec + AHA-2940U2/U2W + + ia32 + + + 36869 + 16 + + aha2940u2.conf.bin + 256 + + 5f9b59691890feb957c01340e7bef4ad + 940ff2632bec7fa4274c256f2128d41069c414b7 + 458efd04ee7d5b8cd90a269b568c59181b51e770cc8aa255580cdeefb2436462 + b3f3520aaef141096eedd1316c8fabae8c9ce8728e8f9514 + d87fca5176f174e6ce5b4e303b595e41ae561e51ad332b838375394d66777dfe402e403acd4d071279693b24af5e55c25cfd6944b34a9bb229fa854d849ecbb8 + + + + aha2940u2.rom + 40960 + + 0x49eee01b + 0xb943 + 0x041bd908 + 0x3ee7cc130a1c280d + e86d20cac3727a0ebaf901eeef1a283a + 064b2b8050296caa535aa08de35d051e9e3fb6c7 + 9c2f1b6c07a00c16e35c82ee79050a459568f645 + 150366229d7bf649646f432bae95b31dc2ef51d23d43c2b5cac990aaa9b389e4 + 8e87bc09e451a69cc065cacc9a22d4f52df665f8229810d8cebeb50b505a2b2a6ea55cf282454ba7b53da15b0a2c4d73 + 2328d06b688925c5807dec9b958e270ed90d6117a755aee74d2f8d688159e94f39ed4d38e58bd02c7f81a3254fea0b011ff2f9bf7a846597728803d02c9e5e14 + 768:k9kvYRjE4p9FmqPG8A/dBBHMRkxOZkw73R7Ph86W35zD:k9kgOc9N2DHy8W998t + + Adaptec AHA-2940U2B SCSI BIOS v2.20.0 + PLCC + + + diff --git a/CICMMetadata/samples/pspumd.xml b/CICMMetadata/samples/pspumd.xml new file mode 100644 index 000000000..5a35c82c0 --- /dev/null +++ b/CICMMetadata/samples/pspumd.xml @@ -0,0 +1,263 @@ + + + EA LA + EA Games + Medal of Honor Heroes™ 2 + 1.00 + Retail + 2007-11-30 + + 5030934059299 + + DWX05805828D + ULES-00956 + + Games + + + First-person shooter + + + deu + fra + ita + spa + + + PlayStation Portable System Software + + + psp + + + + PlayStation Portable System Software + 3.51 + + + + spa + 22 + 84x170 + + manual_es.pdf + + 5ac6e3c1 + 8fb25698d2ce5f8d413bc92282d18720 + 70f4c9bfb092c5bb5875a73ebe47d762bee3ac10 + 5e022c7dfd12b54d1aa9ce98ea10f7dd81b5b1ec001ac49ad567a5d8d456a66f + 393216:muQhmo9jxgpVM0fwLGviZjylkxf0eZw4CSf4rlzpEA6hm:muOjZ6AGWyla0iGNr0Y + + + Natalia Portillo + Epson + Perfection 2400 + xxxxxxxxxxxxxxxxxx + Image Capture.app + 6.3 (502.1) + + + Natalia Portillo + ScanTailor + 0.9.11.1 + + + Natalia Portillo + Adobe Acrobat + 11.0.3 + spa + + + + + Medal of Honor Heroes 2 (Europe) (De,Es,Fr,It).iso + 1226768384 + + -1 + + + 8f47eb95 + 1417 + a7c1c1bc + 36ded46fce50efd2 + 7c472f83140e3af1a2fcdcdbadec850a + d9cf3cb3a2dea71ef8168797dc64e19b665c41d3 + 261898a262cdc8652e8d2c0e978e72c1c34a26fa + e6260e593c986e7c914b1588ab842e683170a7efb2b04cca5b08bcdac5595427 + c6b5acb50e5edd85e8615495b37d1f7abf754c41b6c6f45f3c082cbe6b01bb20eb5881d7cb36f5272ba6c58764aa6e82 + 5e9e2e8400d73ed5dd42253a0059a0bfe4dd0b451c9a757cd48818c87adacb1ca6698ae5a3cf93c72a16164fef4b6b35f60116b01d6dda83824a80372857868a + 12582912:kL8uYHoKqsJhjI6kejtUDRJWJCJiJ3JmJ+JwJDrjr1JdJnJhJ8rqyrwrqLrhrcPG:GVYIVQ1IWQ + + A0100878064-A911 16 + IFPI L556 Sony DADC + A2 + A0100878064-B911 17 + IFPI L557 Sony DADC + A1 + UMD + DL + 1 + 1 + MagicGate + + 60 + 32 + 64 + + + PSP + + + cover + + cover_es.png + + 864d127f + 5edb007ebc612bde8ed770a119863b22 + a98cb55d1c241a02bbaa6b621524276898821b72 + 67079e60209d30f0b6fa47bd8c786a020fda98f9a6b95ddeeaaf7f6aa665baa7 + 786432:JRB18CIZlzYWQWcj2qnzKFZXSx9VGh1DoWDaL8hII9Z16r6:PB18CIZtYWkjfz1xWmwQ8hIq2r6 + + + Natalia Portillo + Epson + Perfection 2400 + xxxxxxxxxxxxxxxxxx + Image Capture.app + 6.3 (502.1) + + + Natalia Portillo + Preview.app + 7.0 (826) + + + + + + + + label + + disc_label.png + + 4581778a + 0ef2c3333f773fe0578b9f2688813969 + 3721908aa68fcc0b417843508e08e4c4bffba47e + 6defc6c15d16b85d4a03287e64f07c42fb99afe028eac45d8a2d56f1da19c329 + 98304:OuOsmvSE/00ZxNSnbUGZASJw84/jWOrpuu9HOTy79DtaMr/wVeh:OuOsmvPxN6UAJ4rWOg0uToDtfmeh + + + Natalia Portillo + Epson + Perfection 2400 + xxxxxxxxxxxxxxxxxx + Image Capture.app + 6.3 (502.1) + + + Natalia Portillo + Preview.app + 7.0 (826) + + + + + data + + disc_data.png + + a84cafe4 + a24a06ef4f45e0ea7d89508b616fb5fa + 13e988df0bbff40666fd902c3e26454973df6ea9 + 805230c3037f342b18c9a9b0eaad35a216582dc71607b599c7a58cb7e83458ac + 49152:++RUFqSn6d20+rI9W+wIqUen2IHrwCINYD+CGS4rFM88UlVenKCCMGB4gm6A+Gp2:+g26y4boqCgAT4rFMElsnKhhzA+Yri + + + Natalia Portillo + Epson + Perfection 2400 + xxxxxxxxxxxxxxxxxx + Image Capture.app + 6.3 (502.1) + + + Natalia Portillo + Preview.app + 7.0 (826) + + + + + + Medal of Honor Heroes 2 (Europe) (De,Es,Fr,It).iso + 1226768384 + + 1 + 1 + + 0 + 599007 + data + 2048 + + 8f47eb95 + 1417 + a7c1c1bc + 36ded46fce50efd2 + 7c472f83140e3af1a2fcdcdbadec850a + d9cf3cb3a2dea71ef8168797dc64e19b665c41d3 + 261898a262cdc8652e8d2c0e978e72c1c34a26fa + e6260e593c986e7c914b1588ab842e683170a7efb2b04cca5b08bcdac5595427 + c6b5acb50e5edd85e8615495b37d1f7abf754c41b6c6f45f3c082cbe6b01bb20eb5881d7cb36f5272ba6c58764aa6e82 + 5e9e2e8400d73ed5dd42253a0059a0bfe4dd0b451c9a757cd48818c87adacb1ca6698ae5a3cf93c72a16164fef4b6b35f60116b01d6dda83824a80372857868a + 12582912:kL8uYHoKqsJhjI6kejtUDRJWJCJiJ3JmJ+JwJDrjr1JdJnJhJ8rqyrwrqLrhrcPG:GVYIVQ1IWQ + + + + 1 + 0 + 599007 + + + ISO9660 + 2007/10/11 20:26:37 + 2048 + 599008 + 550 + false + + MOH + 0 + False + PSP GAME + MOH + ELECTRONIC ARTS + ELECTRONIC ARTS + PSP GAME + + + + + + + + Sony + PSP3004 + 6.60 + xx-xxxxxxxx-xxxxxxx-PSP3004 + + + 0 + 599007 + + + + PlayStation Portable System Software + CFW 6.60 + PlayStation Portable System Software + + + + +