2017-05-19 20:28:49 +01:00
|
|
|
// /***************************************************************************
|
2015-10-12 19:55:00 +01:00
|
|
|
// The Disc Image Chef
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
//
|
2016-07-28 18:13:49 +01:00
|
|
|
// Filename : Constructor.cs
|
|
|
|
|
// Author(s) : Natalia Portillo <claunia@claunia.com>
|
2015-10-12 19:55:00 +01:00
|
|
|
//
|
2016-07-28 18:13:49 +01:00
|
|
|
// Component : Direct device access.
|
2015-10-12 19:55:00 +01:00
|
|
|
//
|
|
|
|
|
// --[ Description ] ----------------------------------------------------------
|
|
|
|
|
//
|
2016-07-28 18:13:49 +01:00
|
|
|
// Prepares a device for direct access.
|
2015-10-12 19:55:00 +01:00
|
|
|
//
|
|
|
|
|
// --[ License ] --------------------------------------------------------------
|
|
|
|
|
//
|
2016-07-28 18:13:49 +01:00
|
|
|
// 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
|
2015-10-12 19:55:00 +01:00
|
|
|
// License, or (at your option) any later version.
|
|
|
|
|
//
|
2016-07-28 18:13:49 +01:00
|
|
|
// 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.
|
2015-10-12 19:55:00 +01:00
|
|
|
//
|
2016-07-28 18:13:49 +01:00
|
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
2015-10-12 19:55:00 +01:00
|
|
|
//
|
|
|
|
|
// ----------------------------------------------------------------------------
|
2017-12-19 03:50:57 +00:00
|
|
|
// Copyright © 2011-2018 Natalia Portillo
|
2015-10-12 19:55:00 +01:00
|
|
|
// ****************************************************************************/
|
2016-07-28 18:13:49 +01:00
|
|
|
|
2015-10-12 19:55:00 +01:00
|
|
|
using System;
|
2017-12-21 07:08:26 +00:00
|
|
|
using System.Linq;
|
2015-10-13 01:45:07 +01:00
|
|
|
using System.Runtime.InteropServices;
|
2017-12-06 13:46:35 +00:00
|
|
|
using DiscImageChef.Console;
|
2015-11-23 04:26:53 +00:00
|
|
|
using DiscImageChef.Decoders.ATA;
|
2017-12-19 19:33:46 +00:00
|
|
|
using Microsoft.Win32.SafeHandles;
|
2015-10-12 19:55:00 +01:00
|
|
|
|
|
|
|
|
namespace DiscImageChef.Devices
|
|
|
|
|
{
|
|
|
|
|
public partial class Device
|
|
|
|
|
{
|
2015-10-12 20:08:56 +01:00
|
|
|
/// <summary>
|
|
|
|
|
/// Opens the device for sending direct commands
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="devicePath">Device path</param>
|
2015-10-12 19:55:00 +01:00
|
|
|
public Device(string devicePath)
|
|
|
|
|
{
|
2017-12-20 17:15:26 +00:00
|
|
|
platformId = Interop.DetectOS.GetRealPlatformID();
|
2015-10-12 19:55:00 +01:00
|
|
|
Timeout = 15;
|
2015-10-13 01:45:07 +01:00
|
|
|
error = false;
|
2015-12-30 11:45:27 +00:00
|
|
|
removable = false;
|
2015-10-12 19:55:00 +01:00
|
|
|
|
2017-12-20 17:15:26 +00:00
|
|
|
switch(platformId)
|
2015-10-12 19:55:00 +01:00
|
|
|
{
|
|
|
|
|
case Interop.PlatformID.Win32NT:
|
2017-12-19 20:33:03 +00:00
|
|
|
{
|
|
|
|
|
fd = Windows.Extern.CreateFile(devicePath,
|
|
|
|
|
Windows.FileAccess.GenericRead | Windows.FileAccess.GenericWrite,
|
|
|
|
|
Windows.FileShare.Read | Windows.FileShare.Write, IntPtr.Zero,
|
|
|
|
|
Windows.FileMode.OpenExisting, Windows.FileAttributes.Normal,
|
|
|
|
|
IntPtr.Zero);
|
2015-10-13 01:45:07 +01:00
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
if(((SafeFileHandle)fd).IsInvalid)
|
2015-10-12 19:55:00 +01:00
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
error = true;
|
|
|
|
|
lastError = Marshal.GetLastWin32Error();
|
|
|
|
|
}
|
2015-10-13 01:45:07 +01:00
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case Interop.PlatformID.Linux:
|
|
|
|
|
{
|
|
|
|
|
fd = Linux.Extern.open(devicePath, Linux.FileFlags.Readonly | Linux.FileFlags.NonBlocking);
|
2015-10-12 19:55:00 +01:00
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
if((int)fd < 0)
|
|
|
|
|
{
|
|
|
|
|
error = true;
|
|
|
|
|
lastError = Marshal.GetLastWin32Error();
|
2015-10-12 19:55:00 +01:00
|
|
|
}
|
2017-12-19 20:33:03 +00:00
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
2017-12-10 21:00:20 +00:00
|
|
|
case Interop.PlatformID.FreeBSD:
|
|
|
|
|
{
|
|
|
|
|
fd = FreeBSD.Extern.cam_open_device(devicePath, FreeBSD.FileFlags.ReadWrite);
|
|
|
|
|
|
|
|
|
|
if(((IntPtr)fd).ToInt64() == 0)
|
|
|
|
|
{
|
|
|
|
|
error = true;
|
|
|
|
|
lastError = Marshal.GetLastWin32Error();
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-20 17:15:26 +00:00
|
|
|
FreeBSD.CamDevice camDevice =
|
|
|
|
|
(FreeBSD.CamDevice)Marshal.PtrToStructure((IntPtr)fd, typeof(FreeBSD.CamDevice));
|
2017-12-19 20:33:03 +00:00
|
|
|
|
2017-12-20 17:15:26 +00:00
|
|
|
if(StringHandlers.CToString(camDevice.SimName) == "ata")
|
2017-12-19 20:33:03 +00:00
|
|
|
throw new
|
|
|
|
|
InvalidOperationException("Parallel ATA devices are not supported on FreeBSD due to upstream bug #224250.");
|
2017-12-11 19:29:19 +00:00
|
|
|
|
2017-12-10 21:00:20 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2015-10-12 19:55:00 +01:00
|
|
|
default:
|
2017-12-20 17:15:26 +00:00
|
|
|
throw new InvalidOperationException(string.Format("Platform {0} not yet supported.", platformId));
|
2015-10-12 19:55:00 +01:00
|
|
|
}
|
2015-10-19 04:46:09 +01:00
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
if(error) throw new SystemException(string.Format("Error {0} opening device.", lastError));
|
* DiscImageChef.CommonTypes/MediaTypeFromSCSI.cs:
* DiscImageChef.CommonTypes/DiscImageChef.CommonTypes.csproj:
Added method to calculate MediaType from SCSI parameters
(mode, density, medium type, device type, etc).
* DiscImageChef.Metadata/DeviceReport.cs:
Added command to guess drive and media parameters and output
an XML report of them.
* DiscImageChef/Commands/DeviceReport.cs:
* DiscImageChef.Metadata/DiscImageChef.Metadata.csproj:
Added command to guess drive and media parameters and output
an XML report of them.
* DiscImageChef/Commands/DumpMedia.cs:
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
* DiscImageChef/Core/Checksum.cs:
* DiscImageChef/Commands/CreateSidecar.cs:
Moved checksum generation to a separate class.
* CICMMetadata:
Added support for ADIP.
* DiscImageChef.CommonTypes/MediaType.cs:
Added parameters of UDO media.
Moved DataPlay outside of Iomega, as it's not from that
manufacturer.
Added missing Exatape media and corrected 160m XL one.
Added SyJet media.
Added all ECMA defined magneto-optical (sectors calculated
from specifications, unchecked).
Added PD media.
Added Imation 320Gb RDX.
Added generic USB flash drives.
* DiscImageChef.Decoders/SCSI/Enums.cs:
Make enumerations public.
* DiscImageChef.Decoders/SCSI/Inquiry.cs:
* DiscImageChef.Devices/Device/Constructor.cs:
Trim space padded strings on SCSI INQUIRY.
* DiscImageChef.Devices/Device/ScsiCommands/MMC.cs:
Added PREVENT ALLOW MEDIUM REMOVAL.
Added START STOP UNIT.
* DiscImageChef.Devices/Device/ScsiCommands/NEC.cs:
Rename NEC methods.
* DiscImageChef.Devices/Device/ScsiCommands/Pioneer.cs:
Corrected Pioneer transfer length calculation.
* DiscImageChef.Devices/Device/ScsiCommands/Plextor.cs:
Renamed Plextor methods.
* DiscImageChef.Devices/Device/ScsiCommands/SPC.cs:
Renamed SSC PREVENT ALLOW MEDIUM REMOVAL to uncollide with
MMC same name but different command.
* DiscImageChef.Devices/DiscImageChef.Devices.csproj:
Set platform target to x86 (does it really matter?).
* DiscImageChef.Devices/Linux/Command.cs:
Reduced allocation for readlink() to current kernel
MAX_PATH.
* DiscImageChef.Devices/Linux/Enums.cs:
Modified Linux ioctl to 32-bit. Works on 64-bit also. Solves
commands not working on 32-bit environments.
* DiscImageChef.DiscImages/ZZZRawImage.cs:
Changed ECMA-184 and ECMA-183 enums.
* DiscImageChef.Metadata/Dimensions.cs:
Added all ECMA defined magneto-opticals.
Added PD media.
Added 320Gb RDX.
Corrected Exatape 160m XL.
Added Exatape 22m and 28m.
* DiscImageChef.Metadata/MediaType.cs:
Added 356mm magneto-optical media.
Changed ECMA-184 and ECMA-183 enums.
Added USB generic flash drive.
* DiscImageChef/Commands/DeviceInfo.cs:
Corrected SCSI INQUIRY naming.
Corrected SCSI MODE SENSE (6) parameters.
Reduced SCSI MODE SENSE timeout, some devices just get stuck
with unsupported MODE SENSE commanda and must be left to
timeout.
Changed FUJITSU vendor string comparison.
* DiscImageChef/Commands/MediaInfo.cs:
Added method to calculate MediaType from SCSI parameters
(mode, density, medium type, device type, etc).
Changed some error WriteLine() to debug ones. Too much
verbosity.
Added DVD media type decoding from PFI.
Found a drive that dumps ADIP, enabling it again (not
decoded).
* DiscImageChef/Commands/MediaScan.cs:
Added option to generate ImgBurn compatible log to
media-scan command.
* DiscImageChef/DiscImageChef.csproj:
Moved checksum generation to a separate class.
Added command to guess drive and media parameters and output
an XML report of them.
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
* DiscImageChef/Main.cs:
Added command to guess drive and media parameters and output
an XML report of them.
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
* DiscImageChef/Options.cs:
Added command to guess drive and media parameters and output
an XML report of them.
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
Added option to generate ImgBurn compatible log to media-scan
command.
2016-01-31 08:05:56 +00:00
|
|
|
|
2015-10-19 04:46:09 +01:00
|
|
|
type = DeviceType.Unknown;
|
2015-10-19 05:20:42 +01:00
|
|
|
scsiType = Decoders.SCSI.PeripheralDeviceTypes.UnknownDevice;
|
2015-10-19 05:11:28 +01:00
|
|
|
|
|
|
|
|
AtaErrorRegistersCHS errorRegisters;
|
|
|
|
|
|
|
|
|
|
byte[] ataBuf;
|
2015-11-05 06:50:02 +00:00
|
|
|
byte[] senseBuf;
|
2017-09-07 16:47:06 +01:00
|
|
|
byte[] inqBuf = null;
|
2015-10-19 05:11:28 +01:00
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
if(error) throw new SystemException(string.Format("Error {0} trying device.", lastError));
|
* DiscImageChef.CommonTypes/MediaTypeFromSCSI.cs:
* DiscImageChef.CommonTypes/DiscImageChef.CommonTypes.csproj:
Added method to calculate MediaType from SCSI parameters
(mode, density, medium type, device type, etc).
* DiscImageChef.Metadata/DeviceReport.cs:
Added command to guess drive and media parameters and output
an XML report of them.
* DiscImageChef/Commands/DeviceReport.cs:
* DiscImageChef.Metadata/DiscImageChef.Metadata.csproj:
Added command to guess drive and media parameters and output
an XML report of them.
* DiscImageChef/Commands/DumpMedia.cs:
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
* DiscImageChef/Core/Checksum.cs:
* DiscImageChef/Commands/CreateSidecar.cs:
Moved checksum generation to a separate class.
* CICMMetadata:
Added support for ADIP.
* DiscImageChef.CommonTypes/MediaType.cs:
Added parameters of UDO media.
Moved DataPlay outside of Iomega, as it's not from that
manufacturer.
Added missing Exatape media and corrected 160m XL one.
Added SyJet media.
Added all ECMA defined magneto-optical (sectors calculated
from specifications, unchecked).
Added PD media.
Added Imation 320Gb RDX.
Added generic USB flash drives.
* DiscImageChef.Decoders/SCSI/Enums.cs:
Make enumerations public.
* DiscImageChef.Decoders/SCSI/Inquiry.cs:
* DiscImageChef.Devices/Device/Constructor.cs:
Trim space padded strings on SCSI INQUIRY.
* DiscImageChef.Devices/Device/ScsiCommands/MMC.cs:
Added PREVENT ALLOW MEDIUM REMOVAL.
Added START STOP UNIT.
* DiscImageChef.Devices/Device/ScsiCommands/NEC.cs:
Rename NEC methods.
* DiscImageChef.Devices/Device/ScsiCommands/Pioneer.cs:
Corrected Pioneer transfer length calculation.
* DiscImageChef.Devices/Device/ScsiCommands/Plextor.cs:
Renamed Plextor methods.
* DiscImageChef.Devices/Device/ScsiCommands/SPC.cs:
Renamed SSC PREVENT ALLOW MEDIUM REMOVAL to uncollide with
MMC same name but different command.
* DiscImageChef.Devices/DiscImageChef.Devices.csproj:
Set platform target to x86 (does it really matter?).
* DiscImageChef.Devices/Linux/Command.cs:
Reduced allocation for readlink() to current kernel
MAX_PATH.
* DiscImageChef.Devices/Linux/Enums.cs:
Modified Linux ioctl to 32-bit. Works on 64-bit also. Solves
commands not working on 32-bit environments.
* DiscImageChef.DiscImages/ZZZRawImage.cs:
Changed ECMA-184 and ECMA-183 enums.
* DiscImageChef.Metadata/Dimensions.cs:
Added all ECMA defined magneto-opticals.
Added PD media.
Added 320Gb RDX.
Corrected Exatape 160m XL.
Added Exatape 22m and 28m.
* DiscImageChef.Metadata/MediaType.cs:
Added 356mm magneto-optical media.
Changed ECMA-184 and ECMA-183 enums.
Added USB generic flash drive.
* DiscImageChef/Commands/DeviceInfo.cs:
Corrected SCSI INQUIRY naming.
Corrected SCSI MODE SENSE (6) parameters.
Reduced SCSI MODE SENSE timeout, some devices just get stuck
with unsupported MODE SENSE commanda and must be left to
timeout.
Changed FUJITSU vendor string comparison.
* DiscImageChef/Commands/MediaInfo.cs:
Added method to calculate MediaType from SCSI parameters
(mode, density, medium type, device type, etc).
Changed some error WriteLine() to debug ones. Too much
verbosity.
Added DVD media type decoding from PFI.
Found a drive that dumps ADIP, enabling it again (not
decoded).
* DiscImageChef/Commands/MediaScan.cs:
Added option to generate ImgBurn compatible log to
media-scan command.
* DiscImageChef/DiscImageChef.csproj:
Moved checksum generation to a separate class.
Added command to guess drive and media parameters and output
an XML report of them.
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
* DiscImageChef/Main.cs:
Added command to guess drive and media parameters and output
an XML report of them.
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
* DiscImageChef/Options.cs:
Added command to guess drive and media parameters and output
an XML report of them.
Added preliminary command to dump media. Only SCSI for now.
CDs and tapes are not supported. Errors are blalanty
ignored. Options are incomplete. Not yet usable.
Added option to generate ImgBurn compatible log to media-scan
command.
2016-01-31 08:05:56 +00:00
|
|
|
|
2017-09-07 16:47:06 +01:00
|
|
|
bool scsiSense = true;
|
2017-12-06 13:46:35 +00:00
|
|
|
string ntDevicePath = null;
|
2017-09-07 16:47:06 +01:00
|
|
|
|
|
|
|
|
// Windows is answering SCSI INQUIRY for all device types so it needs to be detected first
|
2017-12-21 04:43:29 +00:00
|
|
|
switch(platformId) {
|
|
|
|
|
case Interop.PlatformID.Win32NT:
|
|
|
|
|
Windows.StoragePropertyQuery query = new Windows.StoragePropertyQuery();
|
|
|
|
|
query.PropertyId = Windows.StoragePropertyId.Device;
|
|
|
|
|
query.QueryType = Windows.StorageQueryType.Standard;
|
|
|
|
|
query.AdditionalParameters = new byte[1];
|
2017-09-07 16:47:06 +01:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
IntPtr descriptorPtr = Marshal.AllocHGlobal(1000);
|
|
|
|
|
byte[] descriptorB = new byte[1000];
|
2017-09-07 16:47:06 +01:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
uint returned = 0;
|
|
|
|
|
int error = 0;
|
2017-09-07 16:47:06 +01:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
bool hasError = !Windows.Extern.DeviceIoControlStorageQuery((SafeFileHandle)fd,
|
|
|
|
|
Windows.WindowsIoctl
|
|
|
|
|
.IoctlStorageQueryProperty,
|
|
|
|
|
ref query, (uint)Marshal.SizeOf(query),
|
|
|
|
|
descriptorPtr, 1000, ref returned,
|
|
|
|
|
IntPtr.Zero);
|
2017-09-07 16:47:06 +01:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
if(hasError) error = Marshal.GetLastWin32Error();
|
2017-09-07 16:47:06 +01:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
Marshal.Copy(descriptorPtr, descriptorB, 0, 1000);
|
2017-09-07 16:47:06 +01:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
if(!hasError && error == 0)
|
2017-09-07 16:47:06 +01:00
|
|
|
{
|
2017-12-21 04:43:29 +00:00
|
|
|
Windows.StorageDeviceDescriptor descriptor = new Windows.StorageDeviceDescriptor();
|
|
|
|
|
descriptor.Version = BitConverter.ToUInt32(descriptorB, 0);
|
|
|
|
|
descriptor.Size = BitConverter.ToUInt32(descriptorB, 4);
|
|
|
|
|
descriptor.DeviceType = descriptorB[8];
|
|
|
|
|
descriptor.DeviceTypeModifier = descriptorB[9];
|
|
|
|
|
descriptor.RemovableMedia = descriptorB[10] > 0;
|
|
|
|
|
descriptor.CommandQueueing = descriptorB[11] > 0;
|
|
|
|
|
descriptor.VendorIdOffset = BitConverter.ToInt32(descriptorB, 12);
|
|
|
|
|
descriptor.ProductIdOffset = BitConverter.ToInt32(descriptorB, 16);
|
|
|
|
|
descriptor.ProductRevisionOffset = BitConverter.ToInt32(descriptorB, 20);
|
|
|
|
|
descriptor.SerialNumberOffset = BitConverter.ToInt32(descriptorB, 24);
|
|
|
|
|
descriptor.BusType = (Windows.StorageBusType)BitConverter.ToUInt32(descriptorB, 28);
|
|
|
|
|
descriptor.RawPropertiesLength = BitConverter.ToUInt32(descriptorB, 32);
|
|
|
|
|
descriptor.RawDeviceProperties = new byte[descriptor.RawPropertiesLength];
|
|
|
|
|
Array.Copy(descriptorB, 36, descriptor.RawDeviceProperties, 0, descriptor.RawPropertiesLength);
|
|
|
|
|
|
|
|
|
|
switch(descriptor.BusType)
|
|
|
|
|
{
|
|
|
|
|
case Windows.StorageBusType.SCSI:
|
|
|
|
|
case Windows.StorageBusType.SSA:
|
|
|
|
|
case Windows.StorageBusType.Fibre:
|
|
|
|
|
case Windows.StorageBusType.iSCSI:
|
|
|
|
|
case Windows.StorageBusType.SAS:
|
|
|
|
|
type = DeviceType.SCSI;
|
|
|
|
|
break;
|
|
|
|
|
case Windows.StorageBusType.FireWire:
|
|
|
|
|
firewire = true;
|
|
|
|
|
type = DeviceType.SCSI;
|
|
|
|
|
break;
|
|
|
|
|
case Windows.StorageBusType.USB:
|
|
|
|
|
usb = true;
|
|
|
|
|
type = DeviceType.SCSI;
|
|
|
|
|
break;
|
|
|
|
|
case Windows.StorageBusType.ATAPI:
|
|
|
|
|
type = DeviceType.ATAPI;
|
|
|
|
|
break;
|
|
|
|
|
case Windows.StorageBusType.ATA:
|
|
|
|
|
case Windows.StorageBusType.SATA:
|
|
|
|
|
type = DeviceType.ATA;
|
|
|
|
|
break;
|
|
|
|
|
case Windows.StorageBusType.MultiMediaCard:
|
|
|
|
|
type = DeviceType.MMC;
|
|
|
|
|
break;
|
|
|
|
|
case Windows.StorageBusType.SecureDigital:
|
|
|
|
|
type = DeviceType.SecureDigital;
|
|
|
|
|
break;
|
|
|
|
|
case Windows.StorageBusType.NVMe:
|
|
|
|
|
type = DeviceType.NVMe;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2017-09-07 16:47:06 +01:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
switch(type) {
|
|
|
|
|
case DeviceType.SCSI:
|
|
|
|
|
case DeviceType.ATAPI: scsiSense = ScsiInquiry(out inqBuf, out senseBuf);
|
|
|
|
|
break;
|
|
|
|
|
case DeviceType.ATA:
|
|
|
|
|
bool atapiSense = AtapiIdentify(out ataBuf, out errorRegisters);
|
2017-09-07 16:47:06 +01:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
if(!atapiSense)
|
|
|
|
|
{
|
|
|
|
|
type = DeviceType.ATAPI;
|
|
|
|
|
Identify.IdentifyDevice? ataid = Identify.Decode(ataBuf);
|
2017-09-07 16:47:06 +01:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
if(ataid.HasValue) scsiSense = ScsiInquiry(out inqBuf, out senseBuf);
|
|
|
|
|
}
|
|
|
|
|
else manufacturer = "ATA";
|
|
|
|
|
break;
|
2017-09-07 16:47:06 +01:00
|
|
|
}
|
|
|
|
|
}
|
2017-12-06 23:05:59 +00:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
ntDevicePath = Windows.Command.GetDevicePath((SafeFileHandle)fd);
|
|
|
|
|
DicConsole.DebugWriteLine("Windows devices", "NT device path: {0}", ntDevicePath);
|
|
|
|
|
Marshal.FreeHGlobal(descriptorPtr);
|
2017-12-06 23:05:59 +00:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
if(Windows.Command.IsSdhci((SafeFileHandle)fd))
|
2017-12-06 23:05:59 +00:00
|
|
|
{
|
2017-12-21 04:43:29 +00:00
|
|
|
byte[] sdBuffer = new byte[16];
|
|
|
|
|
bool sense = false;
|
2017-12-06 23:05:59 +00:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
lastError = Windows.Command.SendMmcCommand((SafeFileHandle)fd, MmcCommands.SendCsd, false, false,
|
|
|
|
|
MmcFlags.ResponseSpiR2 | MmcFlags.ResponseR2 |
|
|
|
|
|
MmcFlags.CommandAc, 0, 16, 1, ref sdBuffer,
|
|
|
|
|
out uint[] response, out double duration, out sense, 0);
|
2017-12-06 23:05:59 +00:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
if(!sense)
|
|
|
|
|
{
|
|
|
|
|
cachedCsd = new byte[16];
|
|
|
|
|
Array.Copy(sdBuffer, 0, cachedCsd, 0, 16);
|
|
|
|
|
}
|
2017-12-06 23:05:59 +00:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
sdBuffer = new byte[16];
|
|
|
|
|
sense = false;
|
2017-12-06 23:05:59 +00:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
lastError = Windows.Command.SendMmcCommand((SafeFileHandle)fd, MmcCommands.SendCid, false, false,
|
|
|
|
|
MmcFlags.ResponseSpiR2 | MmcFlags.ResponseR2 |
|
|
|
|
|
MmcFlags.CommandAc, 0, 16, 1, ref sdBuffer, out response,
|
|
|
|
|
out duration, out sense, 0);
|
2017-12-06 23:05:59 +00:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
if(!sense)
|
|
|
|
|
{
|
|
|
|
|
cachedCid = new byte[16];
|
|
|
|
|
Array.Copy(sdBuffer, 0, cachedCid, 0, 16);
|
|
|
|
|
}
|
2017-12-06 23:05:59 +00:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
sdBuffer = new byte[8];
|
2017-12-06 23:05:59 +00:00
|
|
|
sense = false;
|
|
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
lastError = Windows.Command.SendMmcCommand((SafeFileHandle)fd,
|
2017-12-21 04:43:29 +00:00
|
|
|
(MmcCommands)SecureDigitalCommands.SendScr, false, true,
|
|
|
|
|
MmcFlags.ResponseSpiR1 | MmcFlags.ResponseR1 |
|
|
|
|
|
MmcFlags.CommandAdtc, 0, 8, 1, ref sdBuffer,
|
2017-12-19 20:33:03 +00:00
|
|
|
out response, out duration, out sense, 0);
|
2017-12-06 23:05:59 +00:00
|
|
|
|
|
|
|
|
if(!sense)
|
|
|
|
|
{
|
2017-12-21 04:43:29 +00:00
|
|
|
cachedScr = new byte[8];
|
|
|
|
|
Array.Copy(sdBuffer, 0, cachedScr, 0, 8);
|
2017-12-06 23:05:59 +00:00
|
|
|
}
|
|
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
if(cachedScr != null)
|
|
|
|
|
{
|
|
|
|
|
sdBuffer = new byte[4];
|
|
|
|
|
sense = false;
|
2017-12-06 23:05:59 +00:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
lastError = Windows.Command.SendMmcCommand((SafeFileHandle)fd,
|
|
|
|
|
(MmcCommands)SecureDigitalCommands
|
|
|
|
|
.SendOperatingCondition, false, true,
|
|
|
|
|
MmcFlags.ResponseSpiR3 | MmcFlags.ResponseR3 |
|
|
|
|
|
MmcFlags.CommandBcr, 0, 4, 1, ref sdBuffer,
|
|
|
|
|
out response, out duration, out sense, 0);
|
|
|
|
|
|
|
|
|
|
if(!sense)
|
|
|
|
|
{
|
|
|
|
|
cachedScr = new byte[4];
|
|
|
|
|
Array.Copy(sdBuffer, 0, cachedScr, 0, 4);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
2017-12-06 23:05:59 +00:00
|
|
|
{
|
2017-12-21 04:43:29 +00:00
|
|
|
sdBuffer = new byte[4];
|
|
|
|
|
sense = false;
|
|
|
|
|
|
|
|
|
|
lastError = Windows.Command.SendMmcCommand((SafeFileHandle)fd, MmcCommands.SendOpCond, false,
|
|
|
|
|
true,
|
|
|
|
|
MmcFlags.ResponseSpiR3 | MmcFlags.ResponseR3 |
|
|
|
|
|
MmcFlags.CommandBcr, 0, 4, 1, ref sdBuffer,
|
|
|
|
|
out response, out duration, out sense, 0);
|
|
|
|
|
|
|
|
|
|
if(!sense)
|
|
|
|
|
{
|
|
|
|
|
cachedScr = new byte[4];
|
|
|
|
|
Array.Copy(sdBuffer, 0, cachedScr, 0, 4);
|
|
|
|
|
}
|
2017-12-06 23:05:59 +00:00
|
|
|
}
|
|
|
|
|
}
|
2017-12-21 04:43:29 +00:00
|
|
|
break;
|
|
|
|
|
case Interop.PlatformID.Linux:
|
|
|
|
|
if(devicePath.StartsWith("/dev/sd", StringComparison.Ordinal) ||
|
|
|
|
|
devicePath.StartsWith("/dev/sr", StringComparison.Ordinal) ||
|
|
|
|
|
devicePath.StartsWith("/dev/st", StringComparison.Ordinal))
|
|
|
|
|
scsiSense = ScsiInquiry(out inqBuf, out senseBuf);
|
|
|
|
|
// MultiMediaCard and SecureDigital go here
|
|
|
|
|
else if(devicePath.StartsWith("/dev/mmcblk", StringComparison.Ordinal))
|
2017-09-29 13:05:50 +00:00
|
|
|
{
|
2017-12-21 04:43:29 +00:00
|
|
|
string devPath = devicePath.Substring(5);
|
|
|
|
|
if(System.IO.File.Exists("/sys/block/" + devPath + "/device/csd"))
|
|
|
|
|
{
|
|
|
|
|
int len = ConvertFromHexAscii("/sys/block/" + devPath + "/device/csd", out cachedCsd);
|
|
|
|
|
if(len == 0) cachedCsd = null;
|
|
|
|
|
}
|
|
|
|
|
if(System.IO.File.Exists("/sys/block/" + devPath + "/device/cid"))
|
|
|
|
|
{
|
|
|
|
|
int len = ConvertFromHexAscii("/sys/block/" + devPath + "/device/cid", out cachedCid);
|
|
|
|
|
if(len == 0) cachedCid = null;
|
|
|
|
|
}
|
|
|
|
|
if(System.IO.File.Exists("/sys/block/" + devPath + "/device/scr"))
|
|
|
|
|
{
|
|
|
|
|
int len = ConvertFromHexAscii("/sys/block/" + devPath + "/device/scr", out cachedScr);
|
|
|
|
|
if(len == 0) cachedScr = null;
|
|
|
|
|
}
|
|
|
|
|
if(System.IO.File.Exists("/sys/block/" + devPath + "/device/ocr"))
|
|
|
|
|
{
|
|
|
|
|
int len = ConvertFromHexAscii("/sys/block/" + devPath + "/device/ocr", out cachedOcr);
|
|
|
|
|
if(len == 0) cachedOcr = null;
|
|
|
|
|
}
|
2017-09-29 13:05:50 +00:00
|
|
|
}
|
2017-12-21 04:43:29 +00:00
|
|
|
break;
|
|
|
|
|
default: scsiSense = ScsiInquiry(out inqBuf, out senseBuf);
|
|
|
|
|
break;
|
2017-12-06 23:05:59 +00:00
|
|
|
}
|
2017-09-28 19:14:50 +00:00
|
|
|
|
2017-12-06 23:05:59 +00:00
|
|
|
#region SecureDigital / MultiMediaCard
|
|
|
|
|
if(cachedCid != null)
|
|
|
|
|
{
|
|
|
|
|
scsiType = Decoders.SCSI.PeripheralDeviceTypes.DirectAccess;
|
|
|
|
|
removable = false;
|
2017-09-28 19:14:50 +00:00
|
|
|
|
2017-12-06 23:05:59 +00:00
|
|
|
if(cachedScr != null)
|
|
|
|
|
{
|
|
|
|
|
type = DeviceType.SecureDigital;
|
|
|
|
|
Decoders.SecureDigital.CID decoded = Decoders.SecureDigital.Decoders.DecodeCID(cachedCid);
|
|
|
|
|
manufacturer = Decoders.SecureDigital.VendorString.Prettify(decoded.Manufacturer);
|
|
|
|
|
model = decoded.ProductName;
|
2017-12-19 20:33:03 +00:00
|
|
|
revision = string.Format("{0:X2}.{1:X2}", (decoded.ProductRevision & 0xF0) >> 4,
|
|
|
|
|
decoded.ProductRevision & 0x0F);
|
2017-12-06 23:05:59 +00:00
|
|
|
serial = string.Format("{0}", decoded.ProductSerialNumber);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
type = DeviceType.MMC;
|
|
|
|
|
Decoders.MMC.CID decoded = Decoders.MMC.Decoders.DecodeCID(cachedCid);
|
|
|
|
|
manufacturer = Decoders.MMC.VendorString.Prettify(decoded.Manufacturer);
|
|
|
|
|
model = decoded.ProductName;
|
2017-12-19 20:33:03 +00:00
|
|
|
revision = string.Format("{0:X2}.{1:X2}", (decoded.ProductRevision & 0xF0) >> 4,
|
|
|
|
|
decoded.ProductRevision & 0x0F);
|
2017-12-06 23:05:59 +00:00
|
|
|
serial = string.Format("{0}", decoded.ProductSerialNumber);
|
2017-09-28 19:14:50 +00:00
|
|
|
}
|
2017-09-28 17:54:07 +00:00
|
|
|
}
|
2017-12-06 23:05:59 +00:00
|
|
|
#endregion SecureDigital / MultiMediaCard
|
2017-12-06 13:46:35 +00:00
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
#region USB
|
2017-12-21 04:43:29 +00:00
|
|
|
switch(platformId) {
|
|
|
|
|
case Interop.PlatformID.Linux:
|
|
|
|
|
if(devicePath.StartsWith("/dev/sd", StringComparison.Ordinal) ||
|
|
|
|
|
devicePath.StartsWith("/dev/sr", StringComparison.Ordinal) ||
|
|
|
|
|
devicePath.StartsWith("/dev/st", StringComparison.Ordinal))
|
2015-12-31 16:12:22 +00:00
|
|
|
{
|
2017-12-21 04:43:29 +00:00
|
|
|
string devPath = devicePath.Substring(5);
|
|
|
|
|
if(System.IO.Directory.Exists("/sys/block/" + devPath))
|
|
|
|
|
{
|
|
|
|
|
string resolvedLink = Linux.Command.ReadLink("/sys/block/" + devPath);
|
|
|
|
|
resolvedLink = "/sys" + resolvedLink.Substring(2);
|
|
|
|
|
if(!string.IsNullOrEmpty(resolvedLink))
|
|
|
|
|
while(resolvedLink.Contains("usb"))
|
2015-12-31 16:12:22 +00:00
|
|
|
{
|
2017-12-21 04:43:29 +00:00
|
|
|
resolvedLink = System.IO.Path.GetDirectoryName(resolvedLink);
|
2017-12-21 06:06:19 +00:00
|
|
|
if(!System.IO.File.Exists(resolvedLink + "/descriptors") ||
|
|
|
|
|
!System.IO.File.Exists(resolvedLink + "/idProduct") ||
|
|
|
|
|
!System.IO.File.Exists(resolvedLink + "/idVendor")) continue;
|
|
|
|
|
|
|
|
|
|
System.IO.FileStream usbFs;
|
|
|
|
|
System.IO.StreamReader usbSr;
|
|
|
|
|
string usbTemp;
|
|
|
|
|
|
|
|
|
|
usbFs = new System.IO.FileStream(resolvedLink + "/descriptors",
|
|
|
|
|
System.IO.FileMode.Open,
|
|
|
|
|
System.IO.FileAccess.Read);
|
|
|
|
|
byte[] usbBuf = new byte[65536];
|
|
|
|
|
int usbCount = usbFs.Read(usbBuf, 0, 65536);
|
|
|
|
|
usbDescriptors = new byte[usbCount];
|
|
|
|
|
Array.Copy(usbBuf, 0, usbDescriptors, 0, usbCount);
|
|
|
|
|
usbFs.Close();
|
|
|
|
|
|
|
|
|
|
usbSr = new System.IO.StreamReader(resolvedLink + "/idProduct");
|
|
|
|
|
usbTemp = usbSr.ReadToEnd();
|
|
|
|
|
ushort.TryParse(usbTemp, System.Globalization.NumberStyles.HexNumber,
|
|
|
|
|
System.Globalization.CultureInfo.InvariantCulture, out usbProduct);
|
|
|
|
|
usbSr.Close();
|
|
|
|
|
|
|
|
|
|
usbSr = new System.IO.StreamReader(resolvedLink + "/idVendor");
|
|
|
|
|
usbTemp = usbSr.ReadToEnd();
|
|
|
|
|
ushort.TryParse(usbTemp, System.Globalization.NumberStyles.HexNumber,
|
|
|
|
|
System.Globalization.CultureInfo.InvariantCulture, out usbVendor);
|
|
|
|
|
usbSr.Close();
|
|
|
|
|
|
|
|
|
|
if(System.IO.File.Exists(resolvedLink + "/manufacturer"))
|
2015-12-31 16:12:22 +00:00
|
|
|
{
|
2017-12-21 06:06:19 +00:00
|
|
|
usbSr = new System.IO.StreamReader(resolvedLink + "/manufacturer");
|
|
|
|
|
usbManufacturerString = usbSr.ReadToEnd().Trim();
|
2015-12-31 16:12:22 +00:00
|
|
|
usbSr.Close();
|
2017-12-21 06:06:19 +00:00
|
|
|
}
|
2015-12-31 16:12:22 +00:00
|
|
|
|
2017-12-21 06:06:19 +00:00
|
|
|
if(System.IO.File.Exists(resolvedLink + "/product"))
|
|
|
|
|
{
|
|
|
|
|
usbSr = new System.IO.StreamReader(resolvedLink + "/product");
|
|
|
|
|
usbProductString = usbSr.ReadToEnd().Trim();
|
2016-04-19 02:11:47 +01:00
|
|
|
usbSr.Close();
|
2017-12-21 06:06:19 +00:00
|
|
|
}
|
2015-12-31 16:12:22 +00:00
|
|
|
|
2017-12-21 06:06:19 +00:00
|
|
|
if(System.IO.File.Exists(resolvedLink + "/serial"))
|
|
|
|
|
{
|
|
|
|
|
usbSr = new System.IO.StreamReader(resolvedLink + "/serial");
|
|
|
|
|
usbSerialString = usbSr.ReadToEnd().Trim();
|
|
|
|
|
usbSr.Close();
|
2015-12-31 16:12:22 +00:00
|
|
|
}
|
2017-12-21 06:06:19 +00:00
|
|
|
|
|
|
|
|
usb = true;
|
|
|
|
|
break;
|
2015-12-31 16:12:22 +00:00
|
|
|
}
|
2017-12-21 04:43:29 +00:00
|
|
|
}
|
2015-12-31 16:12:22 +00:00
|
|
|
}
|
2017-12-19 20:33:03 +00:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
break;
|
|
|
|
|
case Interop.PlatformID.Win32NT:
|
|
|
|
|
Windows.Usb.UsbDevice usbDevice = null;
|
2017-12-06 19:30:03 +00:00
|
|
|
|
2017-12-21 04:43:29 +00:00
|
|
|
// I have to search for USB disks, floppies and CD-ROMs as separate device types
|
|
|
|
|
foreach(string devGuid in new[]
|
|
|
|
|
{
|
|
|
|
|
Windows.Usb.GuidDevinterfaceFloppy, Windows.Usb.GuidDevinterfaceCdrom,
|
|
|
|
|
Windows.Usb.GuidDevinterfaceDisk
|
|
|
|
|
})
|
|
|
|
|
{
|
|
|
|
|
usbDevice = Windows.Usb.FindDrivePath(devicePath, devGuid);
|
|
|
|
|
if(usbDevice != null) break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(usbDevice != null)
|
|
|
|
|
{
|
|
|
|
|
usbDescriptors = usbDevice.BinaryDescriptors;
|
|
|
|
|
usbVendor = (ushort)usbDevice.DeviceDescriptor.idVendor;
|
|
|
|
|
usbProduct = (ushort)usbDevice.DeviceDescriptor.idProduct;
|
|
|
|
|
usbManufacturerString = usbDevice.Manufacturer;
|
|
|
|
|
usbProductString = usbDevice.Product;
|
|
|
|
|
usbSerialString =
|
|
|
|
|
usbDevice.SerialNumber; // This is incorrect filled by Windows with SCSI/ATA serial number
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default: usb = false;
|
|
|
|
|
break;
|
2015-12-31 16:12:22 +00:00
|
|
|
}
|
|
|
|
|
#endregion USB
|
|
|
|
|
|
2015-12-31 16:33:20 +00:00
|
|
|
#region FireWire
|
2017-12-20 17:15:26 +00:00
|
|
|
if(platformId == Interop.PlatformID.Linux)
|
2015-12-31 16:33:20 +00:00
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
if(devicePath.StartsWith("/dev/sd", StringComparison.Ordinal) ||
|
|
|
|
|
devicePath.StartsWith("/dev/sr", StringComparison.Ordinal) ||
|
|
|
|
|
devicePath.StartsWith("/dev/st", StringComparison.Ordinal))
|
2015-12-31 16:33:20 +00:00
|
|
|
{
|
|
|
|
|
string devPath = devicePath.Substring(5);
|
|
|
|
|
if(System.IO.Directory.Exists("/sys/block/" + devPath))
|
|
|
|
|
{
|
|
|
|
|
string resolvedLink = Linux.Command.ReadLink("/sys/block/" + devPath);
|
|
|
|
|
resolvedLink = "/sys" + resolvedLink.Substring(2);
|
|
|
|
|
if(!string.IsNullOrEmpty(resolvedLink))
|
|
|
|
|
while(resolvedLink.Contains("firewire"))
|
|
|
|
|
{
|
|
|
|
|
resolvedLink = System.IO.Path.GetDirectoryName(resolvedLink);
|
2017-12-21 06:06:19 +00:00
|
|
|
if(!System.IO.File.Exists(resolvedLink + "/model") ||
|
|
|
|
|
!System.IO.File.Exists(resolvedLink + "/vendor") ||
|
|
|
|
|
!System.IO.File.Exists(resolvedLink + "/guid")) continue;
|
|
|
|
|
|
|
|
|
|
System.IO.StreamReader fwSr;
|
|
|
|
|
string fwTemp;
|
|
|
|
|
|
|
|
|
|
fwSr = new System.IO.StreamReader(resolvedLink + "/model");
|
|
|
|
|
fwTemp = fwSr.ReadToEnd();
|
|
|
|
|
uint.TryParse(fwTemp, System.Globalization.NumberStyles.HexNumber,
|
|
|
|
|
System.Globalization.CultureInfo.InvariantCulture, out firewireModel);
|
|
|
|
|
fwSr.Close();
|
|
|
|
|
|
|
|
|
|
fwSr = new System.IO.StreamReader(resolvedLink + "/vendor");
|
|
|
|
|
fwTemp = fwSr.ReadToEnd();
|
|
|
|
|
uint.TryParse(fwTemp, System.Globalization.NumberStyles.HexNumber,
|
|
|
|
|
System.Globalization.CultureInfo.InvariantCulture,
|
|
|
|
|
out firewireVendor);
|
|
|
|
|
fwSr.Close();
|
|
|
|
|
|
|
|
|
|
fwSr = new System.IO.StreamReader(resolvedLink + "/guid");
|
|
|
|
|
fwTemp = fwSr.ReadToEnd();
|
|
|
|
|
ulong.TryParse(fwTemp, System.Globalization.NumberStyles.HexNumber,
|
|
|
|
|
System.Globalization.CultureInfo.InvariantCulture, out firewireGuid);
|
|
|
|
|
fwSr.Close();
|
|
|
|
|
|
|
|
|
|
if(System.IO.File.Exists(resolvedLink + "/model_name"))
|
2015-12-31 16:33:20 +00:00
|
|
|
{
|
2017-12-21 06:06:19 +00:00
|
|
|
fwSr = new System.IO.StreamReader(resolvedLink + "/model_name");
|
|
|
|
|
firewireModelName = fwSr.ReadToEnd().Trim();
|
2015-12-31 16:33:20 +00:00
|
|
|
fwSr.Close();
|
2017-12-21 06:06:19 +00:00
|
|
|
}
|
2015-12-31 16:33:20 +00:00
|
|
|
|
2017-12-21 06:06:19 +00:00
|
|
|
if(System.IO.File.Exists(resolvedLink + "/vendor_name"))
|
|
|
|
|
{
|
|
|
|
|
fwSr = new System.IO.StreamReader(resolvedLink + "/vendor_name");
|
|
|
|
|
firewireVendorName = fwSr.ReadToEnd().Trim();
|
2015-12-31 16:33:20 +00:00
|
|
|
fwSr.Close();
|
|
|
|
|
}
|
2017-12-21 06:06:19 +00:00
|
|
|
|
|
|
|
|
firewire = true;
|
|
|
|
|
break;
|
2015-12-31 16:33:20 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// TODO: Implement for other operating systems
|
2017-12-19 20:33:03 +00:00
|
|
|
else firewire = false;
|
2015-12-31 16:33:20 +00:00
|
|
|
#endregion FireWire
|
|
|
|
|
|
2016-10-17 04:41:27 +01:00
|
|
|
#region PCMCIA
|
2017-12-20 17:15:26 +00:00
|
|
|
if(platformId == Interop.PlatformID.Linux)
|
2016-10-17 04:41:27 +01:00
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
if(devicePath.StartsWith("/dev/sd", StringComparison.Ordinal) ||
|
|
|
|
|
devicePath.StartsWith("/dev/sr", StringComparison.Ordinal) ||
|
|
|
|
|
devicePath.StartsWith("/dev/st", StringComparison.Ordinal))
|
2016-10-17 04:41:27 +01:00
|
|
|
{
|
|
|
|
|
string devPath = devicePath.Substring(5);
|
|
|
|
|
if(System.IO.Directory.Exists("/sys/block/" + devPath))
|
|
|
|
|
{
|
|
|
|
|
string resolvedLink = Linux.Command.ReadLink("/sys/block/" + devPath);
|
|
|
|
|
resolvedLink = "/sys" + resolvedLink.Substring(2);
|
|
|
|
|
if(!string.IsNullOrEmpty(resolvedLink))
|
|
|
|
|
while(resolvedLink.Contains("/sys/devices"))
|
|
|
|
|
{
|
|
|
|
|
resolvedLink = System.IO.Path.GetDirectoryName(resolvedLink);
|
2017-12-21 06:06:19 +00:00
|
|
|
if(!System.IO.Directory.Exists(resolvedLink + "/pcmcia_socket")) continue;
|
2016-10-17 04:41:27 +01:00
|
|
|
|
2017-12-21 06:06:19 +00:00
|
|
|
string[] subdirs =
|
|
|
|
|
System.IO.Directory.GetDirectories(resolvedLink + "/pcmcia_socket",
|
|
|
|
|
"pcmcia_socket*",
|
|
|
|
|
System.IO.SearchOption.TopDirectoryOnly);
|
|
|
|
|
|
|
|
|
|
if(subdirs.Length <= 0) continue;
|
|
|
|
|
|
|
|
|
|
string possibleDir =
|
|
|
|
|
System.IO.Path.Combine(resolvedLink, "pcmcia_socket", subdirs[0]);
|
|
|
|
|
if(!System.IO.File.Exists(possibleDir + "/card_type") ||
|
|
|
|
|
!System.IO.File.Exists(possibleDir + "/cis")) continue;
|
|
|
|
|
|
|
|
|
|
System.IO.FileStream cisFs;
|
|
|
|
|
|
|
|
|
|
cisFs = new System.IO.FileStream(possibleDir + "/cis",
|
|
|
|
|
System.IO.FileMode.Open,
|
|
|
|
|
System.IO.FileAccess.Read);
|
|
|
|
|
byte[] cisBuf = new byte[65536];
|
|
|
|
|
int cisCount = cisFs.Read(cisBuf, 0, 65536);
|
|
|
|
|
cis = new byte[cisCount];
|
|
|
|
|
Array.Copy(cisBuf, 0, cis, 0, cisCount);
|
|
|
|
|
cisFs.Close();
|
|
|
|
|
|
|
|
|
|
pcmcia = true;
|
|
|
|
|
break;
|
2016-10-17 04:41:27 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// TODO: Implement for other operating systems
|
2017-12-19 20:33:03 +00:00
|
|
|
else pcmcia = false;
|
2016-10-17 04:41:27 +01:00
|
|
|
#endregion PCMCIA
|
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
if(!scsiSense)
|
2015-11-05 06:50:02 +00:00
|
|
|
{
|
2017-12-20 17:15:26 +00:00
|
|
|
Decoders.SCSI.Inquiry.SCSIInquiry? inquiry = Decoders.SCSI.Inquiry.Decode(inqBuf);
|
2015-10-19 05:11:28 +01:00
|
|
|
|
2015-11-05 06:50:02 +00:00
|
|
|
type = DeviceType.SCSI;
|
* commandline:
* DiscImageChef.Settings/Settings.cs:
* DiscImageChef.Settings/docs/README.txt:
* DiscImageChef.Settings/packages.config:
* DiscImageChef.Settings/docs/LICENSE.txt:
* DiscImageChef.Settings/docs/ChangeLog.txt:
* DiscImageChef.Settings/docs/mono/index.xml:
* DiscImageChef.Settings/docs/html/index.html:
* DiscImageChef.Settings/Properties/AssemblyInfo.cs:
* DiscImageChef.Settings/DiscImageChef.Settings.csproj:
* DiscImageChef.Settings/docs/mono/ns-Claunia.PropertyList.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/UID.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/UID.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSSet.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/index.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSSet.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSDate.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSData.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSDate.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSData.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSArray.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSNumber.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSString.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSObject.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSArray.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSNumber.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSString.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSObject.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSDictionary.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSDictionary.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/PropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/PropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/XmlPropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/XmlPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/ASCIIPropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/ASCIIPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/BinaryPropertyListParser.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/BinaryPropertyListWriter.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/BinaryPropertyListWriter.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/BinaryPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/PropertyListFormatException.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/PropertyListFormatException.html:
Added supports for settings
* DiscImageChef/Commands/Configure.cs:
Added support for settings.
* DiscImageChef/Core/Statistics.cs:
* DiscImageChef/Commands/Verify.cs:
* DiscImageChef/Commands/Entropy.cs:
* DiscImageChef/Commands/Formats.cs:
* DiscImageChef/Commands/PrintHex.cs:
* DiscImageChef/Commands/MediaInfo.cs:
* DiscImageChef/Commands/Statistics.cs:
Added statistics.
* DiscImageChef.Decoders/SCSI/Inquiry.cs:
Corrected bug on inquiry decoding.
* DiscImageChef.Decoders/SCSI/Modes.cs:
Corrected bug on decoding mode page 2Ah without write
performance descriptors.
Corrected bug when there is a vendor page 0 in mode sense
decoding.
* DiscImageChef.Devices/Device/Constructor.cs:
Corrected detecting USB or FireWire attached CD/DVD/BD and
tape drives.
Try ATA identify on USB or FireWire that don't have SCSI
INQUIRY.
* DiscImageChef.DiscImages/CDRWin.cs:
Corrected CD-ROM XA vs CD-ROM detection.
* DiscImageChef.Partitions/AppleMap.cs:
Corrected big endian working.
Added debug output.
* DiscImageChef.sln:
Added supports for settings.
* DiscImageChef/Commands/Decode.cs:
* DiscImageChef/Commands/Analyze.cs:
* DiscImageChef/Commands/Compare.cs:
* DiscImageChef/Commands/Checksum.cs:
* DiscImageChef/Commands/Benchmark.cs:
* DiscImageChef/Commands/DeviceInfo.cs:
* DiscImageChef/Commands/CreateSidecar.cs:
Added statistics.
* DiscImageChef/Commands/DeviceReport.cs:
Added statistics.
Correct handling empty inquiry string fields.
Suppose it is not removable, til proved wrong.
Corrected MODE SENSE (6/10) detection and calling order.
If device is MMC type but reports neither mode page 2Ah
neither GET CONFIGURATION, try all CDs (old drives work like
that).
Try reading Lead-In and Lead-Out in Audio CD using Audio READ
CD commands.
Corrected READ LONG information handling, some drives return
2s-complement in 32 bit. Upper 16 bits are ignored.
Added support for DVD raw block (37856 bytes).
Check READ LONG up to 36 times the cooked block size. That
should be enough to detect huge blocked media (like DVD and
BD) without taking ages.
If READ LONG size had to be bruteforced, and debug is
activated, save the result.
* DiscImageChef/Commands/DumpMedia.cs:
Added statistics.
Corrected READ LONG information handling, some drives return
2s-complement in 32 bit. Upper 16 bits are ignored.
Start trying with 64 blocks at a time. Some drives report to
be able to read 255 at a time, but they really don't, they
take a lot longer to read.
* DiscImageChef/Commands/MediaScan.cs:
Added statistics.
Start trying with 64 blocks at a time. Some drives report to
be able to read 255 at a time, but they really don't, they
take a lot longer to read.
* DiscImageChef/DiscImageChef.csproj:
Added support for settings.
Added statistics.
* DiscImageChef/Main.cs:
* DiscImageChef/Options.cs:
Added support for settings.
Added statistics.
2016-02-03 18:58:11 +00:00
|
|
|
bool serialSense = ScsiInquiry(out inqBuf, out senseBuf, 0x80);
|
2017-12-19 20:33:03 +00:00
|
|
|
if(!serialSense) serial = Decoders.SCSI.EVPD.DecodePage80(inqBuf);
|
2016-04-19 02:11:47 +01:00
|
|
|
|
2017-12-20 17:15:26 +00:00
|
|
|
if(inquiry.HasValue)
|
2015-11-05 06:50:02 +00:00
|
|
|
{
|
2017-12-20 17:15:26 +00:00
|
|
|
string tmp = StringHandlers.CToString(inquiry.Value.ProductRevisionLevel);
|
2017-12-19 20:33:03 +00:00
|
|
|
if(tmp != null) revision = tmp.Trim();
|
2017-12-20 17:15:26 +00:00
|
|
|
tmp = StringHandlers.CToString(inquiry.Value.ProductIdentification);
|
2017-12-19 20:33:03 +00:00
|
|
|
if(tmp != null) model = tmp.Trim();
|
2017-12-20 17:15:26 +00:00
|
|
|
tmp = StringHandlers.CToString(inquiry.Value.VendorIdentification);
|
2017-12-19 20:33:03 +00:00
|
|
|
if(tmp != null) manufacturer = tmp.Trim();
|
2017-12-20 17:15:26 +00:00
|
|
|
removable = inquiry.Value.RMB;
|
2015-10-19 05:20:42 +01:00
|
|
|
|
2017-12-20 17:15:26 +00:00
|
|
|
scsiType = (Decoders.SCSI.PeripheralDeviceTypes)inquiry.Value.PeripheralDeviceType;
|
2015-10-19 05:11:28 +01:00
|
|
|
}
|
2015-11-05 06:50:02 +00:00
|
|
|
|
* commandline:
* DiscImageChef.Settings/Settings.cs:
* DiscImageChef.Settings/docs/README.txt:
* DiscImageChef.Settings/packages.config:
* DiscImageChef.Settings/docs/LICENSE.txt:
* DiscImageChef.Settings/docs/ChangeLog.txt:
* DiscImageChef.Settings/docs/mono/index.xml:
* DiscImageChef.Settings/docs/html/index.html:
* DiscImageChef.Settings/Properties/AssemblyInfo.cs:
* DiscImageChef.Settings/DiscImageChef.Settings.csproj:
* DiscImageChef.Settings/docs/mono/ns-Claunia.PropertyList.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/UID.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/UID.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSSet.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/index.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSSet.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSDate.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSData.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSDate.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSData.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSArray.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSNumber.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSString.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSObject.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSArray.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSNumber.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSString.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSObject.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSDictionary.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSDictionary.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/PropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/PropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/XmlPropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/XmlPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/ASCIIPropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/ASCIIPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/BinaryPropertyListParser.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/BinaryPropertyListWriter.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/BinaryPropertyListWriter.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/BinaryPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/PropertyListFormatException.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/PropertyListFormatException.html:
Added supports for settings
* DiscImageChef/Commands/Configure.cs:
Added support for settings.
* DiscImageChef/Core/Statistics.cs:
* DiscImageChef/Commands/Verify.cs:
* DiscImageChef/Commands/Entropy.cs:
* DiscImageChef/Commands/Formats.cs:
* DiscImageChef/Commands/PrintHex.cs:
* DiscImageChef/Commands/MediaInfo.cs:
* DiscImageChef/Commands/Statistics.cs:
Added statistics.
* DiscImageChef.Decoders/SCSI/Inquiry.cs:
Corrected bug on inquiry decoding.
* DiscImageChef.Decoders/SCSI/Modes.cs:
Corrected bug on decoding mode page 2Ah without write
performance descriptors.
Corrected bug when there is a vendor page 0 in mode sense
decoding.
* DiscImageChef.Devices/Device/Constructor.cs:
Corrected detecting USB or FireWire attached CD/DVD/BD and
tape drives.
Try ATA identify on USB or FireWire that don't have SCSI
INQUIRY.
* DiscImageChef.DiscImages/CDRWin.cs:
Corrected CD-ROM XA vs CD-ROM detection.
* DiscImageChef.Partitions/AppleMap.cs:
Corrected big endian working.
Added debug output.
* DiscImageChef.sln:
Added supports for settings.
* DiscImageChef/Commands/Decode.cs:
* DiscImageChef/Commands/Analyze.cs:
* DiscImageChef/Commands/Compare.cs:
* DiscImageChef/Commands/Checksum.cs:
* DiscImageChef/Commands/Benchmark.cs:
* DiscImageChef/Commands/DeviceInfo.cs:
* DiscImageChef/Commands/CreateSidecar.cs:
Added statistics.
* DiscImageChef/Commands/DeviceReport.cs:
Added statistics.
Correct handling empty inquiry string fields.
Suppose it is not removable, til proved wrong.
Corrected MODE SENSE (6/10) detection and calling order.
If device is MMC type but reports neither mode page 2Ah
neither GET CONFIGURATION, try all CDs (old drives work like
that).
Try reading Lead-In and Lead-Out in Audio CD using Audio READ
CD commands.
Corrected READ LONG information handling, some drives return
2s-complement in 32 bit. Upper 16 bits are ignored.
Added support for DVD raw block (37856 bytes).
Check READ LONG up to 36 times the cooked block size. That
should be enough to detect huge blocked media (like DVD and
BD) without taking ages.
If READ LONG size had to be bruteforced, and debug is
activated, save the result.
* DiscImageChef/Commands/DumpMedia.cs:
Added statistics.
Corrected READ LONG information handling, some drives return
2s-complement in 32 bit. Upper 16 bits are ignored.
Start trying with 64 blocks at a time. Some drives report to
be able to read 255 at a time, but they really don't, they
take a lot longer to read.
* DiscImageChef/Commands/MediaScan.cs:
Added statistics.
Start trying with 64 blocks at a time. Some drives report to
be able to read 255 at a time, but they really don't, they
take a lot longer to read.
* DiscImageChef/DiscImageChef.csproj:
Added support for settings.
Added statistics.
* DiscImageChef/Main.cs:
* DiscImageChef/Options.cs:
Added support for settings.
Added statistics.
2016-02-03 18:58:11 +00:00
|
|
|
bool atapiSense = AtapiIdentify(out ataBuf, out errorRegisters);
|
2015-10-19 05:11:28 +01:00
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
if(!atapiSense)
|
2015-10-19 05:11:28 +01:00
|
|
|
{
|
|
|
|
|
type = DeviceType.ATAPI;
|
2017-12-20 17:15:26 +00:00
|
|
|
Identify.IdentifyDevice? ataId = Identify.Decode(ataBuf);
|
2015-10-19 05:11:28 +01:00
|
|
|
|
2017-12-20 17:15:26 +00:00
|
|
|
if(ataId.HasValue) serial = ataId.Value.SerialNumber;
|
2015-10-19 05:11:28 +01:00
|
|
|
}
|
2017-09-06 20:46:56 +01:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
lastError = 0;
|
|
|
|
|
error = false;
|
|
|
|
|
}
|
2015-11-05 06:50:02 +00:00
|
|
|
}
|
2015-10-19 05:11:28 +01:00
|
|
|
|
2017-12-20 17:26:28 +00:00
|
|
|
if(scsiSense && (usb || firewire) || manufacturer == "ATA")
|
2015-11-05 06:50:02 +00:00
|
|
|
{
|
* commandline:
* DiscImageChef.Settings/Settings.cs:
* DiscImageChef.Settings/docs/README.txt:
* DiscImageChef.Settings/packages.config:
* DiscImageChef.Settings/docs/LICENSE.txt:
* DiscImageChef.Settings/docs/ChangeLog.txt:
* DiscImageChef.Settings/docs/mono/index.xml:
* DiscImageChef.Settings/docs/html/index.html:
* DiscImageChef.Settings/Properties/AssemblyInfo.cs:
* DiscImageChef.Settings/DiscImageChef.Settings.csproj:
* DiscImageChef.Settings/docs/mono/ns-Claunia.PropertyList.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/UID.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/UID.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSSet.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/index.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSSet.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSDate.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSData.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSDate.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSData.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSArray.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSNumber.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSString.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSObject.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSArray.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSNumber.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSString.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSObject.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/NSDictionary.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/NSDictionary.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/PropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/PropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/XmlPropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/XmlPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/ASCIIPropertyListParser.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/ASCIIPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/BinaryPropertyListParser.xml:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/BinaryPropertyListWriter.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/BinaryPropertyListWriter.html:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/BinaryPropertyListParser.html:
* DiscImageChef.Settings/docs/mono/Claunia.PropertyList/PropertyListFormatException.xml:
* DiscImageChef.Settings/docs/html/Claunia.PropertyList/PropertyListFormatException.html:
Added supports for settings
* DiscImageChef/Commands/Configure.cs:
Added support for settings.
* DiscImageChef/Core/Statistics.cs:
* DiscImageChef/Commands/Verify.cs:
* DiscImageChef/Commands/Entropy.cs:
* DiscImageChef/Commands/Formats.cs:
* DiscImageChef/Commands/PrintHex.cs:
* DiscImageChef/Commands/MediaInfo.cs:
* DiscImageChef/Commands/Statistics.cs:
Added statistics.
* DiscImageChef.Decoders/SCSI/Inquiry.cs:
Corrected bug on inquiry decoding.
* DiscImageChef.Decoders/SCSI/Modes.cs:
Corrected bug on decoding mode page 2Ah without write
performance descriptors.
Corrected bug when there is a vendor page 0 in mode sense
decoding.
* DiscImageChef.Devices/Device/Constructor.cs:
Corrected detecting USB or FireWire attached CD/DVD/BD and
tape drives.
Try ATA identify on USB or FireWire that don't have SCSI
INQUIRY.
* DiscImageChef.DiscImages/CDRWin.cs:
Corrected CD-ROM XA vs CD-ROM detection.
* DiscImageChef.Partitions/AppleMap.cs:
Corrected big endian working.
Added debug output.
* DiscImageChef.sln:
Added supports for settings.
* DiscImageChef/Commands/Decode.cs:
* DiscImageChef/Commands/Analyze.cs:
* DiscImageChef/Commands/Compare.cs:
* DiscImageChef/Commands/Checksum.cs:
* DiscImageChef/Commands/Benchmark.cs:
* DiscImageChef/Commands/DeviceInfo.cs:
* DiscImageChef/Commands/CreateSidecar.cs:
Added statistics.
* DiscImageChef/Commands/DeviceReport.cs:
Added statistics.
Correct handling empty inquiry string fields.
Suppose it is not removable, til proved wrong.
Corrected MODE SENSE (6/10) detection and calling order.
If device is MMC type but reports neither mode page 2Ah
neither GET CONFIGURATION, try all CDs (old drives work like
that).
Try reading Lead-In and Lead-Out in Audio CD using Audio READ
CD commands.
Corrected READ LONG information handling, some drives return
2s-complement in 32 bit. Upper 16 bits are ignored.
Added support for DVD raw block (37856 bytes).
Check READ LONG up to 36 times the cooked block size. That
should be enough to detect huge blocked media (like DVD and
BD) without taking ages.
If READ LONG size had to be bruteforced, and debug is
activated, save the result.
* DiscImageChef/Commands/DumpMedia.cs:
Added statistics.
Corrected READ LONG information handling, some drives return
2s-complement in 32 bit. Upper 16 bits are ignored.
Start trying with 64 blocks at a time. Some drives report to
be able to read 255 at a time, but they really don't, they
take a lot longer to read.
* DiscImageChef/Commands/MediaScan.cs:
Added statistics.
Start trying with 64 blocks at a time. Some drives report to
be able to read 255 at a time, but they really don't, they
take a lot longer to read.
* DiscImageChef/DiscImageChef.csproj:
Added support for settings.
Added statistics.
* DiscImageChef/Main.cs:
* DiscImageChef/Options.cs:
Added support for settings.
Added statistics.
2016-02-03 18:58:11 +00:00
|
|
|
bool ataSense = AtaIdentify(out ataBuf, out errorRegisters);
|
2016-04-19 02:11:47 +01:00
|
|
|
if(!ataSense)
|
2015-10-19 05:11:28 +01:00
|
|
|
{
|
2015-11-05 06:50:02 +00:00
|
|
|
type = DeviceType.ATA;
|
2017-12-20 17:15:26 +00:00
|
|
|
Identify.IdentifyDevice? ataid = Identify.Decode(ataBuf);
|
2015-10-19 05:11:28 +01:00
|
|
|
|
2017-12-20 17:15:26 +00:00
|
|
|
if(ataid.HasValue)
|
2015-10-19 05:11:28 +01:00
|
|
|
{
|
2017-12-20 17:15:26 +00:00
|
|
|
string[] separated = ataid.Value.Model.Split(' ');
|
2015-10-19 05:11:28 +01:00
|
|
|
|
2017-12-19 20:33:03 +00:00
|
|
|
if(separated.Length == 1) model = separated[0];
|
2015-11-05 06:50:02 +00:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
manufacturer = separated[0];
|
|
|
|
|
model = separated[separated.Length - 1];
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-20 17:15:26 +00:00
|
|
|
revision = ataid.Value.FirmwareRevision;
|
|
|
|
|
serial = ataid.Value.SerialNumber;
|
2015-10-19 05:20:42 +01:00
|
|
|
|
2015-11-05 06:50:02 +00:00
|
|
|
scsiType = Decoders.SCSI.PeripheralDeviceTypes.DirectAccess;
|
2015-12-30 11:45:27 +00:00
|
|
|
|
2017-12-20 17:15:26 +00:00
|
|
|
if((ushort)ataid.Value.GeneralConfiguration != 0x848A)
|
2017-12-19 20:33:03 +00:00
|
|
|
removable |=
|
2017-12-20 17:15:26 +00:00
|
|
|
(ataid.Value.GeneralConfiguration & Identify.GeneralConfigurationBit.Removable) ==
|
2017-12-19 20:33:03 +00:00
|
|
|
Identify.GeneralConfigurationBit.Removable;
|
|
|
|
|
else compactFlash = true;
|
2015-10-19 05:11:28 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
if(type == DeviceType.Unknown)
|
2015-10-19 05:11:28 +01:00
|
|
|
{
|
|
|
|
|
manufacturer = null;
|
|
|
|
|
model = null;
|
|
|
|
|
revision = null;
|
|
|
|
|
serial = null;
|
|
|
|
|
}
|
2015-12-31 16:12:22 +00:00
|
|
|
|
2016-04-19 02:11:47 +01:00
|
|
|
if(usb)
|
2015-12-31 16:12:22 +00:00
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
if(string.IsNullOrEmpty(manufacturer)) manufacturer = usbManufacturerString;
|
|
|
|
|
if(string.IsNullOrEmpty(model)) model = usbProductString;
|
|
|
|
|
if(string.IsNullOrEmpty(serial)) serial = usbSerialString;
|
2017-12-21 07:08:26 +00:00
|
|
|
else foreach(char c in serial.Where(c => char.IsControl(c))) serial = usbSerialString;
|
2015-12-31 16:12:22 +00:00
|
|
|
}
|
2015-12-31 16:33:20 +00:00
|
|
|
|
2017-12-21 06:06:19 +00:00
|
|
|
if(!firewire) return;
|
|
|
|
|
|
|
|
|
|
if(string.IsNullOrEmpty(manufacturer)) manufacturer = firewireVendorName;
|
|
|
|
|
if(string.IsNullOrEmpty(model)) model = firewireModelName;
|
|
|
|
|
if(string.IsNullOrEmpty(serial)) serial = string.Format("{0:X16}", firewireGuid);
|
2017-12-21 07:08:26 +00:00
|
|
|
else foreach(char c in serial.Where(c => char.IsControl(c))) serial = string.Format("{0:X16}", firewireGuid);
|
2015-10-12 19:55:00 +01:00
|
|
|
}
|
2017-09-28 19:14:50 +00:00
|
|
|
|
2017-12-20 17:15:26 +00:00
|
|
|
static int ConvertFromHexAscii(string file, out byte[] outBuf)
|
2017-09-28 19:14:50 +00:00
|
|
|
{
|
|
|
|
|
System.IO.StreamReader sr = new System.IO.StreamReader(file);
|
|
|
|
|
string ins = sr.ReadToEnd().Trim();
|
|
|
|
|
outBuf = new byte[ins.Length / 2];
|
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
for(int i = 0; i < ins.Length; i += 2)
|
2017-09-28 19:14:50 +00:00
|
|
|
{
|
2017-12-19 20:33:03 +00:00
|
|
|
outBuf[i / 2] = Convert.ToByte(ins.Substring(i, 2), 16);
|
2017-09-28 19:14:50 +00:00
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-12-19 20:33:03 +00:00
|
|
|
catch { count = 0; }
|
2017-09-28 19:14:50 +00:00
|
|
|
|
|
|
|
|
sr.Close();
|
|
|
|
|
return count;
|
|
|
|
|
}
|
2015-10-12 19:55:00 +01:00
|
|
|
}
|
2017-12-19 20:33:03 +00:00
|
|
|
}
|