2025-11-19 15:15:58 +00:00
|
|
|
// /***************************************************************************
|
|
|
|
|
// Aaru Data Preservation Suite
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// Filename : DeviceViewModel.cs
|
|
|
|
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
|
|
|
|
//
|
|
|
|
|
// Component : GUI view models.
|
|
|
|
|
//
|
|
|
|
|
// --[ Description ] ----------------------------------------------------------
|
|
|
|
|
//
|
|
|
|
|
// View model for device.
|
|
|
|
|
//
|
|
|
|
|
// --[ 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 <http://www.gnu.org/licenses/>.
|
|
|
|
|
//
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
// Copyright © 2011-2025 Natalia Portillo
|
|
|
|
|
// ****************************************************************************/
|
|
|
|
|
|
2025-11-19 18:07:32 +00:00
|
|
|
using System;
|
2025-11-19 18:40:00 +00:00
|
|
|
using System.IO;
|
2025-11-19 19:56:01 +00:00
|
|
|
using System.Text;
|
2025-11-19 15:15:58 +00:00
|
|
|
using System.Threading.Tasks;
|
2025-11-19 18:07:32 +00:00
|
|
|
using System.Windows.Input;
|
2025-11-19 15:15:58 +00:00
|
|
|
using Aaru.CommonTypes.Enums;
|
2025-11-19 19:56:01 +00:00
|
|
|
using Aaru.CommonTypes.Structs.Devices.SCSI;
|
2025-11-19 15:15:58 +00:00
|
|
|
using Aaru.Core;
|
2025-11-19 18:07:32 +00:00
|
|
|
using Aaru.Decoders.SCSI.SSC;
|
2025-11-19 15:15:58 +00:00
|
|
|
using Aaru.Devices;
|
2025-11-19 18:07:32 +00:00
|
|
|
using Aaru.Gui.ViewModels.Tabs;
|
|
|
|
|
using Aaru.Gui.Views.Tabs;
|
2025-11-19 15:15:58 +00:00
|
|
|
using Aaru.Gui.Views.Windows;
|
|
|
|
|
using Aaru.Localization;
|
|
|
|
|
using Aaru.Logging;
|
2025-11-19 19:56:01 +00:00
|
|
|
using Avalonia.Media;
|
|
|
|
|
using Avalonia.Media.Imaging;
|
|
|
|
|
using Avalonia.Platform;
|
2025-11-19 18:40:00 +00:00
|
|
|
using Avalonia.Platform.Storage;
|
2025-11-19 19:56:01 +00:00
|
|
|
using Avalonia.Svg;
|
2025-11-19 15:15:58 +00:00
|
|
|
using Avalonia.Threading;
|
|
|
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
2025-11-19 18:40:00 +00:00
|
|
|
using CommunityToolkit.Mvvm.Input;
|
2025-11-19 15:15:58 +00:00
|
|
|
using Humanizer;
|
2025-11-19 19:56:01 +00:00
|
|
|
using Humanizer.Bytes;
|
2025-11-19 18:07:32 +00:00
|
|
|
using Humanizer.Localisation;
|
2025-11-19 15:15:58 +00:00
|
|
|
using MsBox.Avalonia;
|
|
|
|
|
using MsBox.Avalonia.Base;
|
|
|
|
|
using MsBox.Avalonia.Enums;
|
2025-11-19 18:40:00 +00:00
|
|
|
using DeviceInfo = Aaru.Core.Devices.Info.DeviceInfo;
|
2025-11-19 19:56:01 +00:00
|
|
|
using ScsiInfo = Aaru.Core.Media.Info.ScsiInfo;
|
2025-11-19 15:15:58 +00:00
|
|
|
|
|
|
|
|
namespace Aaru.Gui.ViewModels.Windows;
|
|
|
|
|
|
|
|
|
|
public partial class DeviceViewModel : ViewModelBase
|
|
|
|
|
{
|
|
|
|
|
readonly DeviceView _window;
|
|
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
AtaInfo _ataInfo;
|
2025-11-19 15:15:58 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _blockLimits;
|
2025-11-19 15:15:58 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _blockSizeGranularity;
|
2025-11-19 15:15:58 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 19:56:01 +00:00
|
|
|
BlurayInfo _blurayInfo;
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
CompactDiscInfo _compactDiscInfo;
|
|
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _densities;
|
|
|
|
|
Device _dev;
|
2025-11-19 15:15:58 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _devicePath;
|
2025-11-19 15:15:58 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _deviceType;
|
2025-11-19 15:15:58 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 19:56:01 +00:00
|
|
|
DvdInfo _dvdInfo;
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
DvdWritableInfo _dvdWritableInfo;
|
|
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _firewireGuid;
|
2025-11-19 15:15:58 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _firewireManufacturer;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _firewireModel;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _firewireModelId;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _firewireVendorId;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _firewireVisible;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _kreon;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _kreonChallengeResponse;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _kreonChallengeResponse360;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _kreonDecryptSs;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _kreonDecryptSs360;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _kreonErrorSkipping;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _kreonLock;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _kreonWxripperUnlock;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _kreonWxripperUnlock360;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _kreonXtremeUnlock;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _kreonXtremeUnlock360;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _manufacturer;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _maxBlockSize;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 19:56:01 +00:00
|
|
|
bool _mediaHasInformation;
|
|
|
|
|
ScsiInfo _mediaInfo;
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
bool _mediaIsInserted;
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
IImage _mediaLogo;
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
string _mediaSerial;
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
string _mediaSize;
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
string _mediaType;
|
|
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _mediumDensity;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _mediumTypes;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _minBlockSize;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 19:56:01 +00:00
|
|
|
bool _mmcVisible;
|
|
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _model;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
PcmciaInfo _pcmciaInfo;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorBitSetting;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorBitSettingDl;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _plextorCdReadTime;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _plextorCdWriteTime;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _plextorDiscs;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorDvd;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorDvdPlusWriteTest;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _plextorDvdReadTime;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorDvdTimesVisible;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _plextorDvdWriteTime;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorEepromVisible;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorGigaRec;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorHidesRecordables;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorHidesSessions;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorHiding;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorPoweRec;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorPoweRecEnabled;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _plextorPoweRecLast;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorPoweRecLastVisible;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _plextorPoweRecMax;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorPoweRecMaxVisible;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
|
|
|
|
string _plextorPoweRecRecommended;
|
|
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorPoweRecRecommendedVisible;
|
|
|
|
|
[ObservableProperty]
|
2025-11-19 18:07:32 +00:00
|
|
|
string _plextorPoweRecSelected;
|
|
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorPoweRecSelectedVisible;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorSecuRec;
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
bool _plextorSilentMode;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
|
|
|
|
string _plextorSilentModeAccessTime;
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
string _plextorSilentModeCdReadSpeedLimit;
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
string _plextorSilentModeCdWriteSpeedLimit;
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
string _plextorSilentModeDvdReadSpeedLimit;
|
|
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorSilentModeDvdReadSpeedLimitVisible;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorSilentModeEnabled;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorSpeedEnabled;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorSpeedRead;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorVariRec;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorVariRecDvd;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _plextorVisible;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _removableChecked;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _revision;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 19:56:01 +00:00
|
|
|
bool _saveGetConfigurationVisible;
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
bool _saveReadCapacity16Visible;
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
bool _saveReadCapacityVisible;
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
bool _saveReadMediaSerialVisible;
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
bool _saveRecognizedFormatLayersVisible;
|
|
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _saveUsbDescriptorsEnabled;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 19:56:01 +00:00
|
|
|
bool _saveWriteProtectionStatusVisible;
|
|
|
|
|
[ObservableProperty]
|
|
|
|
|
Views.Tabs.ScsiInfo _scsiInfo;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _scsiType;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
SdMmcInfo _sdMmcInfo;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _serial;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _ssc;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _statusMessage;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 19:56:01 +00:00
|
|
|
bool _statusMessageVisible;
|
|
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _usbConnected;
|
|
|
|
|
byte[] _usbDescriptors;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _usbManufacturer;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _usbProduct;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _usbProductId;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _usbSerial;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
string _usbVendorId;
|
2025-11-19 18:07:32 +00:00
|
|
|
[ObservableProperty]
|
2025-11-19 18:40:00 +00:00
|
|
|
bool _usbVisible;
|
2025-11-19 19:56:01 +00:00
|
|
|
[ObservableProperty]
|
|
|
|
|
XboxInfo _xboxInfo;
|
2025-11-19 15:15:58 +00:00
|
|
|
|
|
|
|
|
public DeviceViewModel(DeviceView window, string devicePath)
|
|
|
|
|
{
|
|
|
|
|
_window = window;
|
|
|
|
|
DevicePath = devicePath;
|
2025-11-19 18:40:00 +00:00
|
|
|
|
2025-11-19 19:56:01 +00:00
|
|
|
SaveUsbDescriptorsCommand = new AsyncRelayCommand(SaveUsbDescriptorsAsync);
|
|
|
|
|
SaveReadMediaSerialCommand = new AsyncRelayCommand(SaveReadMediaSerialAsync);
|
|
|
|
|
SaveReadCapacityCommand = new AsyncRelayCommand(SaveReadCapacityAsync);
|
|
|
|
|
SaveReadCapacity16Command = new AsyncRelayCommand(SaveReadCapacity16Async);
|
|
|
|
|
SaveGetConfigurationCommand = new AsyncRelayCommand(SaveGetConfigurationAsync);
|
|
|
|
|
SaveRecognizedFormatLayersCommand = new AsyncRelayCommand(SaveRecognizedFormatLayersAsync);
|
|
|
|
|
SaveWriteProtectionStatusCommand = new AsyncRelayCommand(SaveWriteProtectionStatusAsync);
|
|
|
|
|
DumpCommand = new AsyncRelayCommand(DumpAsync);
|
|
|
|
|
ScanCommand = new AsyncRelayCommand(ScanAsync);
|
2025-11-19 15:15:58 +00:00
|
|
|
}
|
|
|
|
|
|
2025-11-19 19:56:01 +00:00
|
|
|
public ICommand SaveUsbDescriptorsCommand { get; }
|
|
|
|
|
public ICommand SaveReadMediaSerialCommand { get; }
|
|
|
|
|
public ICommand SaveReadCapacityCommand { get; }
|
|
|
|
|
public ICommand SaveReadCapacity16Command { get; }
|
|
|
|
|
public ICommand SaveGetConfigurationCommand { get; }
|
|
|
|
|
public ICommand SaveRecognizedFormatLayersCommand { get; }
|
|
|
|
|
public ICommand SaveWriteProtectionStatusCommand { get; }
|
|
|
|
|
public ICommand DumpCommand { get; }
|
|
|
|
|
public ICommand ScanCommand { get; }
|
|
|
|
|
|
|
|
|
|
Task SaveReadMediaSerialAsync() => SaveElementAsync(_mediaInfo.MediaSerialNumber);
|
|
|
|
|
|
|
|
|
|
Task SaveReadCapacityAsync() => SaveElementAsync(_mediaInfo.ReadCapacity);
|
|
|
|
|
|
|
|
|
|
Task SaveReadCapacity16Async() => SaveElementAsync(_mediaInfo.ReadCapacity16);
|
|
|
|
|
|
|
|
|
|
Task SaveGetConfigurationAsync() => SaveElementAsync(_mediaInfo.MmcConfiguration);
|
|
|
|
|
|
|
|
|
|
Task SaveRecognizedFormatLayersAsync() => SaveElementAsync(_mediaInfo.RecognizedFormatLayers);
|
|
|
|
|
|
|
|
|
|
Task SaveWriteProtectionStatusAsync() => SaveElementAsync(_mediaInfo.WriteProtectionStatus);
|
|
|
|
|
|
|
|
|
|
async Task SaveElementAsync(byte[] data)
|
|
|
|
|
{
|
|
|
|
|
IStorageFile result = await _window.StorageProvider.SaveFilePickerAsync(new FilePickerSaveOptions
|
|
|
|
|
{
|
|
|
|
|
FileTypeChoices = [FilePickerFileTypes.Binary]
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if(result is null) return;
|
|
|
|
|
|
|
|
|
|
var saveFs = new FileStream(result.Path.AbsolutePath, FileMode.Create);
|
|
|
|
|
await saveFs.WriteAsync(data, 0, data.Length);
|
|
|
|
|
|
|
|
|
|
saveFs.Close();
|
|
|
|
|
}
|
2025-11-19 18:40:00 +00:00
|
|
|
|
2025-11-19 15:15:58 +00:00
|
|
|
public void LoadData()
|
|
|
|
|
{
|
|
|
|
|
_ = Task.Run(Worker);
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-19 18:40:00 +00:00
|
|
|
async Task SaveUsbDescriptorsAsync()
|
|
|
|
|
{
|
|
|
|
|
IStorageFile result = await _window.StorageProvider.SaveFilePickerAsync(new FilePickerSaveOptions
|
|
|
|
|
{
|
|
|
|
|
FileTypeChoices = [FilePickerFileTypes.Binary]
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if(result is null) return;
|
|
|
|
|
|
|
|
|
|
var saveFs = new FileStream(result.Path.AbsolutePath, FileMode.Create);
|
|
|
|
|
await saveFs.WriteAsync(_usbDescriptors, 0, _usbDescriptors.Length);
|
|
|
|
|
|
|
|
|
|
saveFs.Close();
|
|
|
|
|
}
|
2025-11-19 18:07:32 +00:00
|
|
|
|
2025-11-19 15:15:58 +00:00
|
|
|
void Worker()
|
|
|
|
|
{
|
2025-11-19 19:56:01 +00:00
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
|
|
|
|
StatusMessageVisible = true;
|
|
|
|
|
StatusMessage = "Opening device...";
|
|
|
|
|
});
|
2025-11-19 15:15:58 +00:00
|
|
|
|
|
|
|
|
var dev = Device.Create(DevicePath, out ErrorNumber devErrno);
|
|
|
|
|
|
|
|
|
|
if(dev is null)
|
|
|
|
|
{
|
|
|
|
|
AaruLogging.Error(string.Format(UI.Could_not_open_device_error_0, devErrno));
|
|
|
|
|
|
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
|
|
|
|
IMsBox<ButtonResult> msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
|
|
|
|
|
string.Format(UI.Could_not_open_device_error_0, devErrno),
|
|
|
|
|
ButtonEnum.Ok,
|
|
|
|
|
Icon.Error);
|
|
|
|
|
|
|
|
|
|
_ = msbox.ShowAsync();
|
|
|
|
|
|
|
|
|
|
_window.Close();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(dev.Error)
|
|
|
|
|
{
|
|
|
|
|
AaruLogging.Error(Error.Print(dev.LastError));
|
|
|
|
|
|
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
|
|
|
|
IMsBox<ButtonResult> msbox = MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
|
|
|
|
|
Error.Print(dev.LastError),
|
|
|
|
|
ButtonEnum.Ok,
|
|
|
|
|
Icon.Error);
|
|
|
|
|
|
|
|
|
|
_ = msbox.ShowAsync();
|
|
|
|
|
|
|
|
|
|
_window.Close();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
|
|
|
|
DeviceType = $"[rosybrown]{dev.Type.Humanize()}[/]";
|
|
|
|
|
Manufacturer = (dev.Manufacturer != null ? $"[blue]{dev.Manufacturer}[/]" : null)!;
|
|
|
|
|
Model = (dev.Model != null ? $"[purple]{dev.Model}[/]" : null)!;
|
|
|
|
|
Revision = (dev.FirmwareRevision != null ? $"[teal]{dev.FirmwareRevision}[/]" : null)!;
|
|
|
|
|
Serial = (dev.Serial != null ? $"[fuchsia]{dev.Serial}[/]" : null)!;
|
|
|
|
|
ScsiType = $"[orange]{dev.ScsiType.Humanize()}[/]";
|
|
|
|
|
RemovableChecked = dev.IsRemovable;
|
|
|
|
|
UsbConnected = dev.IsUsb;
|
|
|
|
|
StatusMessage = "Device opened successfully.";
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
_dev = dev;
|
2025-11-19 18:07:32 +00:00
|
|
|
|
|
|
|
|
Statistics.AddDevice(dev);
|
|
|
|
|
|
2025-11-19 19:56:01 +00:00
|
|
|
Dispatcher.UIThread.Invoke(() => StatusMessage = "Querying device information...");
|
2025-11-19 18:07:32 +00:00
|
|
|
|
2025-11-19 18:40:00 +00:00
|
|
|
var devInfo = new DeviceInfo(dev);
|
2025-11-19 18:07:32 +00:00
|
|
|
|
2025-11-19 19:56:01 +00:00
|
|
|
Dispatcher.UIThread.Invoke(() => StatusMessage = "Device information queryied successfully...");
|
2025-11-19 18:07:32 +00:00
|
|
|
|
|
|
|
|
if(devInfo.IsUsb)
|
|
|
|
|
{
|
2025-11-19 18:40:00 +00:00
|
|
|
_usbDescriptors = devInfo.UsbDescriptors;
|
|
|
|
|
|
2025-11-19 18:07:32 +00:00
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
|
|
|
|
UsbVisible = true;
|
|
|
|
|
SaveUsbDescriptorsEnabled = devInfo.UsbDescriptors != null;
|
|
|
|
|
UsbVendorId = $"[cyan]{devInfo.UsbVendorId:X4}[/]";
|
|
|
|
|
UsbProductId = $"[cyan]{devInfo.UsbProductId:X4}[/]";
|
|
|
|
|
UsbManufacturer = $"[blue]{devInfo.UsbManufacturerString}[/]";
|
|
|
|
|
UsbProduct = $"[purple]{devInfo.UsbProductString}[/]";
|
|
|
|
|
UsbSerial = $"[fuchsia]{devInfo.UsbSerialString}[/]";
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(devInfo.IsFireWire)
|
|
|
|
|
{
|
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
|
|
|
|
FirewireVisible = true;
|
|
|
|
|
FirewireVendorId = $"[cyan]{devInfo.FireWireVendor:X4}[/]";
|
|
|
|
|
FirewireModelId = $"[cyan]{devInfo.FireWireModel:X4}[/]";
|
|
|
|
|
FirewireManufacturer = $"[blue]{devInfo.FireWireVendorName}[/]";
|
|
|
|
|
FirewireModel = $"[purple]{devInfo.FireWireModelName}[/]";
|
|
|
|
|
FirewireGuid = $"[fuchsia]{devInfo.FireWireGuid:X16}[/]";
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(devInfo.IsPcmcia)
|
|
|
|
|
{
|
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
|
|
|
|
PcmciaInfo = new PcmciaInfo
|
|
|
|
|
{
|
|
|
|
|
DataContext = new PcmciaInfoViewModel(devInfo.Cis, _window)
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(devInfo.AtaIdentify != null || devInfo.AtapiIdentify != null)
|
|
|
|
|
{
|
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
|
|
|
|
AtaInfo = new AtaInfo
|
|
|
|
|
{
|
|
|
|
|
DataContext = new AtaInfoViewModel(devInfo.AtaIdentify,
|
|
|
|
|
devInfo.AtapiIdentify,
|
|
|
|
|
devInfo.AtaMcptError,
|
|
|
|
|
_window)
|
|
|
|
|
};
|
2025-11-19 19:56:01 +00:00
|
|
|
|
|
|
|
|
MediaIsInserted = true;
|
2025-11-19 18:07:32 +00:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(devInfo.ScsiInquiryData != null)
|
|
|
|
|
{
|
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
2025-11-19 19:56:01 +00:00
|
|
|
ScsiInfo = new Views.Tabs.ScsiInfo
|
2025-11-19 18:07:32 +00:00
|
|
|
{
|
|
|
|
|
DataContext = new ScsiInfoViewModel(devInfo.ScsiInquiryData,
|
|
|
|
|
devInfo.ScsiInquiry,
|
|
|
|
|
devInfo.ScsiEvpdPages,
|
|
|
|
|
devInfo.ScsiMode,
|
|
|
|
|
devInfo.ScsiType,
|
|
|
|
|
devInfo.ScsiModeSense6,
|
|
|
|
|
devInfo.ScsiModeSense10,
|
|
|
|
|
devInfo.MmcConfiguration,
|
|
|
|
|
_window)
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if(devInfo.PlextorFeatures != null)
|
|
|
|
|
{
|
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
|
|
|
|
PlextorVisible = true;
|
|
|
|
|
|
|
|
|
|
if(devInfo.PlextorFeatures.Eeprom != null)
|
|
|
|
|
{
|
|
|
|
|
PlextorEepromVisible = true;
|
|
|
|
|
PlextorDiscs = $"{devInfo.PlextorFeatures.Discs}";
|
|
|
|
|
|
|
|
|
|
PlextorCdReadTime = devInfo.PlextorFeatures.CdReadTime.Seconds()
|
|
|
|
|
.Humanize(minUnit: TimeUnit.Second);
|
|
|
|
|
|
|
|
|
|
PlextorCdWriteTime = devInfo.PlextorFeatures.CdWriteTime.Seconds()
|
|
|
|
|
.Humanize(minUnit: TimeUnit.Second);
|
|
|
|
|
|
|
|
|
|
if(devInfo.PlextorFeatures.IsDvd)
|
|
|
|
|
{
|
|
|
|
|
PlextorDvdTimesVisible = true;
|
|
|
|
|
|
|
|
|
|
PlextorDvdReadTime = devInfo.PlextorFeatures.DvdReadTime.Seconds()
|
|
|
|
|
.Humanize(minUnit: TimeUnit.Second);
|
|
|
|
|
|
|
|
|
|
PlextorDvdWriteTime = devInfo.PlextorFeatures.DvdWriteTime.Seconds()
|
|
|
|
|
.Humanize(minUnit: TimeUnit.Second);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PlextorPoweRec = devInfo.PlextorFeatures.PoweRec;
|
|
|
|
|
|
|
|
|
|
if(devInfo.PlextorFeatures.PoweRec)
|
|
|
|
|
{
|
|
|
|
|
PlextorPoweRecEnabled = devInfo.PlextorFeatures.PoweRecEnabled;
|
|
|
|
|
|
|
|
|
|
if(devInfo.PlextorFeatures.PoweRecEnabled)
|
|
|
|
|
{
|
|
|
|
|
PlextorPoweRecEnabled = true;
|
|
|
|
|
|
|
|
|
|
if(devInfo.PlextorFeatures.PoweRecRecommendedSpeed > 0)
|
|
|
|
|
{
|
|
|
|
|
PlextorPoweRecRecommendedVisible = true;
|
|
|
|
|
|
|
|
|
|
PlextorPoweRecRecommended =
|
|
|
|
|
string.Format(UI._0_Kb_sec, devInfo.PlextorFeatures.PoweRecRecommendedSpeed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(devInfo.PlextorFeatures.PoweRecSelected > 0)
|
|
|
|
|
{
|
|
|
|
|
PlextorPoweRecSelectedVisible = true;
|
|
|
|
|
|
|
|
|
|
PlextorPoweRecSelected =
|
|
|
|
|
string.Format(UI._0_Kb_sec, devInfo.PlextorFeatures.PoweRecSelected);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(devInfo.PlextorFeatures.PoweRecMax > 0)
|
|
|
|
|
{
|
|
|
|
|
PlextorPoweRecMaxVisible = true;
|
|
|
|
|
PlextorPoweRecMax = string.Format(UI._0_Kb_sec, devInfo.PlextorFeatures.PoweRecMax);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(devInfo.PlextorFeatures.PoweRecLast > 0)
|
|
|
|
|
{
|
|
|
|
|
PlextorPoweRecLastVisible = true;
|
|
|
|
|
PlextorPoweRecLast = string.Format(UI._0_Kb_sec, devInfo.PlextorFeatures.PoweRecLast);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PlextorSilentMode = devInfo.PlextorFeatures.SilentMode;
|
|
|
|
|
|
|
|
|
|
if(devInfo.PlextorFeatures.SilentMode)
|
|
|
|
|
{
|
|
|
|
|
PlextorSilentModeEnabled = devInfo.PlextorFeatures.SilentModeEnabled;
|
|
|
|
|
|
|
|
|
|
if(devInfo.PlextorFeatures.SilentModeEnabled)
|
|
|
|
|
{
|
|
|
|
|
PlextorSilentModeAccessTime = devInfo.PlextorFeatures.AccessTimeLimit == 2
|
|
|
|
|
? Localization.Core.Access_time_is_slow
|
|
|
|
|
: Localization.Core.Access_time_is_fast;
|
|
|
|
|
|
|
|
|
|
PlextorSilentModeCdReadSpeedLimit =
|
|
|
|
|
devInfo.PlextorFeatures.CdReadSpeedLimit > 0
|
|
|
|
|
? $"{devInfo.PlextorFeatures.CdReadSpeedLimit}x"
|
|
|
|
|
: UI.unlimited_as_in_speed;
|
|
|
|
|
|
|
|
|
|
PlextorSilentModeCdWriteSpeedLimit =
|
|
|
|
|
devInfo.PlextorFeatures.CdWriteSpeedLimit > 0
|
|
|
|
|
? $"{devInfo.PlextorFeatures.CdReadSpeedLimit}x"
|
|
|
|
|
: UI.unlimited_as_in_speed;
|
|
|
|
|
|
|
|
|
|
if(devInfo.PlextorFeatures.IsDvd)
|
|
|
|
|
{
|
|
|
|
|
PlextorSilentModeDvdReadSpeedLimitVisible = true;
|
|
|
|
|
|
|
|
|
|
PlextorSilentModeDvdReadSpeedLimit =
|
|
|
|
|
devInfo.PlextorFeatures.DvdReadSpeedLimit > 0
|
|
|
|
|
? $"{devInfo.PlextorFeatures.DvdReadSpeedLimit}x"
|
|
|
|
|
: UI.unlimited_as_in_speed;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PlextorGigaRec = devInfo.PlextorFeatures.GigaRec;
|
|
|
|
|
PlextorSecuRec = devInfo.PlextorFeatures.SecuRec;
|
|
|
|
|
PlextorSpeedRead = devInfo.PlextorFeatures.SpeedRead;
|
|
|
|
|
|
|
|
|
|
if(devInfo.PlextorFeatures.SpeedRead)
|
|
|
|
|
PlextorSpeedEnabled = devInfo.PlextorFeatures.SpeedReadEnabled;
|
|
|
|
|
|
|
|
|
|
PlextorHiding = devInfo.PlextorFeatures.Hiding;
|
|
|
|
|
|
|
|
|
|
if(devInfo.PlextorFeatures.Hiding)
|
|
|
|
|
{
|
|
|
|
|
PlextorHidesRecordables = devInfo.PlextorFeatures.HidesRecordables;
|
|
|
|
|
PlextorHidesSessions = devInfo.PlextorFeatures.HidesSessions;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PlextorVariRec = devInfo.PlextorFeatures.VariRec;
|
|
|
|
|
|
2025-11-19 19:56:01 +00:00
|
|
|
if(!devInfo.PlextorFeatures.IsDvd) return;
|
|
|
|
|
|
|
|
|
|
PlextorVariRecDvd = devInfo.PlextorFeatures.VariRecDvd;
|
|
|
|
|
PlextorBitSetting = devInfo.PlextorFeatures.BitSetting;
|
|
|
|
|
PlextorBitSettingDl = devInfo.PlextorFeatures.BitSettingDl;
|
|
|
|
|
PlextorDvdPlusWriteTest = devInfo.PlextorFeatures.DvdPlusWriteTest;
|
2025-11-19 18:07:32 +00:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(devInfo.ScsiInquiry?.KreonPresent == true)
|
|
|
|
|
{
|
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
|
|
|
|
Kreon = true;
|
|
|
|
|
KreonChallengeResponse = devInfo.KreonFeatures.HasFlag(KreonFeatures.ChallengeResponse);
|
|
|
|
|
KreonDecryptSs = devInfo.KreonFeatures.HasFlag(KreonFeatures.DecryptSs);
|
|
|
|
|
KreonXtremeUnlock = devInfo.KreonFeatures.HasFlag(KreonFeatures.XtremeUnlock);
|
|
|
|
|
KreonWxripperUnlock = devInfo.KreonFeatures.HasFlag(KreonFeatures.WxripperUnlock);
|
|
|
|
|
|
|
|
|
|
KreonChallengeResponse360 = devInfo.KreonFeatures.HasFlag(KreonFeatures.ChallengeResponse360);
|
|
|
|
|
|
|
|
|
|
KreonDecryptSs360 = devInfo.KreonFeatures.HasFlag(KreonFeatures.DecryptSs360);
|
|
|
|
|
KreonXtremeUnlock360 = devInfo.KreonFeatures.HasFlag(KreonFeatures.XtremeUnlock360);
|
|
|
|
|
KreonWxripperUnlock360 = devInfo.KreonFeatures.HasFlag(KreonFeatures.WxripperUnlock360);
|
|
|
|
|
KreonLock = devInfo.KreonFeatures.HasFlag(KreonFeatures.Lock);
|
|
|
|
|
KreonErrorSkipping = devInfo.KreonFeatures.HasFlag(KreonFeatures.ErrorSkipping);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(devInfo.BlockLimits != null)
|
|
|
|
|
{
|
|
|
|
|
BlockLimits.BlockLimitsData? blockLimits = Decoders.SCSI.SSC.BlockLimits.Decode(devInfo.BlockLimits);
|
|
|
|
|
|
|
|
|
|
if(blockLimits.HasValue)
|
|
|
|
|
{
|
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
|
|
|
|
Ssc = true;
|
|
|
|
|
|
|
|
|
|
if(blockLimits.Value.minBlockLen == blockLimits.Value.maxBlockLen)
|
|
|
|
|
{
|
|
|
|
|
MinBlockSize = string.Format(Localization.Core.Device_block_size_is_fixed_at_0_bytes,
|
|
|
|
|
blockLimits.Value.minBlockLen);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
MaxBlockSize = blockLimits.Value.maxBlockLen > 0
|
|
|
|
|
? string.Format(Localization.Core.Device_maximum_block_size_is_0_bytes,
|
|
|
|
|
blockLimits.Value.maxBlockLen)
|
|
|
|
|
: Localization.Core.Device_does_not_specify_a_maximum_block_size;
|
|
|
|
|
|
|
|
|
|
MinBlockSize = string.Format(Localization.Core.Device_minimum_block_size_is_0_bytes,
|
|
|
|
|
blockLimits.Value.minBlockLen);
|
|
|
|
|
|
|
|
|
|
if(blockLimits.Value.granularity > 0)
|
|
|
|
|
{
|
|
|
|
|
BlockSizeGranularity =
|
|
|
|
|
string.Format(Localization.Core
|
|
|
|
|
.Device_needs_a_block_size_granularity_of_pow_0_1_bytes,
|
|
|
|
|
blockLimits.Value.granularity,
|
|
|
|
|
Math.Pow(2, blockLimits.Value.granularity));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(devInfo.DensitySupport != null)
|
|
|
|
|
{
|
|
|
|
|
if(devInfo.DensitySupportHeader.HasValue)
|
2025-11-19 18:40:00 +00:00
|
|
|
{
|
2025-11-19 18:07:32 +00:00
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
2025-11-19 18:40:00 +00:00
|
|
|
Densities =
|
|
|
|
|
DensitySupport.PrettifyDensity(devInfo.DensitySupportHeader);
|
2025-11-19 18:07:32 +00:00
|
|
|
});
|
2025-11-19 18:40:00 +00:00
|
|
|
}
|
2025-11-19 18:07:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(devInfo.MediumDensitySupport != null)
|
|
|
|
|
{
|
|
|
|
|
if(devInfo.MediaTypeSupportHeader.HasValue)
|
2025-11-19 18:40:00 +00:00
|
|
|
{
|
2025-11-19 18:07:32 +00:00
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
2025-11-19 18:40:00 +00:00
|
|
|
MediumTypes =
|
|
|
|
|
DensitySupport
|
|
|
|
|
.PrettifyMediumType(devInfo.MediaTypeSupportHeader);
|
2025-11-19 18:07:32 +00:00
|
|
|
});
|
2025-11-19 18:40:00 +00:00
|
|
|
}
|
2025-11-19 18:07:32 +00:00
|
|
|
|
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
2025-11-19 18:40:00 +00:00
|
|
|
MediumDensity =
|
|
|
|
|
DensitySupport.PrettifyMediumType(devInfo.MediumDensitySupport);
|
2025-11-19 18:07:32 +00:00
|
|
|
});
|
|
|
|
|
}
|
2025-11-19 19:56:01 +00:00
|
|
|
|
|
|
|
|
Dispatcher.UIThread.Invoke(() => StatusMessage = "Querying media information...");
|
|
|
|
|
|
|
|
|
|
var mediaInfo = new ScsiInfo(dev);
|
|
|
|
|
|
|
|
|
|
if(!mediaInfo.MediaInserted)
|
|
|
|
|
{
|
|
|
|
|
Dispatcher.UIThread.Invoke(() => StatusMessageVisible = false);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MediaIsInserted = true;
|
|
|
|
|
|
|
|
|
|
var genericHddIcon =
|
|
|
|
|
new Bitmap(AssetLoader.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/drive-harddisk.png")));
|
|
|
|
|
|
|
|
|
|
var genericOpticalIcon =
|
|
|
|
|
new Bitmap(AssetLoader.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/drive-optical.png")));
|
|
|
|
|
|
|
|
|
|
var genericFolderIcon =
|
|
|
|
|
new Bitmap(AssetLoader
|
|
|
|
|
.Open(new Uri("avares://Aaru.Gui/Assets/Icons/oxygen/32x32/inode-directory.png")));
|
|
|
|
|
|
|
|
|
|
var mediaResource = new Uri($"avares://Aaru.Gui/Assets/Logos/Media/{mediaInfo.MediaType}.svg");
|
|
|
|
|
|
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
|
|
|
|
MediaLogo = AssetLoader.Exists(mediaResource)
|
|
|
|
|
? new SvgImage
|
|
|
|
|
{
|
|
|
|
|
Source = SvgSource.Load(AssetLoader.Open(mediaResource))
|
|
|
|
|
}
|
|
|
|
|
: dev.ScsiType == PeripheralDeviceTypes.DirectAccess
|
|
|
|
|
? genericHddIcon
|
|
|
|
|
: dev.ScsiType == PeripheralDeviceTypes.MultiMediaDevice
|
|
|
|
|
? genericOpticalIcon
|
|
|
|
|
: genericFolderIcon;
|
|
|
|
|
|
2025-11-19 20:25:09 +00:00
|
|
|
MediaType = mediaInfo.MediaType.Humanize();
|
2025-11-19 19:56:01 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if(mediaInfo.Blocks != 0 && mediaInfo.BlockSize != 0)
|
|
|
|
|
{
|
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
|
|
|
|
MediaSize =
|
|
|
|
|
string.Format(Localization.Core
|
|
|
|
|
.Media_has_0_blocks_of_1_bytes_each_for_a_total_of_2,
|
|
|
|
|
mediaInfo.Blocks,
|
|
|
|
|
mediaInfo.BlockSize,
|
|
|
|
|
ByteSize.FromBytes(mediaInfo.Blocks *
|
|
|
|
|
mediaInfo.BlockSize)
|
|
|
|
|
.ToString("0.000"));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(mediaInfo.MediaSerialNumber != null)
|
|
|
|
|
{
|
|
|
|
|
var sbSerial = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
for(var i = 4; i < mediaInfo.MediaSerialNumber.Length; i++)
|
|
|
|
|
sbSerial.Append($"{mediaInfo.MediaSerialNumber[i]:X2}");
|
|
|
|
|
|
|
|
|
|
Dispatcher.UIThread.Invoke(() => MediaSerial = sbSerial.ToString());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
|
|
|
|
MediaHasInformation = true;
|
|
|
|
|
|
|
|
|
|
SaveReadMediaSerialVisible = mediaInfo.MediaSerialNumber != null;
|
|
|
|
|
SaveReadCapacityVisible = mediaInfo.ReadCapacity != null;
|
|
|
|
|
SaveReadCapacity16Visible = mediaInfo.ReadCapacity16 != null;
|
|
|
|
|
|
|
|
|
|
SaveGetConfigurationVisible = mediaInfo.MmcConfiguration != null;
|
|
|
|
|
|
|
|
|
|
SaveRecognizedFormatLayersVisible = mediaInfo.RecognizedFormatLayers != null;
|
|
|
|
|
|
|
|
|
|
SaveWriteProtectionStatusVisible = mediaInfo.WriteProtectionStatus != null;
|
|
|
|
|
|
|
|
|
|
MmcVisible = SaveGetConfigurationVisible ||
|
|
|
|
|
SaveRecognizedFormatLayersVisible ||
|
|
|
|
|
SaveWriteProtectionStatusVisible;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
_mediaInfo = mediaInfo;
|
|
|
|
|
|
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
|
|
|
|
if(_mediaInfo.Toc != null ||
|
|
|
|
|
_mediaInfo.Atip != null ||
|
|
|
|
|
_mediaInfo.DiscInformation != null ||
|
|
|
|
|
_mediaInfo.Session != null ||
|
|
|
|
|
_mediaInfo.RawToc != null ||
|
|
|
|
|
_mediaInfo.Pma != null ||
|
|
|
|
|
_mediaInfo.CdTextLeadIn != null ||
|
|
|
|
|
_mediaInfo.DecodedToc != null ||
|
|
|
|
|
_mediaInfo.DecodedAtip != null ||
|
|
|
|
|
_mediaInfo.DecodedSession != null ||
|
|
|
|
|
_mediaInfo.FullToc != null ||
|
|
|
|
|
_mediaInfo.DecodedCdTextLeadIn != null ||
|
|
|
|
|
_mediaInfo.DecodedDiscInformation != null ||
|
|
|
|
|
_mediaInfo.Mcn != null ||
|
|
|
|
|
_mediaInfo.Isrcs != null)
|
|
|
|
|
{
|
|
|
|
|
CompactDiscInfo = new CompactDiscInfo
|
|
|
|
|
{
|
|
|
|
|
DataContext = new CompactDiscInfoViewModel(_mediaInfo.Toc,
|
|
|
|
|
_mediaInfo.Atip,
|
|
|
|
|
_mediaInfo.DiscInformation,
|
|
|
|
|
_mediaInfo.Session,
|
|
|
|
|
_mediaInfo.RawToc,
|
|
|
|
|
_mediaInfo.Pma,
|
|
|
|
|
_mediaInfo.CdTextLeadIn,
|
|
|
|
|
_mediaInfo.DecodedToc,
|
|
|
|
|
_mediaInfo.DecodedAtip,
|
|
|
|
|
_mediaInfo.DecodedSession,
|
|
|
|
|
_mediaInfo.FullToc,
|
|
|
|
|
_mediaInfo.DecodedCdTextLeadIn,
|
|
|
|
|
_mediaInfo.DecodedDiscInformation,
|
|
|
|
|
_mediaInfo.Mcn,
|
|
|
|
|
_mediaInfo.Isrcs,
|
|
|
|
|
_window)
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(_mediaInfo.DvdPfi != null ||
|
|
|
|
|
_mediaInfo.DvdDmi != null ||
|
|
|
|
|
_mediaInfo.DvdCmi != null ||
|
|
|
|
|
_mediaInfo.HddvdCopyrightInformation != null ||
|
|
|
|
|
_mediaInfo.DvdBca != null ||
|
|
|
|
|
_mediaInfo.DvdAacs != null ||
|
|
|
|
|
_mediaInfo.DecodedPfi != null)
|
|
|
|
|
{
|
|
|
|
|
DvdInfo = new DvdInfo
|
|
|
|
|
{
|
|
|
|
|
DataContext = new DvdInfoViewModel(_mediaInfo.DvdPfi,
|
|
|
|
|
_mediaInfo.DvdDmi,
|
|
|
|
|
_mediaInfo.DvdCmi,
|
|
|
|
|
_mediaInfo.HddvdCopyrightInformation,
|
|
|
|
|
_mediaInfo.DvdBca,
|
|
|
|
|
_mediaInfo.DvdAacs,
|
|
|
|
|
_mediaInfo.DecodedPfi,
|
|
|
|
|
_window)
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(_mediaInfo.XgdInfo != null ||
|
|
|
|
|
_mediaInfo.XboxSecuritySector != null ||
|
|
|
|
|
_mediaInfo.DecodedXboxSecuritySector != null)
|
|
|
|
|
{
|
|
|
|
|
XboxInfo = new XboxInfo
|
|
|
|
|
{
|
|
|
|
|
DataContext = new XboxInfoViewModel(_mediaInfo.XgdInfo,
|
|
|
|
|
_mediaInfo.DvdDmi,
|
|
|
|
|
_mediaInfo.XboxSecuritySector,
|
|
|
|
|
_mediaInfo.DecodedXboxSecuritySector,
|
|
|
|
|
_window)
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(_mediaInfo.DvdRamDds != null ||
|
|
|
|
|
_mediaInfo.DvdRamCartridgeStatus != null ||
|
|
|
|
|
_mediaInfo.DvdRamSpareArea != null ||
|
|
|
|
|
_mediaInfo.LastBorderOutRmd != null ||
|
|
|
|
|
_mediaInfo.DvdPreRecordedInfo != null ||
|
|
|
|
|
_mediaInfo.DvdrMediaIdentifier != null ||
|
|
|
|
|
_mediaInfo.DvdrPhysicalInformation != null ||
|
|
|
|
|
_mediaInfo.HddvdrMediumStatus != null ||
|
|
|
|
|
_mediaInfo.HddvdrLastRmd != null ||
|
|
|
|
|
_mediaInfo.DvdrLayerCapacity != null ||
|
|
|
|
|
_mediaInfo.DvdrDlMiddleZoneStart != null ||
|
|
|
|
|
_mediaInfo.DvdrDlJumpIntervalSize != null ||
|
|
|
|
|
_mediaInfo.DvdrDlManualLayerJumpStartLba != null ||
|
|
|
|
|
_mediaInfo.DvdrDlRemapAnchorPoint != null ||
|
|
|
|
|
_mediaInfo.DvdPlusAdip != null ||
|
|
|
|
|
_mediaInfo.DvdPlusDcb != null)
|
|
|
|
|
{
|
|
|
|
|
DvdWritableInfo = new DvdWritableInfo
|
|
|
|
|
{
|
|
|
|
|
DataContext = new DvdWritableInfoViewModel(_mediaInfo.DvdRamDds,
|
|
|
|
|
_mediaInfo.DvdRamCartridgeStatus,
|
|
|
|
|
_mediaInfo.DvdRamSpareArea,
|
|
|
|
|
_mediaInfo.LastBorderOutRmd,
|
|
|
|
|
_mediaInfo.DvdPreRecordedInfo,
|
|
|
|
|
_mediaInfo.DvdrMediaIdentifier,
|
|
|
|
|
_mediaInfo.DvdrPhysicalInformation,
|
|
|
|
|
_mediaInfo.HddvdrMediumStatus,
|
|
|
|
|
_mediaInfo.HddvdrLastRmd,
|
|
|
|
|
_mediaInfo.DvdrLayerCapacity,
|
|
|
|
|
_mediaInfo.DvdrDlMiddleZoneStart,
|
|
|
|
|
_mediaInfo.DvdrDlJumpIntervalSize,
|
|
|
|
|
_mediaInfo.DvdrDlManualLayerJumpStartLba,
|
|
|
|
|
_mediaInfo.DvdrDlRemapAnchorPoint,
|
|
|
|
|
_mediaInfo.DvdPlusAdip,
|
|
|
|
|
_mediaInfo.DvdPlusDcb,
|
|
|
|
|
_window)
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(_mediaInfo.BlurayDiscInformation != null ||
|
|
|
|
|
_mediaInfo.BlurayBurstCuttingArea != null ||
|
|
|
|
|
_mediaInfo.BlurayDds != null ||
|
|
|
|
|
_mediaInfo.BlurayCartridgeStatus != null ||
|
|
|
|
|
_mediaInfo.BluraySpareAreaInformation != null ||
|
|
|
|
|
_mediaInfo.BlurayPowResources != null ||
|
|
|
|
|
_mediaInfo.BlurayTrackResources != null ||
|
|
|
|
|
_mediaInfo.BlurayRawDfl != null ||
|
|
|
|
|
_mediaInfo.BlurayPac != null)
|
|
|
|
|
{
|
|
|
|
|
BlurayInfo = new BlurayInfo
|
|
|
|
|
{
|
|
|
|
|
DataContext = new BlurayInfoViewModel(_mediaInfo.BlurayDiscInformation,
|
|
|
|
|
_mediaInfo.BlurayBurstCuttingArea,
|
|
|
|
|
_mediaInfo.BlurayDds,
|
|
|
|
|
_mediaInfo.BlurayCartridgeStatus,
|
|
|
|
|
_mediaInfo.BluraySpareAreaInformation,
|
|
|
|
|
_mediaInfo.BlurayPowResources,
|
|
|
|
|
_mediaInfo.BlurayTrackResources,
|
|
|
|
|
_mediaInfo.BlurayRawDfl,
|
|
|
|
|
_mediaInfo.BlurayPac,
|
|
|
|
|
_window)
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
});
|
2025-11-19 18:07:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(devInfo.CID != null ||
|
|
|
|
|
devInfo.CSD != null ||
|
|
|
|
|
devInfo.OCR != null ||
|
|
|
|
|
devInfo.ExtendedCSD != null ||
|
|
|
|
|
devInfo.SCR != null)
|
2025-11-19 18:40:00 +00:00
|
|
|
{
|
2025-11-19 18:07:32 +00:00
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
|
|
|
|
SdMmcInfo = new SdMmcInfo
|
|
|
|
|
{
|
|
|
|
|
DataContext = new SdMmcInfoViewModel(devInfo.Type,
|
|
|
|
|
devInfo.CID,
|
|
|
|
|
devInfo.CSD,
|
|
|
|
|
devInfo.OCR,
|
|
|
|
|
devInfo.ExtendedCSD,
|
|
|
|
|
devInfo.SCR)
|
|
|
|
|
};
|
2025-11-19 19:56:01 +00:00
|
|
|
|
|
|
|
|
MediaIsInserted = true;
|
2025-11-19 18:07:32 +00:00
|
|
|
});
|
2025-11-19 18:40:00 +00:00
|
|
|
}
|
2025-11-19 19:56:01 +00:00
|
|
|
|
|
|
|
|
Dispatcher.UIThread.Invoke(() => StatusMessageVisible = false);
|
2025-11-19 15:15:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Closed()
|
|
|
|
|
{
|
|
|
|
|
_dev?.Close();
|
|
|
|
|
}
|
2025-11-19 19:56:01 +00:00
|
|
|
|
|
|
|
|
async Task DumpAsync()
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
switch(_scsiInfo.MediaType)
|
|
|
|
|
{
|
|
|
|
|
case CommonTypes.MediaType.GDR or CommonTypes.MediaType.GDROM:
|
|
|
|
|
await MessageBoxManager
|
|
|
|
|
.GetMessageBoxStandard(UI.Title_Error,
|
|
|
|
|
Localization.Core.GD_ROM_dump_support_is_not_yet_implemented,
|
|
|
|
|
ButtonEnum.Ok,
|
|
|
|
|
Icon.Error)
|
|
|
|
|
.ShowWindowDialogAsync(_view);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
case CommonTypes.MediaType.XGD or CommonTypes.MediaType.XGD2 or CommonTypes.MediaType.XGD3
|
|
|
|
|
when _scsiInfo.DeviceInfo.ScsiInquiry?.KreonPresent != true:
|
|
|
|
|
await MessageBoxManager
|
|
|
|
|
.GetMessageBoxStandard(UI.Title_Error,
|
|
|
|
|
Localization.Core
|
|
|
|
|
.Dumping_Xbox_Game_Discs_requires_a_drive_with_Kreon_firmware,
|
|
|
|
|
ButtonEnum.Ok,
|
|
|
|
|
Icon.Error)
|
|
|
|
|
.ShowWindowDialogAsync(_view);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var mediaDumpWindow = new MediaDump();
|
|
|
|
|
|
|
|
|
|
mediaDumpWindow.DataContext =
|
|
|
|
|
new MediaDumpViewModel(_devicePath, _scsiInfo.DeviceInfo, mediaDumpWindow, _scsiInfo);
|
|
|
|
|
|
|
|
|
|
mediaDumpWindow.Show();
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async Task ScanAsync()
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
switch(_scsiInfo.MediaType)
|
|
|
|
|
{
|
|
|
|
|
// TODO: GD-ROM
|
|
|
|
|
case CommonTypes.MediaType.GDR:
|
|
|
|
|
case CommonTypes.MediaType.GDROM:
|
|
|
|
|
await MessageBoxManager
|
|
|
|
|
.GetMessageBoxStandard(UI.Title_Error,
|
|
|
|
|
Localization.Core.GD_ROM_scan_support_is_not_yet_implemented,
|
|
|
|
|
ButtonEnum.Ok,
|
|
|
|
|
Icon.Error)
|
|
|
|
|
.ShowWindowDialogAsync(_view);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// TODO: Xbox
|
|
|
|
|
case CommonTypes.MediaType.XGD:
|
|
|
|
|
case CommonTypes.MediaType.XGD2:
|
|
|
|
|
case CommonTypes.MediaType.XGD3:
|
|
|
|
|
await MessageBoxManager.GetMessageBoxStandard(UI.Title_Error,
|
|
|
|
|
Localization.Core
|
|
|
|
|
.Scanning_Xbox_discs_is_not_yet_supported,
|
|
|
|
|
ButtonEnum.Ok,
|
|
|
|
|
Icon.Error)
|
|
|
|
|
.ShowWindowDialogAsync(_view);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var mediaScanWindow = new MediaScan();
|
|
|
|
|
|
|
|
|
|
mediaScanWindow.DataContext = new MediaScanViewModel(_devicePath, mediaScanWindow);
|
|
|
|
|
|
|
|
|
|
mediaScanWindow.Show();
|
|
|
|
|
*/
|
|
|
|
|
}
|
2025-11-19 15:15:58 +00:00
|
|
|
}
|