Initial checkin

This commit is contained in:
chudov
2008-11-26 18:57:40 +00:00
parent 0cb204d2bc
commit 16cbf58dd4
56 changed files with 12266 additions and 0 deletions

View File

@@ -0,0 +1,112 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{B75FA7AD-968E-4990-B342-1B4B17C850DF}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Bwg.Hardware</RootNamespace>
<AssemblyName>Bwg.Hardware</AssemblyName>
<SccProjectName>
</SccProjectName>
<SccLocalPath>
</SccLocalPath>
<SccAuxPath>
</SccAuxPath>
<SccProvider>
</SccProvider>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>2.0</OldToolsVersion>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\Bwg.Hardware.XML</DocumentationFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DocumentationFile>bin\Debug\Bwg.Hardware.XML</DocumentationFile>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DocumentationFile>bin\Debug\Bwg.Hardware.XML</DocumentationFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="HardwareDevice.cs" />
<Compile Include="HardwareManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,209 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Hardware
{
/// <summary>
/// This class represents a hardware device as extracted from the registry.
/// </summary>
public class HardwareDevice
{
#region private member variables
private string m_name;
private string m_desc;
private string m_class;
private Guid m_class_guid;
private string m_key_name ;
private string m_location;
private string[] m_hardware;
#endregion
#region constructor
/// <summary>
/// The constructor for a device.
/// </summary>
/// <param name="key">the name of the registry key that contains info about this device</param>
public HardwareDevice(string key)
{
m_key_name = key;
m_name = string.Empty ;
m_desc = string.Empty ;
m_location = string.Empty;
m_hardware = new string[0];
}
#endregion
#region public methods
/// <summary>
/// Add a new hardware address to the device
/// </summary>
/// <param name="addr">the new address to add to the device</param>
public void AddHardware(string addr)
{
int count = m_hardware.GetLength(0);
Array.Resize(ref m_hardware, count + 1);
m_hardware[count] = addr;
}
#endregion
#region public properties
/// <summary>
/// The name of the key where this information was extracted
/// </summary>
public string KeyName
{
get { return m_key_name; }
}
/// <summary>
/// This property is the (friendly) name of the device
/// </summary>
public string Name
{
get
{
if (m_name != string.Empty)
return m_name;
if (m_desc != string.Empty)
return m_desc;
return m_key_name;
}
set
{
m_name = value;
}
}
/// <summary>
/// This property is the description of the device
/// </summary>
public string Description
{
get
{
return m_desc;
}
set
{
m_desc = value;
}
}
/// <summary>
/// This property is the class that the device belong to
/// </summary>
public string Class
{
get
{
return m_class;
}
set
{
m_class = value;
}
}
/// <summary>
/// This property is the GUID for the class that the device belongs to
/// </summary>
public Guid ClassGUID
{
get
{
return m_class_guid;
}
set
{
m_class_guid = value;
}
}
/// <summary>
/// This property is the location of the device
/// </summary>
public string Location
{
get { return m_location; }
set { m_location = value; }
}
/// <summary>
/// This class is the hardware addresses assocaited with the device
/// </summary>
public string[] Hardware
{
get
{
return m_hardware;
}
}
/// <summary>
/// This property returns true if the device is an IDE device
/// </summary>
public bool IsIde
{
get
{
return HardwareStartsWith("IDE");
}
}
/// <summary>
/// This property returns true if this is a USB device
/// </summary>
public bool IsUsb
{
get
{
return HardwareStartsWith("USB") ;
}
}
/// <summary>
/// This property returns true if this is a Firewire device
/// </summary>
public bool IsFirewire
{
get
{
return HardwareStartsWith("SBP2");
}
}
/// <summary>
/// This property returns true if this is a SCSI device
/// </summary>
public bool IsScsi
{
get
{
return HardwareStartsWith("SCSI");
}
}
#endregion
#region private methods
/// <summary>
/// This method returns true if the hardware address start with the string given
/// </summary>
/// <param name="begin">the string to start with</param>
/// <returns>true if the string begins with the right value, otherwise false</returns>
public bool HardwareStartsWith(string begin)
{
foreach (string str in m_hardware)
{
if (str.StartsWith(begin))
return true;
}
return false;
}
#endregion
}
}

View File

@@ -0,0 +1,209 @@
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.IO;
using System.Security;
using Microsoft.Win32;
namespace Bwg.Hardware
{
/// <summary>
/// This class is the manager that reads the registry and determines which devices exist
/// </summary>
public class HardwareManager : IEnumerable<HardwareDevice>, IEnumerable
{
#region private member variables
private IList<HardwareDevice> m_devices;
#endregion
#region constructors
/// <summary>
/// The constructor for the device manager, creates a list for devices to be added.
/// </summary>
public HardwareManager()
{
m_devices = new List<HardwareDevice>();
}
#endregion
/// <summary>
/// Return an enumerator for iterating over all of the tracks on the
/// disk.
/// </summary>
/// <returns>iterator</returns>
public IEnumerator<HardwareDevice> GetEnumerator()
{
return m_devices.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return m_devices.GetEnumerator();
}
/// <summary>
/// Open a given machine, or the default machine if no machine is given
/// </summary>
/// <param name="keyname"></param>
/// <returns></returns>
public bool OpenMachine(string keyname)
{
if (keyname == string.Empty)
keyname = "System\\CurrentControlSet\\Enum";
RegistryKey key = Registry.LocalMachine.OpenSubKey(keyname);
if (key == null)
return false;
CheckForHardware(key);
key.Close();
return true;
}
/// <summary>
/// Find a specific device given its class, vendor, and product
/// </summary>
/// <param name="classname">the class of the device</param>
/// <param name="vendor">the vendor id of the device</param>
/// <param name="product">the product id of the device</param>
/// <returns></returns>
public HardwareDevice FindDevice(string classname, string vendor, string product)
{
foreach (HardwareDevice dev in m_devices)
{
if (dev.Class != classname)
continue;
if (dev.Name.Contains(vendor) && dev.Name.Contains(product))
{
if (dev.IsUsb && dev.Location.Length == 0)
dev.Location = FindUsbLocation(dev);
return dev;
}
}
return null;
}
#region private methods
private string FindUsbLocation(HardwareDevice cddev)
{
string result = string.Empty;
int index = cddev.KeyName.LastIndexOf('&');
if (index == -1)
return result;
string devname = cddev.KeyName.Substring(0, index);
foreach (HardwareDevice dev in m_devices)
{
if (dev.Class == "USB" && dev.KeyName == devname)
return dev.Location;
}
return result;
}
private static bool FindClassString(string s1)
{
return s1 == "Class";
}
private static bool FindClassGUIDString(string s1)
{
return s1 == "ClassGUID";
}
private void CreateDevice(RegistryKey key)
{
string keyname = key.ToString();
string onekey ;
HardwareDevice dev;
try
{
onekey = Path.GetFileName(keyname);
}
catch (ArgumentException)
{
return;
}
dev = new HardwareDevice(onekey);
object value;
value = key.GetValue("Class");
if (value != null)
{
if (value is string)
dev.Class = (string)value;
else if (value is string[])
{
dev.Class = ((string[])value)[0];
}
}
value = key.GetValue("ClassGUID");
if (value != null && value is string)
dev.ClassGUID = new Guid((string)value);
value = key.GetValue("DeviceDesc");
if (value != null && value is string)
dev.Description = (string)value;
value = key.GetValue("FriendlyName");
if (value != null && value is string)
dev.Name = (string)value;
value = key.GetValue("LocationInformation");
if (value != null && value is string)
dev.Location = (string)value;
value = key.GetValue("HardwareID");
if (value != null)
{
if (value is string)
dev.AddHardware((string)value);
else if (value is string[])
{
foreach (string str in (string[])value)
dev.AddHardware(str);
}
}
m_devices.Add(dev);
}
private void CheckForHardware(RegistryKey key)
{
string[] values = key.GetValueNames();
if (Array.Find(values, FindClassString) != null && Array.Find(values, FindClassGUIDString) != null)
{
// This is a device
CreateDevice(key);
}
else
{
values = key.GetSubKeyNames();
foreach (string str in values)
{
try
{
RegistryKey subkey = key.OpenSubKey(str);
if (subkey != null)
{
CheckForHardware(subkey);
subkey.Close();
}
}
catch (SecurityException)
{
}
}
}
}
#endregion
}
}

View File

@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Bwg.Hardware")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("BwgSoftware")]
[assembly: AssemblyProduct("BwgBurn")]
[assembly: AssemblyCopyright("Copyright © 2006 by Jack W. Griffin, Jr.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("de5dc145-3520-47ee-8988-205a142c6177")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.0.7.1")]
[assembly: AssemblyFileVersion("0.0.7.1")]

View File

@@ -0,0 +1,121 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Bwg.Logging</RootNamespace>
<AssemblyName>Bwg.Logging</AssemblyName>
<SccProjectName>
</SccProjectName>
<SccLocalPath>
</SccLocalPath>
<SccAuxPath>
</SccAuxPath>
<SccProvider>
</SccProvider>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>2.0</OldToolsVersion>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\Bwg.Logging.XML</DocumentationFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\Bwg.Logging.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DocumentationFile>bin\Debug\Bwg.Logging.XML</DocumentationFile>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<DocumentationFile>bin\Release\Bwg.Logging.XML</DocumentationFile>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DocumentationFile>bin\Debug\Bwg.Logging.XML</DocumentationFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<DocumentationFile>bin\Release\Bwg.Logging.XML</DocumentationFile>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ConsoleSink.cs" />
<Compile Include="FileSink.cs" />
<Compile Include="Logger.cs" />
<Compile Include="MemorySink.cs" />
<Compile Include="MessageAddedArgs.cs" />
<Compile Include="TeeSink.cs" />
<Compile Include="UserMessage.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Sink.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,47 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Logging
{
/// <summary>
/// A message sink class that writes messages to the console
/// </summary>
public class ConsoleSink : Sink
{
/// <summary>
/// Log the message to the console
/// </summary>
/// <param name="m">the message</param>
public override void LogMessage(UserMessage m)
{
if (m.Code == 0)
System.Console.WriteLine(m.MType.ToString() + ": " + m.Text);
else
System.Console.WriteLine(m.MType.ToString() + " " + m.Code.ToString() + ": " + m.Text);
}
}
}

67
Bwg.Logging/FileSink.cs Normal file
View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.IO ;
namespace Bwg.Logging
{
/// <summary>
/// This class is a message sink that writes the message to a file
/// </summary>
public class FileSink : Sink, IDisposable
{
#region private member variables
private TextWriter m_writer;
#endregion
#region constructor
/// <summary>
/// Create a new file sink given the name of the output file
/// </summary>
/// <param name="filename">the output file</param>
public FileSink(string filename)
{
try
{
m_writer = new StreamWriter(filename);
}
catch (Exception)
{
m_writer = null;
}
}
#endregion
#region public methods
/// <summary>
/// Dispose of the class, close the file
/// </summary>
public void Dispose()
{
Close();
}
/// <summary>
/// Close the file
/// </summary>
public void Close()
{
if (m_writer != null)
{
m_writer.Flush();
m_writer.Close();
}
}
/// <summary>
/// Log the message
/// </summary>
/// <param name="m">the message to log</param>
public override void LogMessage(UserMessage m)
{
if (m_writer != null)
m_writer.WriteLine(m.ToString());
}
#endregion
}
}

213
Bwg.Logging/Logger.cs Normal file
View File

@@ -0,0 +1,213 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace Bwg.Logging
{
/// <summary>
/// This class allows for the logging of messages
/// </summary>
public class Logger
{
/// <summary>
/// This is used to lock the logger when multiple threads are
/// trying to log messages concurrently
/// </summary>
private Object m_lock_object;
/// <summary>
/// This is a map from message type to sinks
/// </summary>
private IDictionary<UserMessage.Category, Sink> m_sinks;
/// <summary>
/// This is a map from the message type to the level that is being filtered. Anything
/// below the value found here is not displayed
/// </summary>
private IDictionary<UserMessage.Category, int> m_level;
/// <summary>
/// Create the logging object
/// </summary>
public Logger()
{
m_lock_object = new Object();
m_sinks = new Dictionary<UserMessage.Category, Sink>();
m_level = new Dictionary<UserMessage.Category, int>();
}
/// <summary>
/// Assocated a sink with a given type of message
/// </summary>
/// <param name="c">the category of message</param>
/// <param name="s">the sink for this category of message</param>
public void SetSink(UserMessage.Category c, Sink s)
{
lock (m_lock_object)
{
m_sinks[c] = s;
}
}
/// <summary>
/// Return the sink given the type of message
/// </summary>
/// <param name="c">the type of sink</param>
/// <returns>the sink associated with the message type</returns>
public Sink GetSink(UserMessage.Category c)
{
Sink s = null;
lock (m_lock_object)
{
m_sinks.TryGetValue(c, out s);
}
return s;
}
/// <summary>
/// Sets a level, below which messages are filtered
/// </summary>
/// <param name="c">the category to filter</param>
/// <param name="level">the level to display</param>
public void SetLevel(UserMessage.Category c, int level)
{
lock (m_lock_object)
{
m_level[c] = level;
}
}
/// <summary>
/// Given the category, this method returns the current
/// level for this type of message
/// </summary>
/// <param name="c">the type of message</param>
/// <returns>the current level</returns>
public int GetLevel(UserMessage.Category c)
{
int ret = 0;
lock (m_lock_object)
{
if (m_level.ContainsKey(c))
ret = m_level[c];
}
return ret;
}
/// <summary>
/// Remove the sink associated with a specific category of message.
/// </summary>
/// <param name="c">the category of message</param>
public void RemoveSink(UserMessage.Category c)
{
lock (m_lock_object)
{
m_sinks.Remove(c);
}
}
/// <summary>
/// This function returns TRUE if the logger has a message sink for the given
/// category of message. Otherwise it returns FALSE.
/// </summary>
/// <param name="c">the category of interest</param>
/// <returns>true if a sink is present, false otherwise</returns>
public bool HasSink(UserMessage.Category c)
{
return m_sinks.Keys.Contains(c);
}
/// <summary>
/// Log a message
/// </summary>
/// <param name="m">the message to log</param>
public void LogMessage(UserMessage m)
{
lock (m_lock_object)
{
if (m_sinks.ContainsKey(m.MType))
{
int level = 0;
if (m_level.ContainsKey(m.MType))
level = m_level[m.MType];
if (m.Level <= level)
{
Sink s = m_sinks[m.MType];
s.LogMessage(m);
}
}
}
}
/// <summary>
/// Dump a data buffer to the log file, used for debugging
/// </summary>
/// <param name="loglevel">the log level</param>
/// <param name="title">the title</param>
/// <param name="buffer">the buffer</param>
/// <param name="size">the buffer size</param>
public void DumpBuffer(uint loglevel, string title, IntPtr buffer, int size)
{
UserMessage m;
m = new UserMessage(UserMessage.Category.Debug, loglevel, "Dumping data for structure '" + title + "'");
LogMessage(m);
int index = 0;
int linebytes = 0;
string str = string.Empty;
while (index < size)
{
if (linebytes == 16)
{
m = new UserMessage(UserMessage.Category.Debug, loglevel, str);
LogMessage(m);
linebytes = 0;
str = string.Empty;
}
byte b = Marshal.ReadByte(buffer, index++);
str += b.ToString("X2") + " ";
linebytes++;
}
if (linebytes != 0)
{
m = new UserMessage(UserMessage.Category.Debug, loglevel, str);
LogMessage(m);
}
}
}
}

114
Bwg.Logging/MemorySink.cs Normal file
View File

@@ -0,0 +1,114 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Logging
{
/// <summary>
/// This class is a message sink that stores all of the messages
/// in a list.
/// </summary>
public class MemorySink : Sink
{
private Object m_lock;
private IList<UserMessage> m_list ;
/// <summary>
///
/// </summary>
public EventHandler<MessageAddedArgs> MessageAdded;
/// <summary>
///
/// </summary>
public MemorySink()
{
m_lock = new Object();
m_list = new List<UserMessage>();
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public int GetMessageCount()
{
int cnt;
lock (m_lock)
{
cnt = m_list.Count;
}
return cnt;
}
/// <summary>
///
/// </summary>
/// <param name="n"></param>
/// <returns></returns>
public UserMessage GetMessage(int n)
{
UserMessage m;
lock (m_lock)
{
m = m_list[n];
}
return m;
}
/// <summary>
///
/// </summary>
/// <param name="m"></param>
public override void LogMessage(UserMessage m)
{
lock (m_lock)
{
m_list.Add(m);
}
if (MessageAdded != null)
{
MessageAddedArgs args = new MessageAddedArgs(m);
MessageAdded(this, args);
}
}
/// <summary>
///
/// </summary>
public void Clear()
{
lock (m_lock)
{
m_list.Clear();
}
}
}
}

View File

@@ -0,0 +1,49 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Logging
{
/// <summary>
///
/// </summary>
public class MessageAddedArgs : EventArgs
{
/// <summary>
///
/// </summary>
public UserMessage AddedMessage;
/// <summary>
///
/// </summary>
/// <param name="m"></param>
public MessageAddedArgs(UserMessage m)
{
AddedMessage = m;
}
}
}

View File

@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Bwg.Logging")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("BwgSoftware")]
[assembly: AssemblyProduct("BwgBurn")]
[assembly: AssemblyCopyright("Copyright © 2006 by Jack W. Griffin, Jr.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("216f12e9-2978-457c-95d6-32b4b87a361d")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.0.7.1")]
[assembly: AssemblyFileVersion("0.0.7.1")]

43
Bwg.Logging/Sink.cs Normal file
View File

@@ -0,0 +1,43 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Logging
{
/// <summary>
/// An abstract class that provides a place to send messages meant for the
/// user. A class derived from this class is used to allow for GUI versus
/// console applications
/// </summary>
abstract public class Sink
{
/// <summary>
/// This method sends a message to a sink.
/// </summary>
/// <param name="m"></param>
abstract public void LogMessage(UserMessage m);
}
}

59
Bwg.Logging/TeeSink.cs Normal file
View File

@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Logging
{
/// <summary>
/// This class is a message sink that forwards a message to a set of receiving sinks
/// </summary>
public class TeeSink : Sink
{
#region private member variables
/// <summary>
/// The list of sinks to send the message to
/// </summary>
IList<Sink> m_sinks;
#endregion
#region constructor
/// <summary>
/// The constructor to creat the object
/// </summary>
public TeeSink()
{
m_sinks = new List<Sink>();
}
#endregion
#region public methods
/// <summary>
/// Add the sink to the list of receiving sinks
/// </summary>
/// <param name="s">the sink to add</param>
public void AddSink(Sink s)
{
m_sinks.Add(s);
}
/// <summary>
/// Remove the sink to the list of receiving sinks
/// </summary>
/// <param name="s"></param>
public void RemoveSink(Sink s)
{
m_sinks.Remove(s);
}
/// <summary>
/// Log a message to the receiving sinks
/// </summary>
/// <param name="m">the message</param>
public override void LogMessage(UserMessage m)
{
foreach (Sink s in m_sinks)
s.LogMessage(m);
}
#endregion
}
}

117
Bwg.Logging/UserMessage.cs Normal file
View File

@@ -0,0 +1,117 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Logging
{
/// <summary>
/// A message to be logged to the u
/// </summary>
public class UserMessage
{
#region Public Types
/// <summary>
/// Message types
/// </summary>
public enum Category
{
/// <summary>
/// An error occurred
/// </summary>
Error,
/// <summary>
/// A warning occurred
/// </summary>
Warning,
/// <summary>
/// Information about the process
/// </summary>
Info,
/// <summary>
/// Debugging information
/// </summary>
Debug
} ;
#endregion
#region Public Data Members
/// <summary>
/// The category for the message (error, warning, info, debug)
/// </summary>
public readonly Category MType ;
/// <summary>
/// The numeric error code
/// </summary>
public readonly uint Code ;
/// <summary>
/// The text for the error message
/// </summary>
public readonly string Text;
/// <summary>
/// The level for the message, used to filter out messages
/// </summary>
public readonly uint Level;
/// <summary>
/// This member contains a time stamp for the message
/// </summary>
public readonly DateTime When;
#endregion
#region constructor
/// <summary>
/// Constructor for a message
/// </summary>
/// <param name="t">Category of the message</param>
/// <param name="level">Level of the message</param>
/// <param name="s">Text of the message</param>
public UserMessage(Category t, uint level, string s)
{
MType = t;
Text = s;
Level = level;
When = DateTime.Now;
}
#endregion
#region public member functions
/// <summary>
/// This method converts a user message to a single string
/// </summary>
/// <returns>the string that represnts the message</returns>
public override string ToString()
{
return When.ToLongDateString() + " " + When.ToLongTimeString() + " : " + MType.ToString() + " : Level " + Level.ToString() + " : " + Text;
}
#endregion
}
}

150
Bwg.Scsi/AtipInfo.cs Normal file
View File

@@ -0,0 +1,150 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for DotNet
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace Bwg.Scsi
{
/// <summary>
/// This class represents the ATIP information read from the disk
/// </summary>
public class AtipInfo : Result
{
/// <summary>
/// The target write power for the disk
/// </summary>
public readonly byte IndicativeTargetWritingPower;
/// <summary>
///
/// </summary>
public readonly byte ReferenceSpeed;
/// <summary>
/// If true, this is a double density CD
/// </summary>
public readonly bool IsDDCD;
/// <summary>
/// If true, this disk is for unrestricted use
/// </summary>
public readonly bool UnrestrictedUse;
/// <summary>
/// If true, the media is CDRW, otherwise it is CDR
/// </summary>
public readonly bool MediaCDRW;
/// <summary>
/// The CD/RW media subtype
/// </summary>
public readonly byte MediaSubtype;
/// <summary>
///
/// </summary>
public readonly bool A1Valid;
/// <summary>
///
/// </summary>
public readonly bool A2Valid;
/// <summary>
///
/// </summary>
public readonly bool A3Valid;
/// <summary>
/// The ATIP value for the starting leadin time
/// </summary>
public readonly MinuteSecondFrame StartTimeOfLeadin;
/// <summary>
/// This is the address for the last possible leadout
/// </summary>
public readonly MinuteSecondFrame LastPossibleStartOfLeadout;
/// <summary>
/// The data from the A1 field
/// </summary>
public readonly byte[] A1Values;
/// <summary>
/// The data from the A1 field
/// </summary>
public readonly byte[] A2Values;
/// <summary>
/// The data from the A3 field
/// </summary>
public readonly byte[] A3Values;
/// <summary>
/// This constructs the ATIP infomation
/// </summary>
/// <param name="buffer"></param>
/// <param name="size"></param>
public AtipInfo(IntPtr buffer, int size) : base(buffer, size)
{
byte b;
if (size < 4)
return;
b = Get8(4);
IndicativeTargetWritingPower = (byte)((b >> 4) & 0x0f);
IsDDCD = GetBit(4, 3);
ReferenceSpeed = (byte)(b & 0x07);
b = Get8(5);
UnrestrictedUse = GetBit(5, 6);
b = Get8(6);
MediaCDRW = GetBit(6, 6);
MediaSubtype = (byte)((b >> 3) & 0x07);
A1Valid = GetBit(6, 2);
A2Valid = GetBit(6, 1);
A3Valid = GetBit(6, 0);
StartTimeOfLeadin = new MinuteSecondFrame(Get8(8), Get8(9), Get8(10));
LastPossibleStartOfLeadout = new MinuteSecondFrame(Get8(12), Get8(13), Get8(14));
A1Values = new byte[3];
for (int i = 0; i < 3; i++)
A1Values[i] = Get8(i + 16);
A2Values = new byte[3];
for (int i = 0; i < 3; i++)
A2Values[i] = Get8(i + 20);
A3Values = new byte[3];
for (int i = 0; i < 3; i++)
A3Values[i] = Get8(i + 24);
}
}
}

159
Bwg.Scsi/Bwg.Scsi.csproj Normal file
View File

@@ -0,0 +1,159 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Bwg.Scsi</RootNamespace>
<AssemblyName>Bwg.Scsi</AssemblyName>
<SccProjectName>
</SccProjectName>
<SccLocalPath>
</SccLocalPath>
<SccAuxPath>
</SccAuxPath>
<SccProvider>
</SccProvider>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>2.0</OldToolsVersion>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\Bwg.Scsi.XML</DocumentationFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\Bwg.Scsi.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\Bwg.Scsi.XML</DocumentationFile>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\Bwg.Scsi.XML</DocumentationFile>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\Bwg.Scsi.XML</DocumentationFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\Bwg.Scsi.XML</DocumentationFile>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AtipInfo.cs" />
<Compile Include="CapacityDescriptor.cs" />
<Compile Include="Command.cs" />
<Compile Include="Defs.cs" />
<Compile Include="Device.cs" />
<Compile Include="DeviceInfo.cs" />
<Compile Include="DeviceManager.cs" />
<Compile Include="DeviceManagerRescanArgs.cs" />
<Compile Include="DiskInformation.cs" />
<Compile Include="EventStatusNotification.cs" />
<Compile Include="Feature.cs" />
<Compile Include="FeatureList.cs" />
<None Include="FileReader.cs" />
<Compile Include="FormatParameterList.cs" />
<Compile Include="HeaderData.cs" />
<Compile Include="InitializationPattern.cs" />
<Compile Include="InquiryResult.cs" />
<Compile Include="MinuteSecondFrame.cs" />
<Compile Include="ModePage.cs" />
<Compile Include="ModeTable.cs" />
<Compile Include="OpcTableEntry.cs" />
<Compile Include="Performance.cs" />
<Compile Include="PerformanceList.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Result.cs" />
<Compile Include="SpeedDescriptor.cs" />
<Compile Include="SpeedDescriptorList.cs" />
<Compile Include="SubheaderData.cs" />
<Compile Include="TocEntry.cs" />
<Compile Include="TrackInformation.cs" />
<Compile Include="WinDev.cs" />
<Compile Include="WriteBuffer.cs" />
<Compile Include="WriteBufferPool.cs" />
<Compile Include="WriteBufferStream.cs" />
<Compile Include="WriteParameterModePage.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Bwg.Logging\Bwg.Logging.csproj">
<Project>{F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}</Project>
<Name>Bwg.Logging</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,109 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for DotNet
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Scsi
{
/// <summary>
///
/// </summary>
public class CapacityDescriptor : Result
{
#region public types
/// <summary>
///
/// </summary>
public enum DescriptorType : byte
{
/// <summary>
///
/// </summary>
Reserved = 0,
/// <summary>
///
/// </summary>
Unformatted = 1,
/// <summary>
///
/// </summary>
Formatted = 2,
/// <summary>
///
/// </summary>
NoMedia = 3
} ;
#endregion
#region public variables
/// <summary>
/// The number of blocks on this media.
/// </summary>
public readonly uint NumberOfBlocks;
/// <summary>
/// This length of a single block for this capacity
/// </summary>
public readonly uint BlockLength;
/// <summary>
/// This is the descriptor type, see the SCSI-3 MMC specification
/// </summary>
public readonly DescriptorType DescType;
/// <summary>
/// This is the type of format for the capacity descriptor, see the SCSI-3 MMC spec
/// </summary>
public readonly byte FormatType;
#endregion
#region constructor
/// <summary>
///
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="size"></param>
public CapacityDescriptor(IntPtr buffer, int offset, int size)
: base(buffer, size)
{
byte b;
NumberOfBlocks = Get32(offset);
b = Get8(offset + 4);
DescType = (DescriptorType)(b & 0x03);
FormatType = (byte)(b >> 2);
BlockLength = Get24(offset + 5);
}
#endregion
}
}

236
Bwg.Scsi/Command.cs Normal file
View File

@@ -0,0 +1,236 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for DotNet
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace Bwg.Scsi
{
class Command : IDisposable
{
[DllImport("ntdll.dll")]
internal static extern void RtlZeroMemory(IntPtr dest, int size);
public enum CmdDirection
{
In,
Out,
None
} ;
/// <summary>
/// The data buffer for the SCSI command
/// </summary>
private int m_buffer_size;
private IntPtr m_buffer;
private bool m_delete_buffer;
/// <summary>
/// The CDB buffer for the command. This gets copied into the SCSI_PASS_THROUGH_DIRECT
/// structure when this command is sent to the SCSI target.
/// </summary>
private byte[] m_cdb;
/// <summary>
/// The direction of data transfer via the m_buffer field above
/// </summary>
private CmdDirection m_dir;
/// <summary>
/// The amount of time to pass in seconds before a timeout
/// </summary>
private int m_timeout;
public Command(ScsiCommandCode code, byte cdbsize, int bufsize, CmdDirection dir, int timeout)
{
Debug.Assert(bufsize < UInt16.MaxValue);
m_cdb = new byte[cdbsize];
m_cdb[0] = (byte)code;
m_buffer_size = bufsize;
if (bufsize == 0)
m_buffer = IntPtr.Zero;
else
{
m_delete_buffer = true;
m_buffer = Marshal.AllocHGlobal(bufsize);
RtlZeroMemory(m_buffer, bufsize);
}
m_dir = dir;
m_timeout = timeout;
}
public Command(ScsiCommandCode code, byte cdbsize, IntPtr buffer, int bufsize, CmdDirection dir, int timeout)
{
m_cdb = new byte[cdbsize];
m_cdb[0] = (byte)code;
m_buffer_size = bufsize;
if (bufsize == 0)
m_buffer = IntPtr.Zero;
else
{
m_delete_buffer = false;
m_buffer = buffer;
}
m_dir = dir;
m_timeout = timeout;
}
public int TimeOut
{
get
{
return m_timeout;
}
}
public ushort GetCDBLength()
{
return (ushort)m_cdb.GetLength(0);
}
public CmdDirection Direction { get { return m_dir; } }
public int BufferSize { get { return m_buffer_size; } }
public IntPtr GetBuffer() { return m_buffer ; }
public byte GetCDB(byte addr) { return m_cdb[addr] ; }
public void SetCDB8(byte addr, byte value)
{
m_cdb[addr] = value;
}
public void SetCDB16(byte addr, ushort value)
{
m_cdb[addr] = (byte)((value >> 8) & 0xff);
m_cdb[addr + 1] = (byte)(value & 0xff);
}
public void SetCDB24(byte addr, uint value)
{
m_cdb[addr] = (byte)((value >> 16) & 0xff);
m_cdb[addr + 1] = (byte)((value >> 8) & 0xff);
m_cdb[addr + 2] = (byte)(value & 0xff);
}
public void SetCDB24(byte addr, int value)
{
m_cdb[addr] = (byte)((value >> 16) & 0xff);
m_cdb[addr + 1] = (byte)((value >> 8) & 0xff);
m_cdb[addr + 2] = (byte)(value & 0xff);
}
public void SetCDB32(byte addr, uint value)
{
m_cdb[addr] = (byte)((value >> 24) & 0xff);
m_cdb[addr + 1] = (byte)((value >> 16) & 0xff);
m_cdb[addr + 2] = (byte)((value >> 8) & 0xff);
m_cdb[addr + 3] = (byte)(value & 0xff);
}
public void SetCDB32(byte addr, int value)
{
m_cdb[addr] = (byte)((value >> 24) & 0xff);
m_cdb[addr + 1] = (byte)((value >> 16) & 0xff);
m_cdb[addr + 2] = (byte)((value >> 8) & 0xff);
m_cdb[addr + 3] = (byte)(value & 0xff);
}
public void SetBuffer8(ushort addr, byte value)
{
Marshal.WriteByte(m_buffer, addr, value);
}
public void SetBuffer16(ushort addr, ushort value)
{
Marshal.WriteByte(m_buffer, addr + 0, (byte)((value >> 8) & 0xff));
Marshal.WriteByte(m_buffer, addr + 1, (byte)((value >> 0) & 0xff));
}
public void SetBuffer24(ushort addr, uint value)
{
Marshal.WriteByte(m_buffer, addr + 0, (byte)((value >> 16) & 0xff));
Marshal.WriteByte(m_buffer, addr + 1, (byte)((value >> 8) & 0xff));
Marshal.WriteByte(m_buffer, addr + 2, (byte)((value >> 0) & 0xff));
}
public void SetBuffer32(ushort addr, uint value)
{
Marshal.WriteByte(m_buffer, addr + 0, (byte)((value >> 24) & 0xff));
Marshal.WriteByte(m_buffer, addr + 1, (byte)((value >> 16) & 0xff));
Marshal.WriteByte(m_buffer, addr + 2, (byte)((value >> 8) & 0xff));
Marshal.WriteByte(m_buffer, addr + 3, (byte)((value >> 0) & 0xff));
}
public byte GetBuffer8(ushort addr)
{
return Marshal.ReadByte(m_buffer, addr);
}
public ushort GetBuffer16(ushort addr)
{
ushort v = 0;
v |= (ushort)(Marshal.ReadByte(m_buffer, addr) << 8);
v |= (ushort)(Marshal.ReadByte(m_buffer, addr + 1) << 0);
return v;
}
public uint GetBuffer24(ushort addr)
{
uint v = 0;
v |= (uint)(Marshal.ReadByte(m_buffer, addr) << 16);
v |= (uint)(Marshal.ReadByte(m_buffer, addr + 1) << 8);
v |= (uint)(Marshal.ReadByte(m_buffer, addr + 2) << 0);
return v;
}
public uint GetBuffer32(ushort addr)
{
uint v = 0;
v |= (uint)(Marshal.ReadByte(m_buffer, addr + 0) << 24);
v |= (uint)(Marshal.ReadByte(m_buffer, addr + 1) << 16);
v |= (uint)(Marshal.ReadByte(m_buffer, addr + 2) << 8);
v |= (uint)(Marshal.ReadByte(m_buffer, addr + 3) << 0);
return v;
}
public void Dispose()
{
if (m_buffer_size > 0 && m_delete_buffer)
Marshal.FreeHGlobal(m_buffer);
m_cdb = null;
}
}
}

81
Bwg.Scsi/Defs.cs Normal file
View File

@@ -0,0 +1,81 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for DotNet
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
namespace Bwg.Scsi
{
enum ScsiCommandCode
{
TestUnitReady = 0x00,
RequestSense = 0x03,
FormatUnit = 0x04,
Inquiry = 0x12,
StartStopUnit = 0x1B,
PreventAllowMediumRemoval = 0x1E,
ReadFormatCapacities = 0x23,
ReadCapacity = 0x25,
Read = 0x28,
Seek = 0x2B,
Write = 0x2A,
Erase = 0x2C,
WriteAndVerify = 0x2E,
Verify = 0x2F,
SyncronizeCache = 0x35,
WriteBuffer = 0x3B,
ReadBuffer = 0x3C,
ReadSubChannel = 0x42,
ReadTocPmaAtip = 0x43,
PlayAudio10 = 0x45,
GetConfiguration = 0x46,
PlayAudioMSF = 0x47,
GetEventStatusNotification = 0x4A,
PauseResume = 0x4B,
StopPlayScan = 0x4E,
ReadDiskInformation = 0x51,
ReadTrackInformation = 0x52,
ReserveTrack = 0x53,
SendOpcInformation = 0x54,
ModeSelect = 0x55,
RepairTrack = 0x58,
ModeSense = 0x5A,
CloseTrackSession = 0x5B,
ReadBufferCapacity = 0x5C,
SendCueSheet = 0x5D,
Blank = 0xA1,
SendKey = 0xA3,
ReportKey = 0xA4,
PlayAudio12 = 0xA5,
LoadUnloadMedium = 0xA6,
SetReadAhead = 0xA7,
Read12 = 0xA8,
Write12 = 0xAA,
GetPerformance = 0xAC,
ReadDvdStructure = 0xAD,
SetStreaming = 0xB6,
ReadCdMSF = 0xB9,
Scan = 0xBA,
SetCdSpeed = 0xBB,
MechanismStatus = 0xBD,
ReadCd = 0xBE,
SendDvdStructure = 0xBF
} ;
}

3686
Bwg.Scsi/Device.cs Normal file

File diff suppressed because it is too large Load Diff

160
Bwg.Scsi/DeviceInfo.cs Normal file
View File

@@ -0,0 +1,160 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Scsi
{
/// <summary>
/// This class contains information about a burner device that is useful to have
/// even when the device it not open
/// </summary>
public class DeviceInfo
{
#region private member variables
/// <summary>
/// The device name for the device
/// </summary>
private string m_device_name;
/// <summary>
/// The device latter for the device
/// </summary>
private string m_device_letter;
/// <summary>
/// The result of an inquiry
/// </summary>
private InquiryResult m_inqury_result;
#endregion
#region static private member variables
/// <summary>
/// The list of devices found and created. For each device only a single DeviceInfo object
/// will ever be created and this list holds the objects created to date
/// </summary>
private static IList<DeviceInfo> m_devices = new List<DeviceInfo>();
#endregion
#region constructor
/// <summary>
/// Create a new device info object given the device name and drive letter for the device
/// </summary>
/// <param name="name">the device name</param>
/// <param name="letter">the drive letter</param>
private DeviceInfo(string name, string letter)
{
m_device_name = name;
m_device_letter = letter;
}
#endregion
#region public properties
/// <summary>
/// This property returns the drive letter associated with the device
/// </summary>
public string DeviceLetter
{
get { return m_device_letter; }
}
/// <summary>
/// This property returns the NT device name associated with the device
/// </summary>
public string DeviceName
{
get { return m_device_name; }
}
/// <summary>
/// This property returns a short description of the drive including drive letter
/// and NT device name.
/// </summary>
public string ShortDesc
{
get { return m_device_letter + " ( " + m_device_name + " )"; }
}
/// <summary>
/// This property return a long description of the drive including the drive letter,
/// NT device name, vendor ID and product ID.
/// </summary>
public string LongDesc
{
get
{
string result = m_device_letter + " ";
// result += " ( " + m_device_name + " ) ";
result += "[" + m_inqury_result.VendorIdentification + " " +
m_inqury_result.ProductIdentification + " " +
m_inqury_result.FirmwareVersion + "]";
return result;
}
}
/// <summary>
/// This property returns the inquiry data from the inquiry request
/// </summary>
public InquiryResult InquiryData
{
get { return m_inqury_result; }
}
#endregion
#region public methods
/// <summary>
/// This method returns a string representation of this object
/// </summary>
/// <returns>string representatation of the object</returns>
public override string ToString()
{
return m_device_letter + " (" + m_inqury_result.VendorIdentification.Trim() + " " + m_inqury_result.ProductIdentification.Trim() + ")";
}
/// <summary>
/// Extract the information we want to keep around after we close the device.
/// </summary>
/// <param name="dev">the open device we are going to query</param>
/// <returns>true if we got the info, false otherwise</returns>
public bool ExtractInfo(Device dev)
{
if (dev.Inquiry(out m_inqury_result) != Device.CommandStatus.Success)
return false;
if (!m_inqury_result.Valid)
return false;
if (m_inqury_result.PeripheralQualifier != 0)
return false;
if (m_inqury_result.PeripheralDeviceType != Device.MMCDeviceType)
return false;
return true;
}
#endregion
#region public static methods
/// <summary>
/// This method returns or creates a unique device info structure based on the name and the
/// drive letter for a given drive.
/// </summary>
/// <param name="name">the NT name of the drive</param>
/// <param name="letter">the drive letter for the drive</param>
/// <returns>the single DeviceInfo object that represents this drive</returns>
public static DeviceInfo CreateDevice(string name, string letter)
{
foreach (DeviceInfo info in m_devices)
{
if (info.DeviceName == name && info.DeviceLetter == letter)
return info;
}
DeviceInfo newdev = new DeviceInfo(name, letter);
m_devices.Add(newdev);
return newdev;
}
#endregion
}
}

228
Bwg.Scsi/DeviceManager.cs Normal file
View File

@@ -0,0 +1,228 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices ;
using System.IO;
using Bwg.Logging;
namespace Bwg.Scsi
{
/// <summary>
/// This class manages the burner devices that are in the system.
/// </summary>
public unsafe class DeviceManager
{
#region external functions
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern uint QueryDosDevice(string name, IntPtr buffer, uint size);
#endregion
#region private member variables
/// <summary>
/// The logger for logging messages
/// </summary>
private Logger m_logger;
/// <summary>
/// This list contains the device names found in the system
/// </summary>
private IList<DeviceInfo> m_devices_found;
#endregion
#region constructor
/// <summary>
/// This constructor creates a new device manager object.
/// </summary>
/// <param name="l">the logger to use for logging messages</param>
public DeviceManager(Logger l)
{
m_logger = l;
m_devices_found = new List<DeviceInfo>();
}
#endregion
#region public variables
/// <summary>
/// This event is fired just before a rescan of the devices in the system.
/// </summary>
public EventHandler<DeviceManagerRescanArgs> BeforeScan;
/// <summary>
/// This event is triggered just after a rescan of devices in the system.
/// </summary>
public EventHandler<DeviceManagerRescanArgs> AfterScan;
#endregion
#region public properties
/// <summary>
/// This property returns the list of devices found as a result of the most recent
/// scan.
/// </summary>
public IList<DeviceInfo> DevicesFound
{
get { return m_devices_found; }
}
/// <summary>
/// This property returns the logger assocaited with the device manager
/// </summary>
public Logger MyLogger
{
get { return m_logger; }
}
#endregion
#region public methods
/// <summary>
/// This method scans the current machine for all CDROM devices found in the system.
/// </summary>
public void ScanForDevices()
{
if (BeforeScan != null)
{
DeviceManagerRescanArgs args = new DeviceManagerRescanArgs();
BeforeScan(this, args);
}
m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 0, "Scanning for devices ... ")) ;
OperatingSystem os = Environment.OSVersion;
m_logger.LogMessage(new UserMessage(UserMessage.Category.Info, 0, "Operating System: " + os.ToString()));
m_logger.LogMessage(new UserMessage(UserMessage.Category.Info, 0, "Platform: " + os.Platform.ToString()));
int ossize = 32 ;
if (IntPtr.Size == 8)
ossize = 64 ;
m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 0, "OS Word Size: " + ossize.ToString())) ;
m_devices_found.Clear();
for (int i = 0; i < 100; i++)
{
uint dlev = (uint)((i > 5) ? 9 : 8);
string name = "\\\\.\\CDROM" + i.ToString();
m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, dlev, "Checking device " + name + " ... "));
Device dev = new Device(m_logger) ;
if (!dev.Open(name))
{
m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, dlev, " ... device open failed"));
continue ;
}
string letter = GetLetterFromDeviceName(name);
DeviceInfo info = DeviceInfo.CreateDevice(name, letter);
if (!info.ExtractInfo(dev))
{
m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, dlev, " ... cannot extract inquiry information from the drive"));
string str = "The drive '" + letter + "' (" + name + ") is a CD/DVD driver, but is not a valid MMC device.";
m_logger.LogMessage(new UserMessage(UserMessage.Category.Error, 0, str));
str = "This drive is not supported by BwgBurn and is probably an older device.";
m_logger.LogMessage(new UserMessage(UserMessage.Category.Error, 0, str));
continue;
}
m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, dlev, " ... device added to device list"));
m_devices_found.Add(info) ;
dev.Close() ;
}
if (AfterScan != null)
{
DeviceManagerRescanArgs args = new DeviceManagerRescanArgs();
AfterScan(this, args);
}
string devlist = string.Empty;
foreach (DeviceInfo info in m_devices_found)
{
if (devlist.Length > 0)
devlist += ", ";
devlist += info.ShortDesc;
}
m_logger.LogMessage(new UserMessage(UserMessage.Category.Debug, 0, "Found devices ... " + devlist));
foreach (DeviceInfo info in m_devices_found)
{
UserMessage m = new UserMessage(UserMessage.Category.Debug, 6, "Found Device: " + info.DeviceLetter) ;
m_logger.LogMessage(m);
m = new UserMessage(UserMessage.Category.Debug, 6, " NT Name = " + info.DeviceName);
m_logger.LogMessage(m);
m = new UserMessage(UserMessage.Category.Debug, 6, " Vendor = " + info.InquiryData.VendorIdentification.Trim());
m_logger.LogMessage(m);
m = new UserMessage(UserMessage.Category.Debug, 6, " Product = " + info.InquiryData.ProductIdentification.Trim());
m_logger.LogMessage(m);
m = new UserMessage(UserMessage.Category.Debug, 6, " Revision = " + info.InquiryData.ProductRevision.Trim());
m_logger.LogMessage(m);
}
}
#endregion
#region private methods
private static string GetNtDeviceNameForDrive(string name)
{
string result;
const int buflen = 512;
uint ret;
byte[] buffer = new byte[buflen];
if (name.EndsWith("\\"))
name = name.Substring(0, name.Length - 1);
IntPtr ptr = Marshal.AllocHGlobal(buflen);
{
ret = QueryDosDevice(name, ptr, buflen / 2);
Marshal.Copy(ptr, buffer, 0, buflen);
int totallen = buflen;
for (int i = 0; i < buflen - 2; i++)
{
if (buffer[i] == 0 && buffer[i + 1] == 0)
{
totallen = i + 1;
break;
}
}
result = Encoding.Unicode.GetString(buffer, 0, totallen);
}
return result;
}
/// <summary>
/// Return the drive letter for a drive given its NT name
/// </summary>
/// <param name="devname">the NT name</param>
/// <returns>the drive letter</returns>
public static string GetLetterFromDeviceName(string devname)
{
if (devname.StartsWith("\\\\.\\"))
devname = devname.Substring(4);
foreach (DriveInfo info in DriveInfo.GetDrives())
{
if (info.DriveType == DriveType.CDRom)
{
string ntname = GetNtDeviceNameForDrive(info.Name);
if (ntname.StartsWith("\\Device\\"))
ntname = ntname.Substring(8);
if (ntname.ToLower() == devname.ToLower())
return info.Name;
}
}
return string.Empty;
}
#endregion
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Scsi
{
/// <summary>
/// This class represents the arguments to the scan event in the
/// device manager.
/// </summary>
public class DeviceManagerRescanArgs : EventArgs
{
}
}

409
Bwg.Scsi/DiskInformation.cs Normal file
View File

@@ -0,0 +1,409 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for DotNet
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace Bwg.Scsi
{
/// <summary>
/// This class contains the results of the ReadDiskInformation SCSI command
/// </summary>
public class DiskInformation : Result
{
#region Public types
/// <summary>
/// Type defining the state of the last session on the disk
/// </summary>
public enum SessionStateType
{
/// <summary>
/// The session is empty
/// </summary>
EmptySession = 0,
/// <summary>
/// The session is incomplete
/// </summary>
IncompleteSession = 1,
/// <summary>
/// The session is damaged
/// </summary>
DamagedSession = 2,
/// <summary>
/// The session is complete
/// </summary>
CompleteSession = 3
} ;
/// <summary>
/// Type defining the status of the disk
/// </summary>
public enum DiskStatusType
{
/// <summary>
/// The disk is empty
/// </summary>
EmptyDisk = 0,
/// <summary>
/// The disk is incomplete
/// </summary>
IncompleteDisk = 1,
/// <summary>
/// The disk is finalized
/// </summary>
FinalizedDisk = 2,
/// <summary>
/// The disk is in an other state which is dependent on the media type
/// </summary>
RandomlyRecordable = 3
} ;
/// <summary>
/// The state of a background format
/// </summary>
public enum BackgroundFormatStatusType
{
/// <summary>
/// No background format was started, or it does not apply
/// </summary>
NotStartedOrDoesNotApply = 0,
/// <summary>
/// A background format was started, did not complete, and is not running
/// </summary>
StartedButNotRunning = 1,
/// <summary>
/// A background format is in progress and is not complete
/// </summary>
InProgress = 2,
/// <summary>
/// A background format was started and is complete
/// </summary>
Complete = 3
} ;
#endregion
#region Public Data Members
private readonly bool m_erasable;
/// <summary>
/// If true, the disk is erasable. If false the disk cannot be erased
/// </summary>
public bool Erasable
{
get { return m_erasable; }
}
private readonly SessionStateType m_session_state;
/// <summary>
/// The state of the last session on the disk
/// </summary>
public SessionStateType SessionState
{
get { return m_session_state; }
}
private readonly DiskStatusType m_disk_status;
/// <summary>
/// The status of the disk
/// </summary>
public DiskStatusType DiskStatus
{
get { return m_disk_status; }
}
private readonly byte m_first_track;
/// <summary>
/// Number of the first track on the disk
/// </summary>
public byte FirstTrack
{
get { return m_first_track; }
}
private readonly ushort m_session_count;
/// <summary>
/// Number of sessions on the disk
/// </summary>
public ushort SessionCount
{
get { return m_session_count; }
}
private readonly ushort m_first_track_in_last_session;
/// <summary>
/// The first track number in the last session
/// </summary>
public ushort FirstTrackInLastSession
{
get { return m_first_track_in_last_session; }
}
private readonly ushort m_last_track_in_last_session;
/// <summary>
/// The last track number in the last session
/// </summary>
public ushort LastTrackInLastSession
{
get { return m_last_track_in_last_session; }
}
private readonly bool m_disk_id_valid;
/// <summary>
/// If true, the disk ID was valid
/// </summary>
public bool DiskIdValid
{
get { return m_disk_id_valid; }
}
private readonly uint m_disk_identification;
/// <summary>
/// The four byte disk id
/// </summary>
public uint DiskIdentification
{
get { return m_disk_identification; }
}
private readonly bool m_disk_bar_code_valid;
/// <summary>
/// If true, the disk bar code was valid
/// </summary>
public bool DiskBarCodeValid
{
get { return m_disk_bar_code_valid; }
}
private readonly byte[] m_disk_bar_code;
/// <summary>
/// The eight byte disk bar code
/// </summary>
public byte[] DiskBarCode
{
get { return m_disk_bar_code; }
}
private readonly bool m_unrestricted_disk_use;
/// <summary>
/// If true, this disk is unrestriced it its use
/// </summary>
public bool UnrestrictedDiskUse
{
get { return m_unrestricted_disk_use; }
}
private readonly bool m_disk_application_code_valid;
/// <summary>
/// If true, the disk application code is valid
/// </summary>
public bool DiskApplicationCodeValid
{
get { return m_disk_application_code_valid; }
}
private readonly byte m_disk_application_code;
/// <summary>
/// The disk application code
/// </summary>
public byte DiskApplicationCode
{
get { return m_disk_application_code; }
}
private readonly bool m_dirty_bit;
/// <summary>
/// The Dbit (dirty bit) for MRW media
/// </summary>
public bool DirtyBit
{
get { return m_dirty_bit; }
}
private readonly BackgroundFormatStatusType m_background_format_status;
/// <summary>
/// The status of a background format
/// </summary>
public BackgroundFormatStatusType BackgroundFormatStatus
{
get { return m_background_format_status; }
}
private readonly MinuteSecondFrame m_last_session_lead_in_start_address;
/// <summary>
/// The last session leadin start address, media dependent, see SCSI-3 MMC spec
/// </summary>
public MinuteSecondFrame LastSessionLeadInStartAddress
{
get { return m_last_session_lead_in_start_address; }
}
private readonly MinuteSecondFrame m_last_possible_leadout_start_address;
/// <summary>
/// The last possible leadout start address, media dependent, see SCSI-3 MMC spec
/// </summary>
public MinuteSecondFrame LastPossibleLeadoutStartAddress
{
get { return m_last_possible_leadout_start_address; }
}
/// <summary>
/// The OPC table
/// </summary>
public IList<OpcTableEntry> OpcTable;
#endregion
#region constructor
/// <summary>
/// The constructor for the DiskInformation class. It parses the information from the
/// memory buffer that contains the raw SCSI result.
/// </summary>
/// <param name="buffer">The buffer containing the raw SCSI result</param>
/// <param name="size">The size of the raw SCSI result buffer</param>
public DiskInformation(IntPtr buffer, int size) : base(buffer, size)
{
ushort len = Get16(0);
byte b = Get8(2);
if ((b & 0x10) != 0)
m_erasable = true;
else
m_erasable = false;
m_session_state = (SessionStateType)((b >> 2) & 0x03);
m_disk_status = (DiskStatusType)(b & 0x03);
m_first_track = Get8(3);
m_session_count = (ushort)(Get8(4) | (Get8(9) << 8));
m_first_track_in_last_session = (ushort)(Get8(5) | (Get8(10) << 8));
m_last_track_in_last_session = (ushort)(Get8(6) | (Get8(11) << 8));
b = Get8(7);
if ((b & 0x80) != 0)
{
m_disk_id_valid = true;
m_disk_identification = Get32(12);
}
else
m_disk_id_valid = false;
if ((b & 0x40) != 0)
{
m_disk_bar_code_valid = true;
m_disk_bar_code = new byte[8];
for (int i = 24; i <= 31; i++)
m_disk_bar_code[i - 24] = Get8(i);
}
else
{
m_disk_bar_code_valid = false;
m_disk_bar_code = null;
}
if ((b & 0x20) != 0)
m_unrestricted_disk_use = true;
else
m_unrestricted_disk_use = false;
if ((b & 0x10) != 0)
{
m_disk_application_code_valid = true;
m_disk_application_code = Get8(32);
}
else
m_disk_application_code_valid = false;
if ((b & 0x04) != 0)
m_dirty_bit = true;
else
m_dirty_bit = false;
m_background_format_status = (BackgroundFormatStatusType)(b & 0x03);
m_last_session_lead_in_start_address = new MinuteSecondFrame(Get8(16) * 60 + Get8(17), Get8(18), Get8(19));
m_last_possible_leadout_start_address = new MinuteSecondFrame(Get8(20) * 60 + Get8(21), Get8(22), Get8(23));
OpcTable = new List<OpcTableEntry>();
if (BufferSize > 33)
{
byte cnt = Get8(33);
int offset = 34;
for(byte i = 0 ; i < cnt && offset < BufferSize ; i++)
{
OpcTableEntry entry = new OpcTableEntry(Buffer, BufferSize, offset);
OpcTable.Add(entry);
offset += 8;
}
}
}
#endregion
}
}

View File

@@ -0,0 +1,171 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for DotNet
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace Bwg.Scsi
{
/// <summary>
/// This class contains information about event status communicated from the device
/// via the GetEventStatusNotification SCSI command.
/// </summary>
public class EventStatusNotification : Result
{
#region public types
/// <summary>
/// This field indicates the type of event
/// </summary>
public enum EventType
{
/// <summary>
/// No event was returned
/// </summary>
NoEvent = 0x00,
/// <summary>
/// There was an operation change
/// </summary>
OperationalChange = 0x01,
/// <summary>
/// There was a change in power management status
/// </summary>
PowerManagement = 0x02,
/// <summary>
/// There was an external request to the device
/// </summary>
ExternalRequest = 0x03,
/// <summary>
/// The status of the media has changed
/// </summary>
Media = 0x04,
/// <summary>
/// There was a change in the multiple initiator device
/// </summary>
MultipleInitiator = 0x05,
/// <summary>
/// There was a change in the busy state of the device
/// </summary>
DeviceBusy = 0x06,
/// <summary>
/// This value is reserved and should not be returned
/// </summary>
Reserved = 0x07,
} ;
#endregion
#region public member variables
/// <summary>
/// This property returns true if an event is available
/// </summary>
public readonly bool EventAvailable;
/// <summary>
/// This property is a byte that contains a mask of the supported event classes
/// </summary>
public readonly byte SupportedEventClasses;
/// <summary>
/// This property contains the notification class of the specific event that has
/// occurred.
/// </summary>
public readonly EventType NotificationClass;
/// <summary>
/// This array contains the specific data returned describing the event. The format of this
/// data is described in the SCSI-3 MMC specification.
/// </summary>
public readonly byte [] EventData;
#endregion
#region constructor
/// <summary>
/// This is the contructor for this class which contains information about any events that
/// have occurred in the SCSI device.
/// </summary>
/// <param name="buffer">Pointer to a memory area containing the reply from the SCSI device</param>
/// <param name="size">The size of the memory area containing the reply from the SCSI device</param>
public EventStatusNotification(IntPtr buffer, int size) : base(buffer, size)
{
SupportedEventClasses = Marshal.ReadByte(buffer, 3);
byte b = Marshal.ReadByte(buffer, 2);
if ((b & 0x80) != 0)
{
EventAvailable = false;
}
else
{
ushort len = Get16(0);
EventAvailable = true;
NotificationClass = (EventType)(b & 0x03);
EventData = new byte[len];
for (int i = 0; i < len; i++)
EventData[i] = Marshal.ReadByte(buffer, 4 + i);
}
}
#endregion
#region public properties
/// <summary>
/// This property returns true if Operational Events are supported on this device
/// </summary>
public bool OperationalChangeEventsSupported { get { return (SupportedEventClasses & 0x02) != 0; } }
/// <summary>
/// This property returns true if Power Management Events are supported on this device
/// </summary>
public bool PowerManagementEventsSupported { get { return (SupportedEventClasses & 0x04) != 0; } }
/// <summary>
/// This property returns true if External Request Events are supported on this device
/// </summary>
public bool ExternalRequestEventsSupported { get { return (SupportedEventClasses & 0x08) != 0; } }
/// <summary>
/// This property returns true if Media Events are supported on this device
/// </summary>
public bool MediaEventsSupported { get { return (SupportedEventClasses & 0x10) != 0; } }
/// <summary>
/// This property returns true if Multiple Initiator Events are supported on this device
/// </summary>
public bool MultiInitiatorEventsSupported { get { return (SupportedEventClasses & 0x20) != 0; } }
/// <summary>
/// This property returns true if Device Busy Events are supported on this device
/// </summary>
public bool DeviceBusyEventsSupported { get { return (SupportedEventClasses & 0x40) != 0; } }
#endregion
}
}

438
Bwg.Scsi/Feature.cs Normal file
View File

@@ -0,0 +1,438 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Scsi
{
/// <summary>
/// This class describes a single SCSI feature. The data associated with the feature is
/// stored as a series of bytes that must be interpreted by the calling code.
/// </summary>
public class Feature : Result
{
#region Feature Numbers
/// <summary>
/// This enumerated type indicates the type of the feature.
/// </summary>
public enum FeatureType : ushort
{
/// <summary>
/// The ProfileList feature (see the SCSI-3 MMC specification)
/// </summary>
ProfileList = 0x0000,
/// <summary>
/// The Core feature (see the SCSI-3 MMC specification)
/// </summary>
Core = 0x0001,
/// <summary>
/// The Morphing feature (see the SCSI-3 MMC specification)
/// </summary>
Morphing = 0x0002,
/// <summary>
/// The RemovableMedia feature (see the SCSI-3 MMC specification)
/// </summary>
RemovableMedia = 0x0003,
/// <summary>
/// The WriteProtect feature (see the SCSI-3 MMC specification)
/// </summary>
WriteProtect = 0x0004,
/// <summary>
/// The RandomReadable feature (see the SCSI-3 MMC specification)
/// </summary>
RandomReadable = 0x0010,
/// <summary>
/// The MultiRead feature (see the SCSI-3 MMC specification)
/// </summary>
MultiRead = 0x001d,
/// <summary>
/// The CDRead feature (see the SCSI-3 MMC specification)
/// </summary>
CDRead = 0x001e,
/// <summary>
/// The DVDRead feature (see the SCSI-3 MMC specification)
/// </summary>
DVDRead = 0x001f,
/// <summary>
/// The RandomWritable feature (see the SCSI-3 MMC specification)
/// </summary>
RandomWritable = 0x0020,
/// <summary>
/// The IncrementalStreamWritable feature (see the SCSI-3 MMC specification)
/// </summary>
IncrementalStreamWritable = 0x0021,
/// <summary>
/// The SectorErasable feature (see the SCSI-3 MMC specification)
/// </summary>
SectorErasable = 0x0022,
/// <summary>
/// The Formattable feature (see the SCSI-3 MMC specification)
/// </summary>
Formattable = 0x0023,
/// <summary>
/// The HardwareDefectManagement feature (see the SCSI-3 MMC specification)
/// </summary>
HardwareDefectManagement = 0x0024,
/// <summary>
/// The WriteOnce feature (see the SCSI-3 MMC specification)
/// </summary>
WriteOnce = 0x0025,
/// <summary>
/// The RestrictedOverwrite feature (see the SCSI-3 MMC specification)
/// </summary>
RestrictedOverwrite = 0x0026,
/// <summary>
/// The CDRWCavWrite feature (see the SCSI-3 MMC specification)
/// </summary>
CDRWCavWrite = 0x0027,
/// <summary>
/// The MRW feature (see the SCSI-3 MMC specification)
/// </summary>
MRW = 0x0028,
/// <summary>
/// The EnhancedDefectReporting feature (see the SCSI-3 MMC specification)
/// </summary>
EnhancedDefectReporting = 0x0029,
/// <summary>
/// The DVDPlusRW feature (see the SCSI-3 MMC specification)
/// </summary>
DVDPlusRW = 0x002a,
/// <summary>
/// The DVDPlusR feature (see the SCSI-3 MMC specification)
/// </summary>
DVDPlusR = 0x002b,
/// <summary>
/// The RigidRestrictedOverwrite feature (see the SCSI-3 MMC specification)
/// </summary>
RigidRestrictedOverwrite = 0x002c,
/// <summary>
/// The CDTrackAtOnce feature (see the SCSI-3 MMC specification)
/// </summary>
CDTrackAtOnce = 0x002d,
/// <summary>
/// The CDSessionAtOnce feature (see the SCSI-3 MMC specification)
/// </summary>
CDSessionAtOnce = 0x002e,
/// <summary>
/// The DVDMinusR_DVDMinusRW feature (see the SCSI-3 MMC specification)
/// </summary>
DVDMinusR_DVDMinusRW = 0x002f,
/// <summary>
/// The DDCDRead feature (see the SCSI-3 MMC specification)
/// </summary>
DDCDRead = 0x0030,
/// <summary>
/// The DDCDMinusR feature (see the SCSI-3 MMC specification)
/// </summary>
DDCDMinusR = 0x0031,
/// <summary>
/// The DDCDMinusRW feature (see the SCSI-3 MMC specification)
/// </summary>
DDCDMinusRW = 0x0032,
/// <summary>
/// The layer jump recording feature (see the SCSI MMC-5 specification)
/// </summary>
LayerJumpRecording = 0x0033,
/// <summary>
/// The CDRWMediaWriteSupport feature (see the SCSI-3 MMC specification)
/// </summary>
CDRWMediaWriteSupport = 0x0037,
/// <summary>
///
/// </summary>
BD_RPseudoOverWrite = 0x0038,
/// <summary>
/// The dual layer feature for DVD+RW
/// </summary>
DvdPlusRWDualLayer = 0x003a,
/// <summary>
/// The dual layer featuer for DVD+R
/// </summary>
DvdPlusRDualLayer = 0x003b,
/// <summary>
///
/// </summary>
BDRead = 0x0040,
/// <summary>
///
/// </summary>
BDWrite = 0x0041,
/// <summary>
///
/// </summary>
TSR = 0x0042,
/// <summary>
///
/// </summary>
HdDvdRead = 0x0050,
/// <summary>
///
/// </summary>
HdDvdWrite = 0x0051,
/// <summary>
///
/// </summary>
OldHybridDisk = 0x0052,
/// <summary>
///
/// </summary>
HybridDisk = 0x0080,
/// <summary>
/// The PowerMangaementFeature feature (see the SCSI-3 MMC specification)
/// </summary>
PowerMangaementFeature = 0x0100,
/// <summary>
/// The S_M_A_R_T feature (see the SCSI-3 MMC specification)
/// </summary>
S_M_A_R_T = 0x0101,
/// <summary>
/// The EmbeddedChanger feature (see the SCSI-3 MMC specification)
/// </summary>
EmbeddedChanger = 0x0102,
/// <summary>
/// The CDAudioExternalPlay feature (see the SCSI-3 MMC specification)
/// </summary>
CDAudioExternalPlay = 0x0103,
/// <summary>
/// The MicrocodeUpgrade feature (see the SCSI-3 MMC specification)
/// </summary>
MicrocodeUpgrade = 0x0104,
/// <summary>
/// The Timeout feature (see the SCSI-3 MMC specification)
/// </summary>
Timeout = 0x0105,
/// <summary>
/// The DVDCSS feature (see the SCSI-3 MMC specification)
/// </summary>
DVDCSS = 0x0106,
/// <summary>
/// The RealTimeStreaming feature (see the SCSI-3 MMC specification)
/// </summary>
RealTimeStreaming = 0x0107,
/// <summary>
/// The LogicalUnitSerialNumber feature (see the SCSI-3 MMC specification)
/// </summary>
LogicalUnitSerialNumber = 0x0108,
/// <summary>
/// The MediaSerialNumber feature (see the SCSI-3 MMC specification)
/// </summary>
MediaSerialNumber = 0x0109,
/// <summary>
/// The DiskControlBlock feature (see the SCSI-3 MMC specification)
/// </summary>
DiskControlBlock = 0x010A,
/// <summary>
/// The DVD_CPRM feature (see the SCSI-3 MMC specification)
/// </summary>
DVD_CPRM = 0x010B,
/// <summary>
/// The FirmwareInformation feature (see the SCSI-3 MMC specification)
/// </summary>
FirmwareInformation = 0x010C,
/// <summary>
///
/// </summary>
AACS = 0x010d,
/// <summary>
///
/// </summary>
VCPS = 0x0110
} ;
#endregion
#region private variables
/// <summary>
/// The feature code for this feature
/// </summary>
private FeatureType m_code;
/// <summary>
/// The verion for this feature
/// </summary>
private byte m_version;
/// <summary>
/// If true, this feature is persistent (see SCSI MMC spec for more details)
/// </summary>
private bool m_persistent;
/// <summary>
/// If true, this feature is current (see SCSI MMC spec for more details)
/// </summary>
private bool m_current;
/// <summary>
/// The raw data assocaited with the feature. This data may be invalid if the
/// feature is invalid.
/// </summary>
private byte[] m_data;
#endregion
#region constructor
/// <summary>
/// This is a constructor for the SCSI feature. It takes data from a raw buffer and
/// creates the SCSI featuer object
/// </summary>
/// <param name="buffer">Pointer to the start of the raw reply buffer</param>
/// <param name="size">Size of the raw reply buffer</param>
/// <param name="offset">The offset to start parsing a SCSI feature from the reply buffer</param>
public Feature(IntPtr buffer, int size, ref int offset) : base(buffer, size)
{
m_code = (FeatureType)Get16(offset);
offset += 2;
byte b = Get8(offset);
offset++;
if ((b & 0x01) != 0)
m_current = true;
else
m_current = false;
if ((b & 0x02) != 0)
m_persistent = true;
else
m_persistent = false;
m_version = (byte)((b >> 2) & 0x0f);
byte len = Get8(offset);
offset++;
m_data = new byte[len];
for(int i = 0 ; i < len && offset < BufferSize ; i++)
{
m_data[i] = Get8(offset);
offset++;
}
}
#endregion
#region public methods
/// <summary>
/// Return a string representing a human readable form of this object.
/// </summary>
/// <returns>string representing this object</returns>
public override string ToString()
{
return "Feature(type=" + m_code.ToString() + ")";
}
#endregion
#region public propreties
/// <summary>
/// Return the code associated with this feature
/// </summary>
public FeatureType Code { get { return m_code; } }
/// <summary>
/// Return the version of the current feature
/// </summary>
public byte Version { get { return m_version; } }
/// <summary>
/// Return the presistence state of the feature. If true, this feature is persistant
/// </summary>
public bool Persistent { get { return m_persistent; } }
/// <summary>
/// Return the current flag associated with the feature. If true, this feature is currently active.
/// </summary>
public bool Current { get { return m_current; } }
/// <summary>
/// This item contains the data from the feature
/// </summary>
public byte[] Data { get { return m_data; } }
/// <summary>
/// This property returns the name of the feature.
/// </summary>
public string Name
{
get
{
return m_code.ToString();
}
}
#endregion
}
}

64
Bwg.Scsi/FeatureList.cs Normal file
View File

@@ -0,0 +1,64 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Scsi
{
/// <summary>
/// This class represents a list of features returned from the SCSI device.
/// </summary>
public class FeatureList : Result
{
/// <summary>
/// The profile associated with this feature list.
/// </summary>
public readonly ushort Profile;
/// <summary>
/// The list of features returned from the device
/// </summary>
public readonly IList<Feature> Features;
/// <summary>
/// The constructure for the ScsiFeatureList object
/// </summary>
/// <param name="buffer">The pointer to the memory area containing the SCSI reply</param>
/// <param name="size">The size of the SCSI reply</param>
public FeatureList(IntPtr buffer, int size) : base(buffer, size)
{
Profile = Get16(6);
Features = new List<Feature>() ;
uint len = Get32(0);
int offset = 8;
while (offset < len + 8 && offset < size)
{
Feature f = new Feature(buffer, size, ref offset);
Features.Add(f);
}
}
}
}

142
Bwg.Scsi/FileReader.cs Normal file
View File

@@ -0,0 +1,142 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
//using Bwg.Utils;
namespace Bwg.Scsi
{
/// <summary>
/// This class reads data from a file and sends this data to the buffered
/// write stream.
/// </summary>
public unsafe class FileReader
{
#region private member variables
/// <summary>
/// The OS file for reading data from a file into a memory buffer (IntPtr)
/// </summary>
private OsFileReader m_reader;
/// <summary>
/// The buffer pool to receive the data
/// </summary>
private WriteBufferPool m_buffer_stream;
#endregion
/// <summary>
/// Create a new file reader that sends the data read to a buffer stream
/// object
/// </summary>
/// <param name="buffer">the buffer to receive the data</param>
public FileReader(WriteBufferPool buffer)
{
m_buffer_stream = buffer;
m_reader = new OsFileReader();
}
/// <summary>
/// Open a file to read data from
/// </summary>
/// <param name="filename">the name of the file</param>
/// <returns>true if the file is opened, false otherwise</returns>
public bool Open(string filename)
{
return m_reader.Open(filename);
}
/// <summary>
/// This method closes an open file.
/// </summary>
/// <returns>true if the file is closed sucessfully, false otherwise</returns>
public bool Close()
{
return m_reader.Close();
}
/// <summary>
/// This function reads data from the file and sends it to the
/// buffer stream to be sent to the burner. This function does not
/// return until all of the data from the file is read.
/// </summary>
/// <returns></returns>
public bool ReadData(int sector_size, long lba)
{
bool shortbuf = false;
int NumberRead ;
int num_sectors ;
bool first = true;
// This is the number of whole sectors that will fit into the buffer.
num_sectors = m_buffer_stream.PageSize / sector_size;
while (true)
{
WriteBuffer buf ;
buf = m_buffer_stream.GetFreeBuffer();
if (!m_reader.ReadData(buf.BufferPtr, num_sectors * sector_size, out NumberRead))
return false ;
// If the read succeeded, but read zero bytes, we have reached the
// end of the file.
if (NumberRead == 0)
return true;
if (shortbuf)
throw new Exception("read two short packets");
// Mark the buffer with the amount of data that has
// been read from the file
int sectors = NumberRead / sector_size ;
if ((NumberRead % sector_size) != 0)
{
shortbuf = true;
sectors++;
}
if (first)
{
buf.SourceString = "First block from FileReader";
buf.LogicalBlockAddress = lba;
first = false;
}
else
{
buf.SourceString = "Not first block from FileReader";
buf.LogicalBlockAddress = long.MaxValue;
}
buf.SectorSize = sector_size;
buf.DataSize = sectors;
// Send the buffer to the device
m_buffer_stream.SendBufferToDevice(buf);
}
}
}
}

View File

@@ -0,0 +1,343 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace Bwg.Scsi
{
/// <summary>
/// This class represents the list of format parameters that are presented to
/// the device when performing a FormatUnit() operation.
/// </summary>
public class FormatParameterList
{
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
public enum UnitFormatType : byte
{
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
FullFormat = 0,
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
SpareAreaExpansion = 1,
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
ZoneReformat = 4,
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
ZoneFormat = 5,
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
CD_DVD_RW_FullFormat = 0x10,
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
CD_DVD_RW_GrowSession = 0x11,
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
CD_DVD_RW_AddSession = 0x12,
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
DVD_RW_QuickGrowLastSession = 0x13,
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
DVD_RW_QuickAddSession = 0x14,
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
DVD_RW_QuickFormat = 0x15,
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
MRW_FullFormat = 0x24, // CD-RW NumberOfBlocks = 0xffffffff
// DVD+RW NumberOfBlocks = 0xffffffff
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
DVD_Plus_RW_BasicFormat = 0x25, // NumberOfBlock = 0xffffffff
/// <summary>
/// Basic format for DVD+RW (either SL or DL), see SCSI MMC-6
/// </summary>
DVD_Plus_RW_BasicFormat_DL_SL = 0x26,
/// <summary>
/// Format with spare areas for BluRay-RE
/// </summary>
BDRE_Format_With_Spare_Areas = 0x30,
/// <summary>
/// Format without spare areas for BlueRay-RE
/// </summary>
BDRE_Format_Without_Spare_Areas = 0x31,
/// <summary>
/// Format a BD-R disk with spare area
/// </summary>
BDR_Format_With_Spare_Areas = 0x32
} ;
private byte m_flags;
/// <summary>
/// The initializaion pattern for this format operation (not yet supported)
/// </summary>
public InitializationPattern IP;
/// <summary>
/// The format type for this format operation
/// </summary>
public UnitFormatType FormatType;
/// <summary>
/// The subtype for the format
/// </summary>
public byte FormatSubType;
/// <summary>
/// The number of blocks for the format operation
/// </summary>
public uint NumberOfBlocks;
/// <summary>
/// The format type dependent parameter
/// </summary>
public uint Parameter;
/// <summary>
/// Constructor for the parameter list object
/// </summary>
public FormatParameterList()
{
m_flags = 0;
IP = null;
}
/// <summary>
/// The size of the format parameters list in bytes, as it will exist in
/// the command to the SCSI unit.
/// </summary>
public uint Size
{
get
{
return 4 + 8;
}
}
#region public flags
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
public byte FOV
{
get
{
return (byte)((m_flags >> 7) & 0x01);
}
set
{
if (value != 0)
m_flags |= 0x80;
else
m_flags &= 0x7f;
}
}
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
public byte DPRY
{
get
{
return (byte)((m_flags >> 6) & 0x01);
}
set
{
if (value != 0)
m_flags |= 0x40;
else
m_flags &= 0xbf;
}
}
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
public byte DCRT
{
get
{
return (byte)((m_flags >> 5) & 0x01);
}
set
{
if (value != 0)
m_flags |= 0x20;
else
m_flags &= 0xdf;
}
}
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
public byte STPF
{
get
{
return (byte)((m_flags >> 4) & 0x01);
}
set
{
if (value != 0)
m_flags |= 0x10;
else
m_flags &= 0xEF;
}
}
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
public byte TRYOUT
{
get
{
return (byte)((m_flags >> 2) & 0x01);
}
set
{
if (value != 0)
m_flags |= 0x04;
else
m_flags &= 0xFB;
}
}
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
public byte IMMED
{
get
{
return (byte)((m_flags >> 1) & 0x01);
}
set
{
if (value != 0)
m_flags |= 0x02;
else
m_flags &= 0xFD;
}
}
/// <summary>
/// See SCSI MMC-4 specification
/// </summary>
public byte VS
{
get
{
return (byte)((m_flags >> 0) & 0x01);
}
set
{
if (value != 0)
m_flags |= 0x01;
else
m_flags &= 0xFE;
}
}
#endregion
/// <summary>
/// Format the parameter list to the memory block to be sent down to the device.
/// The result should be a format parameter block as seen in the SCSI MMC specs.
/// </summary>
/// <param name="dest"></param>
public void FormatToMemory(IntPtr dest)
{
byte v;
int offset;
Marshal.WriteByte(dest, 0, 0); // Byte 0 - reserved
v = m_flags;
if (IP != null)
v |= 0x08;
Marshal.WriteByte(dest, 1, v); // Byte 1 - flags
Marshal.WriteByte(dest, 2, 0);
Marshal.WriteByte(dest, 3, 8); // Format descriptor length = 8
offset = 4 ;
if (IP != null)
{
// If the initialization pattern exists, it goes here
throw new Exception("Not supported yet");
}
// Write the # of blocks
Marshal.WriteByte(dest, offset++, (byte)((NumberOfBlocks >> 24) & 0xff));
Marshal.WriteByte(dest, offset++, (byte)((NumberOfBlocks >> 16) & 0xff));
Marshal.WriteByte(dest, offset++, (byte)((NumberOfBlocks >> 8) & 0xff));
Marshal.WriteByte(dest, offset++, (byte)((NumberOfBlocks >> 0) & 0xff));
byte b = (byte)(((byte)FormatType << 2) | FormatSubType) ;
Marshal.WriteByte(dest, offset++, b) ;
Marshal.WriteByte(dest, offset++, (byte)((Parameter >> 16) & 0xff));
Marshal.WriteByte(dest, offset++, (byte)((Parameter >> 8) & 0xff));
Marshal.WriteByte(dest, offset++, (byte)((Parameter >> 0) & 0xff));
}
}
}

142
Bwg.Scsi/HeaderData.cs Normal file
View File

@@ -0,0 +1,142 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Scsi
{
/// <summary>
/// This class contains the header data read from a sector
/// </summary>
public class HeaderData : Result
{
#region public types
/// <summary>
/// The block type, see SCSI MMC spec
/// </summary>
public enum BlockTypeType : byte
{
/// <summary>
/// See SCSI MMC spec
/// </summary>
UserDataBlock = 0x00,
/// <summary>
/// See SCSI MMC spec
/// </summary>
FourthRunInBlock = 0x01,
/// <summary>
/// See SCSI MMC spec
/// </summary>
ThirdRunInBlock = 0x02,
/// <summary>
/// See SCSI MMC spec
/// </summary>
SecondRunInBlock = 0x03,
/// <summary>
/// See SCSI MMC spec
/// </summary>
FirstRunInBlock = 0x04,
/// <summary>
/// See SCSI MMC spec
/// </summary>
LinkBlock = 0x05,
/// <summary>
/// See SCSI MMC spec
/// </summary>
SecondRunOutBlock = 0x06,
/// <summary>
/// See SCSI MMC spec
/// </summary>
FirstRunOutBlock = 0x07
} ;
/// <summary>
/// The data mode for the sector (only applies if track mode is 0x04)
/// </summary>
public enum DataTypeType : byte
{
/// <summary>
/// Mode 0 data, 2336 bytes of zero
/// </summary>
Mode0Data = 0x00,
/// <summary>
/// Mode 1 data, 2048 bytes of user data
/// </summary>
Mode1Data = 0x01,
/// <summary>
/// Mode 2 data, multiple forms of data
/// </summary>
Mode2Data = 0x02,
/// <summary>
/// Reserved, should not be returned by a drive
/// </summary>
Reserved = 0x03
} ;
#endregion
#region public data members
/// <summary>
/// The time data read from the sector
/// </summary>
public readonly MinuteSecondFrame MSF;
/// <summary>
/// The block type, see SCSI MMC spec
/// </summary>
public readonly BlockTypeType BlockType;
/// <summary>
/// The data type, see SCSI MMC spec
/// </summary>
public readonly DataTypeType DataType;
#endregion
/// <summary>
/// Create the header data object from a buffer containing the header data
/// </summary>
/// <param name="buf">buffer containing the data</param>
/// <param name="size">size of the data</param>
public HeaderData(IntPtr buf, int size)
: base(buf, size)
{
byte b ;
MSF = new MinuteSecondFrame(Get8(0), Get8(1), Get8(2));
b = Get8(3);
BlockType = (BlockTypeType)((b >> 5) & 0x07);
DataType = (DataTypeType)(b & 0x03);
}
}
}

View File

@@ -0,0 +1,77 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Scsi
{
/// <summary>
/// The class representing a pattern to use in initialization the surface of a
/// DVD.
/// </summary>
public class InitializationPattern
{
/// <summary>
/// The type of modifier for the IP pattern
/// </summary>
public enum IPModifierType : byte
{
/// <summary>
///
/// </summary>
NoHeader = 0,
/// <summary>
///
/// </summary>
WriteLBA = 1,
/// <summary>
///
/// </summary>
WriteLBAPhysical = 2,
/// <summary>
///
/// </summary>
Reserved = 3
}
/// <summary>
/// The modifier
/// </summary>
public IPModifierType IPModifier;
/// <summary>
///
/// </summary>
public byte PatternType;
/// <summary>
///
/// </summary>
public byte[] Pattern;
}
}

128
Bwg.Scsi/InquiryResult.cs Normal file
View File

@@ -0,0 +1,128 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Scsi
{
/// <summary>
/// This class contains the information returned from a SCSI Inquiry request
/// </summary>
public sealed class InquiryResult : Result
{
/// <summary>
/// The peripheral qualifier field from the SCSI inquiry reply, should be zero for MMC devices.
/// </summary>
public readonly byte PeripheralQualifier ;
/// <summary>
/// The peripheral device type field from the SCSI inquiry reply, should be five for MMC devices.
/// </summary>
public readonly byte PeripheralDeviceType;
/// <summary>
/// This gives the version number of the Inquiry data returned
/// </summary>
public readonly byte ResponseDataFormat;
/// <summary>
/// The RMB field from the SCSI inquiry reply, should be true for MMC devices.
/// </summary>
public readonly bool RMB;
/// <summary>
///
/// </summary>
public readonly byte Version;
/// <summary>
///
/// </summary>
public readonly string VendorIdentification;
/// <summary>
///
/// </summary>
public readonly string ProductIdentification;
/// <summary>
/// The version of the firmware
/// </summary>
public readonly string FirmwareVersion;
/// <summary>
///
/// </summary>
public readonly string ProductRevision;
/// <summary>
/// This property returns true if the device supports removable medium.
/// </summary>
public bool RemovableMediumBit { get { return RMB; } }
/// <summary>
///
/// </summary>
/// <param name="buffer"></param>
/// <param name="size"></param>
public InquiryResult(IntPtr buffer, int size) : base(buffer, size)
{
ResponseDataFormat = (byte)(Get8(3) & 0x0f);
//
// Make sure the inquiry data is in the right format
// A data format of 2 is good up through MMC-3. A data format of 3
// is used for MMC-4 and MMC-5. Some drives (especially from LiteOn)
// use a value of 1, but still behave as expected.
//
if (ResponseDataFormat != 2 && ResponseDataFormat != 3 && ResponseDataFormat != 1)
{
m_valid = false;
return;
}
PeripheralQualifier = (byte)((Get8(0) >> 5) & 0x07);
PeripheralDeviceType = (byte)(Get8(0) & 0x1f);
RMB = false;
if ((Get8(1) & 0x80) != 0)
RMB = true;
Version = Get8(0x02);
VendorIdentification = GetString(8, 15);
ProductIdentification = GetString(16, 31);
int len = 35;
if (len >= size)
len = size - 1;
FirmwareVersion = GetString(32, len);
if (size >= 56)
ProductRevision = GetString(36, 55);
else
ProductRevision = string.Empty;
}
}
}

View File

@@ -0,0 +1,309 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
namespace Bwg.Scsi
{
/// <summary>
/// This type represents a location on a disk in minute, seconds, frame format
/// </summary>
[Serializable()]
public class MinuteSecondFrame
{
/// <summary>
/// The number of 44100 Hz samples in a single frame
/// </summary>
public const long SamplesPerFrame = 588;
/// <summary>
/// The number of frames in a second
/// </summary>
public const long FramesPerSecond = 75;
/// <summary>
/// The number of seconds in a minute.
/// </summary>
public const long SecondsPerMinute = 60;
/// <summary>
/// The minutes of this time frame
/// </summary>
public int Minutes;
/// <summary>
/// The seconds of this time frame
/// </summary>
public byte Seconds;
/// <summary>
/// The frames (at FramesPerSecond per second) of this time frame
/// </summary>
public byte Frames;
/// <summary>
/// Constructor for the type
/// </summary>
/// <param name="m"></param>
/// <param name="s"></param>
/// <param name="f"></param>
public MinuteSecondFrame(int m, int s, int f)
{
Minutes = m;
Seconds = (byte)s;
Frames = (byte)f;
}
/// <summary>
/// Create a MinuteSecondFrame value from a sector count
/// </summary>
/// <param name="sectors"></param>
public MinuteSecondFrame(long sectors)
{
long m = sectors / (FramesPerSecond * SecondsPerMinute);
sectors -= m * FramesPerSecond * SecondsPerMinute;
long s = sectors / FramesPerSecond;
sectors -= s * FramesPerSecond;
Debug.Assert(s < SecondsPerMinute);
Debug.Assert(sectors < FramesPerSecond);
Minutes = (int)m;
Seconds = (byte)s;
Frames = (byte)sectors;
}
/// <summary>
/// Return the sector count for this time span
/// </summary>
public long SectorCount
{
get
{
return Minutes * SecondsPerMinute * FramesPerSecond + Seconds * FramesPerSecond + Frames;
}
}
/// <summary>
/// This property returns the logical block address associated with the time given.
/// </summary>
public long LogicalBlockAddress
{
get
{
long result = Minutes * FramesPerSecond * SecondsPerMinute + Seconds * FramesPerSecond + Frames;
if (Minutes < 90)
result -= 150;
else
result -= 450150;
return result;
}
}
/// <summary>
/// Return a hash code for this object
/// </summary>
/// <returns>hash value</returns>
public override int GetHashCode()
{
return base.GetHashCode();
}
/// <summary>
/// Returns true if the two objects are equal
/// </summary>
/// <param name="o">the object to compare to</param>
/// <returns>true if the objects are equal, false otherwise</returns>
public override bool Equals(Object o)
{
if (o == null)
return false;
if (!(o is MinuteSecondFrame))
return false;
MinuteSecondFrame other = (MinuteSecondFrame)o;
return other.Minutes == Minutes && other.Seconds == Seconds && other.Frames == Frames;
}
/// <summary>
/// Convert to a string
/// </summary>
public override string ToString()
{
return Minutes.ToString("") + ":" + Seconds.ToString("") + "." + Frames.ToString("") + ", " + SectorCount + " sectors";
}
/// <summary>
/// convert to a string with format options
/// </summary>
/// <param name="fmt">the format to use for the output</param>
/// <returns>a string representing the object</returns>
public string ToString(string fmt)
{
string result = "";
if (fmt == "M:S")
{
result = Minutes.ToString("d2") + ":" + Seconds.ToString("d2");
}
else if (fmt == "M:S.F")
{
result = Minutes.ToString("d2") + ":" + Seconds.ToString("d2") + "." + Frames.ToString("d2");
}
else if (fmt == "M:S:F")
{
result = Minutes.ToString("d2") + ":" + Seconds.ToString("d2") + ":" + Frames.ToString("d2");
}
else
{
throw new FormatException("the format '" + fmt + "' is not valid for the class Bwg.Scsi.MinuteSecondFrame");
}
return result;
}
/// <summary>
/// Convert a number of samples into an MSF object
/// </summary>
/// <param name="samples">the number of samples</param>
/// <returns></returns>
static public MinuteSecondFrame FromSampleCount(long samples)
{
long frames = samples / SamplesPerFrame;
uint m = (uint)(frames / (FramesPerSecond * SecondsPerMinute));
frames -= m * FramesPerSecond * SecondsPerMinute;
uint s = (uint)(frames / FramesPerSecond);
frames -= s * FramesPerSecond;
Debug.Assert(s < SecondsPerMinute);
Debug.Assert(m < FramesPerSecond);
return new MinuteSecondFrame((byte)m, (byte)s, (byte)frames);
}
/// <summary>
/// Operator for adding two MinuteSecondFrame times together
/// </summary>
/// <param name="t1">the first operand</param>
/// <param name="t2">the second operand</param>
/// <returns>the sum of t1 and t2</returns>
static public MinuteSecondFrame operator +(MinuteSecondFrame t1, MinuteSecondFrame t2)
{
return new MinuteSecondFrame(t1.SectorCount + t2.SectorCount);
}
/// <summary>
/// Operator for adding a time value with a frame count (or sector count)
/// </summary>
/// <param name="t1">the time value</param>
/// <param name="t2">the count in sectors (or frames)</param>
/// <returns>the addition time</returns>
static public MinuteSecondFrame operator +(MinuteSecondFrame t1, long t2)
{
return new MinuteSecondFrame(t1.SectorCount + t2);
}
/// <summary>
/// Returns true if the first object is less than the second object
/// </summary>
/// <param name="t1">the first object</param>
/// <param name="t2">the second object</param>
/// <returns>true if t1 is less than t2 </returns>
static public bool operator <(MinuteSecondFrame t1, MinuteSecondFrame t2)
{
if (t1.Minutes < t2.Minutes)
return true;
if (t1.Minutes > t2.Minutes)
return false;
if (t1.Seconds < t2.Seconds)
return true;
if (t1.Seconds > t2.Seconds)
return false;
if (t1.Frames < t2.Frames)
return true;
return false;
}
/// <summary>
/// Returns true if the first object is greater than the second object
/// </summary>
/// <param name="t1">the first object</param>
/// <param name="t2">the second object</param>
/// <returns>true, if t1 is greater than t2</returns>
static public bool operator >(MinuteSecondFrame t1, MinuteSecondFrame t2)
{
if (t1.Minutes > t2.Minutes)
return true;
if (t1.Minutes < t2.Minutes)
return false;
if (t1.Seconds > t2.Seconds)
return true;
if (t1.Seconds < t2.Seconds)
return false;
if (t1.Frames > t2.Frames)
return true;
return false;
}
/// <summary>
/// returns true if t1 is less than or equal to t2
/// </summary>
/// <param name="t1"></param>
/// <param name="t2"></param>
/// <returns></returns>
static public bool operator <=(MinuteSecondFrame t1, MinuteSecondFrame t2)
{
return (t1 < t2) || (t1 == t2);
}
/// <summary>
///
/// </summary>
/// <param name="t1"></param>
/// <param name="t2"></param>
/// <returns></returns>
static public bool operator >=(MinuteSecondFrame t1, MinuteSecondFrame t2)
{
return (t1 > t2) || (t1 == t2);
}
}
}

174
Bwg.Scsi/ModePage.cs Normal file
View File

@@ -0,0 +1,174 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace Bwg.Scsi
{
/// <summary>
/// This object represents a single mode page in a mode table.
/// </summary>
public class ModePage : Result
{
#region private member variables
/// <summary>
/// The data associated with the page table. This data also includes the page code and length
/// data elements from the mode page data.
/// </summary>
protected byte[] m_page_data;
#endregion
#region constructor
/// <summary>
/// This is the constructor for the mode page object. It builds a mode page object from
/// the raw reply area from the SCSI device.
/// </summary>
/// <param name="buffer">A pointer to the raw reply area</param>
/// <param name="size">The size of the raw reply area in bytes</param>
/// <param name="offset">The offset to the mode page data</param>
public ModePage(IntPtr buffer, int size, ref ushort offset) : base(buffer, size)
{
byte b = Get8(offset);
offset++;
byte len = Get8(offset);
offset++;
m_page_data = new byte[len + 2];
m_page_data[0] = b;
m_page_data[1] = len;
for(int i = 0 ; i < len ; i++)
m_page_data[i + 2] = Get8(offset++);
}
#endregion
#region public properties
/// <summary>
/// This is the data that makes up this mode page
/// </summary>
public byte[] PageData
{
get
{
return m_page_data;
}
}
/// <summary>
/// The length of this mode page in bytes
/// </summary>
public ushort Length
{
get
{
return (ushort)m_page_data.GetLength(0);
}
}
/// <summary>
/// The page code for this page
/// </summary>
public byte PageCode
{
get
{
return (byte)(m_page_data[0] & 0x3f);
}
}
/// <summary>
/// If true, these parameters are saved permanently
/// </summary>
public bool ParametersSavable
{
get
{
return ((m_page_data[0] & 0x80) != 0) ? true : false;
}
set
{
if (value)
m_page_data[0] |= 0x80;
else
m_page_data[0] &= 0x7f;
}
}
#endregion
#region public methods
/// <summary>
/// Retreive a 32 bit value from a mode page
/// </summary>
/// <param name="offset">offset in the page to the value</param>
/// <returns>a 32 bit value retreived from the mode page data</returns>
public int ModeGet32(int offset)
{
return m_page_data[offset + 0] << 24 |
m_page_data[offset + 1] << 16 |
m_page_data[offset + 2] << 8 |
m_page_data[offset + 3] << 0;
}
/// <summary>
/// Set a 32 bit value in a mode page
/// </summary>
/// <param name="offset">offset in the page to where the value will be placed</param>
/// <param name="value">the value to write</param>
public void ModeSet32(int offset, int value)
{
m_page_data[offset + 0] = (byte)((value >> 24) & 0xff);
m_page_data[offset + 1] = (byte)((value >> 16) & 0xff);
m_page_data[offset + 2] = (byte)((value >> 8) & 0xff);
m_page_data[offset + 3] = (byte)((value >> 0) & 0xff);
}
/// <summary>
///
/// </summary>
/// <param name="offset"></param>
/// <returns></returns>
public ushort ModeGet16(int offset)
{
return (ushort)(m_page_data[offset + 0] << 8 |
m_page_data[offset + 1] << 0);
}
/// <summary>
///
/// </summary>
/// <param name="offset"></param>
/// <param name="value"></param>
public void ModeSet16(int offset, ushort value)
{
m_page_data[offset + 0] = (byte)((value >> 8) & 0xff);
m_page_data[offset + 1] = (byte)((value >> 0) & 0xff);
}
#endregion
}
}

108
Bwg.Scsi/ModeTable.cs Normal file
View File

@@ -0,0 +1,108 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace Bwg.Scsi
{
/// <summary>
/// This class represents a mode table from the scsi device.
/// </summary>
public class ModeTable : Result
{
/// <summary>
/// This is the size of the header associated with a mode table.
/// </summary>
public const int ModeTableHeaderSize = 8;
/// <summary>
/// The set of mode pages in this mode table.
/// </summary>
public IList<ModePage> Pages;
/// <summary>
/// The constructor for the mode table object. It builds the mode table from
/// the raw reply buffer from the SCSI device.
/// </summary>
/// <param name="buffer"></param>
/// <param name="size"></param>
public ModeTable(IntPtr buffer, int size): base(buffer, size)
{
ushort len = Get16(0);
ushort index = ModeTableHeaderSize;
Pages = new List<ModePage>();
while (index < len && index < size)
{
int b0 = Get8(index) & 0x3f;
ModePage page ;
if (b0 == 0x05)
page = new WriteParameterModePage(buffer, size, ref index) ;
else
page = new ModePage(buffer, size, ref index);
Pages.Add(page);
}
}
/// <summary>
/// This property returns the total size of the raw mode table in bytes
/// </summary>
public ushort Size
{
get
{
ushort len = ModeTableHeaderSize;
foreach (ModePage p in Pages)
len += p.Length;
return len;
}
}
/// <summary>
/// Format a mode table back into raw buffer for shipment down to a SCSI device.
/// </summary>
/// <param name="buffer">The buffer to receive the mode table</param>
public void Format(IntPtr buffer)
{
ushort s = (ushort)(Size - ModeTableHeaderSize);
Marshal.WriteByte(buffer, 0, (byte)((s >> 8) & 0xff));
Marshal.WriteByte(buffer, 1, (byte)(s & 0xff));
int offset = ModeTableHeaderSize;
foreach (ModePage p in Pages)
{
IntPtr dest = new IntPtr(buffer.ToInt32() + offset);
Marshal.Copy(p.PageData, 0, dest, p.Length);
offset += p.Length;
}
}
}
}

60
Bwg.Scsi/OpcTableEntry.cs Normal file
View File

@@ -0,0 +1,60 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Scsi
{
/// <summary>
/// This class represents a single entry in the OPC table
/// </summary>
public class OpcTableEntry : Result
{
/// <summary>
/// The speed to which this entry applies
/// </summary>
public readonly ushort Speed;
/// <summary>
/// The OPC table entries
/// </summary>
public readonly byte[] Table;
/// <summary>
/// Constructor for an OPC table entry
/// </summary>
/// <param name="buffer">The raw buffer being processed</param>
/// <param name="size">The size of the buffer</param>
/// <param name="offset">The offset into the buffer that contains the OPC entry</param>
public OpcTableEntry(IntPtr buffer, int size, int offset) : base(buffer, size)
{
Speed = Get16(offset);
Table = new byte [6] ;
for (int i = 0; i < 6; i++)
Table[i] = Get8(offset + i + 2);
}
}
}

84
Bwg.Scsi/Performance.cs Normal file
View File

@@ -0,0 +1,84 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Scsi
{
/// <summary>
/// This class represents a performance entry from the device's performance list
/// </summary>
public class Performance : Result
{
/// <summary>
/// The start LBA for this entry
/// </summary>
public readonly uint StartLBA;
/// <summary>
/// The starting performance for this entry
/// </summary>
public readonly uint StartPerformance;
/// <summary>
/// The end LBA for this entry
/// </summary>
public readonly uint EndLBA;
/// <summary>
/// The end performance for this entry
/// </summary>
public readonly uint EndPerformance;
/// <summary>
/// The constructor to create a performance entry
/// </summary>
/// <param name="buffer">the buffer</param>
/// <param name="offset">the offset into the buffer</param>
/// <param name="size">the size of the buffer</param>
public Performance(IntPtr buffer, int offset, int size)
: base(buffer, size)
{
StartLBA = Get32(offset);
StartPerformance = Get32(offset + 4);
EndLBA = Get32(offset + 8);
EndPerformance = Get32(offset + 12);
}
/// <summary>
/// Return a human readable string representing this object.
/// </summary>
/// <returns></returns>
public override string ToString()
{
string str = string.Empty;
str += "Start LBA=" + StartLBA.ToString();
str += ", Start Perf=" + StartPerformance.ToString() + " Kb/sec";
str += ", End LBA=" + EndLBA.ToString();
str += ", End Perf=" + EndPerformance.ToString() + " Kb/sec";
return str;
}
}
}

170
Bwg.Scsi/PerformanceList.cs Normal file
View File

@@ -0,0 +1,170 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Diagnostics;
namespace Bwg.Scsi
{
/// <summary>
/// A list of performance entries from the drive
/// </summary>
public class PerformanceList : Result, IEnumerable<Performance>, IEnumerable
{
#region public types
/// <summary>
/// The type of the data (read or write)
/// </summary>
public enum DataType
{
/// <summary>
/// This means read data
/// </summary>
ReadData,
/// <summary>
/// This means write data
/// </summary>
WriteData
} ;
/// <summary>
///
/// </summary>
public enum ExceptType : byte
{
/// <summary>
///
/// </summary>
Nominal = 0,
/// <summary>
///
/// </summary>
Entire = 1,
/// <summary>
///
/// </summary>
Exceptions = 2
}
#endregion
#region private data members
private DataType m_type;
private IList<Performance> m_list;
private bool m_except;
#endregion
/// <summary>
/// The constructor for the class
/// </summary>
/// <param name="buffer"></param>
/// <param name="size"></param>
public PerformanceList(IntPtr buffer, int size)
: base(buffer, size)
{
m_list = new List<Performance>();
uint len = Get32(0);
int index = 8;
Debug.Assert(size >= 8);
byte b = Get8(4);
if ((b & 0x02) != 0)
m_type = DataType.WriteData;
else
m_type = DataType.ReadData;
if ((b & 0x01) != 0)
m_except = true;
else
m_except = false;
while (index < len && index + 16 <= len && index + 16 <= size)
{
Performance p = new Performance(buffer, index, size);
m_list.Add(p);
index += 16;
}
}
/// <summary>
/// Return an indexed entry tino the performance list
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public Performance this[int index]
{
get
{
return m_list[index];
}
}
#region properties
/// <summary>
/// The type of the data
/// </summary>
public DataType Type
{
get
{
return m_type;
}
}
/// <summary>
/// If true, this is exception data
/// </summary>
public bool IsExceptionData
{
get
{
return m_except;
}
}
#endregion
#region public members
/// <summary>
/// Return an enumerator for this list
/// </summary>
/// <returns></returns>
public IEnumerator<Performance> GetEnumerator()
{
return m_list.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return m_list.GetEnumerator();
}
#endregion
}
}

View File

@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Bwg.Scsi")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("BwgSoftware")]
[assembly: AssemblyProduct("BwgBurn")]
[assembly: AssemblyCopyright("Copyright © 2006 by Jack W. Griffin, Jr.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("d8330703-34ac-4124-a059-ba011391cc2e")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.0.7.1")]
[assembly: AssemblyFileVersion("0.0.7.1")]

205
Bwg.Scsi/Result.cs Normal file
View File

@@ -0,0 +1,205 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Bwg.Scsi
{
/// <summary>
/// This class is a base class for classes that contain results from SCSI commands. This
/// class contains information about whether or not that result is valid and provides functions
/// for extract data from the SCSI response.
/// </summary>
public abstract class Result
{
#region private data members
/// <summary>
/// The data buffer containing the data that makes up the result
/// </summary>
private IntPtr m_buffer ;
/// <summary>
/// The size of the data in the buffer
/// </summary>
private int m_size ;
/// <summary>
/// This member is true if the result is valid. It is false if an error occurred while
/// parsing the SCSI result.
/// </summary>
protected bool m_valid;
#endregion
#region constructor
/// <summary>
/// This is the constructor for the ScsiResult class.
/// </summary>
/// <param name="buffer">A pointer to the memory area containing the SCSI reply</param>
/// <param name="size">The size of the memory area containing the SCSI reply</param>
public Result(IntPtr buffer, int size)
{
m_valid = true;
m_buffer = buffer;
m_size = size;
}
#endregion
#region public properties
/// <summary>
/// This property is true if the result is valid, and false otherwise.
/// </summary>
public bool Valid
{
get
{
return m_valid;
}
}
/// <summary>
/// This property returns the size of the buffer
/// </summary>
public int BufferSize
{
get { return m_size; }
}
/// <summary>
/// This property returns the buffer
/// </summary>
public IntPtr Buffer
{
get { return m_buffer; }
}
#endregion
#region public member functions
/// <summary>
/// This method returns a byte of data from the memory area associated with the SCSI reply.
/// </summary>
/// <param name="offset">The location of the byte to return within the reply</param>
/// <returns>a byte of data from the reply</returns>
public byte Get8(int offset)
{
if (offset >= m_size)
throw new Exception("offset " + offset.ToString() + " is out side the range of the buffer");
return Marshal.ReadByte(m_buffer, offset);
}
/// <summary>
///
/// </summary>
/// <param name="offset"></param>
/// <returns></returns>
public ushort Get16(int offset)
{
return (ushort)((Get8(offset) << 8) | Get8(offset + 1));
}
/// <summary>
/// Get a 16 bit number located in two different places in the buffer
/// </summary>
/// <param name="msb">offset to the MSB of the number</param>
/// <param name="lsb">offset to the LSB of the number</param>
/// <returns></returns>
public ushort Get16(int msb, int lsb)
{
return (ushort)((Get8(msb) << 8) | Get8(lsb));
}
/// <summary>
///
/// </summary>
/// <param name="offset"></param>
/// <returns></returns>
public uint Get24(int offset)
{
return (UInt32)((Get8(offset) << 16) | (Get8(offset + 1) << 8) | Get8(offset + 2));
}
/// <summary>
///
/// </summary>
/// <param name="offset"></param>
/// <returns></returns>
public uint Get32(int offset)
{
return (UInt32)((Get8(offset) << 24) | (Get8(offset + 1) << 16) | (Get8(offset + 2) << 8) | Get8(offset + 3));
}
/// <summary>
/// This method returns a 32 bit integer from an offset in the data buffer. The data is
/// ordered as big endian data per the SCSI-3 specification.
/// </summary>
/// <param name="offset">the offset into the buffer</param>
/// <returns></returns>
public int Get32Int(int offset)
{
uint b = Get32(offset);
Debug.Assert(b < Int32.MaxValue);
return (int)b;
}
/// <summary>
///
/// </summary>
/// <param name="start"></param>
/// <param name="stop"></param>
/// <returns></returns>
public string GetString(int start, int stop)
{
string s = "";
for (int i = start; i <= stop; i++)
{
byte b = Get8(i);
s += (char)b;
}
return s;
}
/// <summary>
/// Return a true or false value based on a bit in the buffer
/// </summary>
/// <param name="offset">offset to the byte containing the bit</param>
/// <param name="bit">the specific bit number</param>
/// <returns>boolean reflecting the value of the bit</returns>
public bool GetBit(int offset, int bit)
{
byte b = Get8(offset);
if ((b & (1 << bit)) != 0)
return true;
return false;
}
#endregion
}
}

115
Bwg.Scsi/SpeedDescriptor.cs Normal file
View File

@@ -0,0 +1,115 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Scsi
{
/// <summary>
///
/// </summary>
public class SpeedDescriptor : Result
{
/// <summary>
///
/// </summary>
public readonly Device.RotationalControl WRC;
/// <summary>
///
/// </summary>
public readonly bool Exact;
/// <summary>
///
/// </summary>
public readonly bool MRW;
/// <summary>
///
/// </summary>
public readonly uint EndLBA;
/// <summary>
///
/// </summary>
public readonly int ReadSpeed;
/// <summary>
///
/// </summary>
public readonly int WriteSpeed;
#region constructor
/// <summary>
///
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="size"></param>
public SpeedDescriptor(IntPtr buffer, int offset, int size)
: base(buffer, size)
{
byte b = Get8(offset);
if (((b & 0x03) >> 3 == 0))
WRC = Device.RotationalControl.CLVandNonPureCav ;
else if (((b & 0x03) >> 3) == 1)
WRC = Device.RotationalControl.PureCav ;
if ((b & 0x02) == 0)
Exact = false ;
else
Exact = true ;
if ((b & 0x01) == 0)
MRW = false ;
else
MRW = true ;
EndLBA = Get32(offset + 4);
ReadSpeed = Get32Int(offset + 8);
WriteSpeed = Get32Int(offset + 12);
}
/// <summary>
/// Return a human readable string representing this object
/// </summary>
/// <returns></returns>
public override string ToString()
{
string str = string.Empty;
str += "WRC=" + WRC.ToString();
str += ", Exact=" + Exact.ToString();
str += ", MRW=" + MRW.ToString();
str += ", EndLba=" + EndLBA.ToString();
str += ", Read=" + ReadSpeed.ToString();
str += ", Write=" + WriteSpeed.ToString();
return str;
}
#endregion
}
}

View File

@@ -0,0 +1,96 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Diagnostics;
namespace Bwg.Scsi
{
/// <summary>
///
/// </summary>
public class SpeedDescriptorList : Result, IEnumerable<SpeedDescriptor>, IEnumerable
{
private IList<SpeedDescriptor> m_list;
/// <summary>
///
/// </summary>
/// <param name="buffer"></param>
/// <param name="size"></param>
public SpeedDescriptorList(IntPtr buffer, int size)
: base(buffer, size)
{
m_list = new List<SpeedDescriptor>();
uint len = Get32(0) + 4;
int index = 8;
Debug.Assert(size >= 8);
while (index < len && index < size)
{
SpeedDescriptor p = new SpeedDescriptor(buffer, index, size);
m_list.Add(p);
index += 16;
}
}
/// <summary>
/// This method is an indexor into the list of descriptors
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public SpeedDescriptor this[int index]
{
get
{
return m_list[index];
}
}
/// <summary>
/// Return the number of speed descriptors in the list
/// </summary>
public int Count
{
get { return m_list.Count; }
}
/// <summary>
/// Return an enumerator for this list
/// </summary>
/// <returns></returns>
public IEnumerator<SpeedDescriptor> GetEnumerator()
{
return m_list.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return m_list.GetEnumerator();
}
}
}

121
Bwg.Scsi/SubheaderData.cs Normal file
View File

@@ -0,0 +1,121 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Scsi
{
/// <summary>
/// This class represents subheader data for a given sector
/// </summary>
public class SubheaderData : Result
{
#region public types
/// <summary>
/// The submode type
/// </summary>
[Flags]
public enum SubmodeType : byte
{
/// <summary>
/// See SCSI MMC spec
/// </summary>
EndOfFile = 0x80,
/// <summary>
/// See SCSI MMC spec
/// </summary>
RealTimeBlock = 0x40,
/// <summary>
/// See SCSI MMC spec
/// </summary>
Form2 = 0x20,
/// <summary>
/// See SCSI MMC spec
/// </summary>
TriggerBlock = 0x10,
/// <summary>
/// See SCSI MMC spec
/// </summary>
DataBlock = 0x08,
/// <summary>
/// See SCSI MMC spec
/// </summary>
AudioBlock = 0x04, // Not traditional CD-DA
/// <summary>
/// See SCSI MMC spec
/// </summary>
VideoBlock = 0x02,
/// <summary>
/// See SCSI MMC spec
/// </summary>
EndOfRecord = 0x01
} ;
#endregion
#region public data members
/// <summary>
/// File number, see SCSI MMC spec
/// </summary>
public readonly byte FileNumber;
/// <summary>
/// Channel number, see SCSI MMC spec
/// </summary>
public readonly byte ChannelNumber;
/// <summary>
/// Submode, see SCSI MMC spec
/// </summary>
public readonly SubmodeType Submode;
/// <summary>
/// Coding information, see SCSI MMC spec
/// </summary>
public readonly byte CodingInformation;
#endregion
/// <summary>
/// Create subheader data information from subheader data read
/// </summary>
/// <param name="buf">the buffer containing the subheader data</param>
/// <param name="size">the size of the data</param>
public SubheaderData(IntPtr buf, int size)
: base(buf, size)
{
FileNumber = Get8(0);
ChannelNumber = Get8(1);
Submode = (SubmodeType)Get8(2);
CodingInformation = Get8(3);
}
}
}

80
Bwg.Scsi/TocEntry.cs Normal file
View File

@@ -0,0 +1,80 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Scsi
{
/// <summary>
/// A class representing a single TOC entry
/// </summary>
public class TocEntry : Result
{
/// <summary>
/// The ADR value for this track
/// </summary>
public byte Adr;
/// <summary>
/// The control value for this track
/// </summary>
public byte Control;
/// <summary>
/// The track number for this track
/// </summary>
public byte Number;
/// <summary>
/// The start address (in sector) for this track
/// </summary>
public uint StartSector ;
/// <summary>
/// The starting MSF for this track
/// </summary>
public MinuteSecondFrame StartMSF;
/// <summary>
/// Create a new TOC entry
/// </summary>
/// <param name="buffer">the memory buffer holding the TOC</param>
/// <param name="offset">the offset to the TOC entry of interest</param>
/// <param name="size">the overall size of the buffer</param>
/// <param name="mode">time versus lba mode</param>
public TocEntry(IntPtr buffer, int offset, int size, bool mode) : base(buffer, size)
{
byte b = Get8(offset + 1) ;
Adr = (byte)((b >> 4) & 0x0f) ;
Control = (byte)(b & 0x0f) ;
Number = Get8(offset + 2) ;
if (mode)
StartMSF = new MinuteSecondFrame(Get8(offset + 5), Get8(offset + 6), Get8(offset + 7));
else
StartSector = Get32(offset + 4) ;
}
}
}

View File

@@ -0,0 +1,204 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
namespace Bwg.Scsi
{
/// <summary>
/// This data structure contains the results from call ReadTrackInformation() to read
/// data about a track
/// </summary>
public class TrackInformation : Result
{
#region public types
/// <summary>
/// This type represents the data mode for the track
/// </summary>
public enum DataModeType
{
/// <summary>
/// Mode 1 user data (digital data, 2048 bytes per sector)
/// </summary>
Mode1 = 0x01,
/// <summary>
/// Mode 2 user data (digital data, multiple forms)
/// </summary>
Mode2 = 0x02,
/// <summary>
/// Audio data, 2352 bytes of audio data per sector
/// </summary>
Audio = 0x0f
} ;
#endregion
#region public Track Information Members
/// <summary>
///
/// </summary>
public readonly ushort TrackNumber;
/// <summary>
///
/// </summary>
public readonly ushort SessionNumber;
/// <summary>
///
/// </summary>
public readonly bool Copy;
/// <summary>
///
/// </summary>
public readonly bool Damage;
/// <summary>
///
/// </summary>
public readonly byte TrackMode;
/// <summary>
///
/// </summary>
public readonly bool RT;
/// <summary>
///
/// </summary>
public readonly bool Blank;
/// <summary>
///
/// </summary>
public readonly bool Packet;
/// <summary>
///
/// </summary>
public readonly bool FP;
/// <summary>
///
/// </summary>
public readonly DataModeType DataMode;
/// <summary>
///
/// </summary>
public readonly bool LRA_V;
/// <summary>
///
/// </summary>
public readonly bool NWA_V;
/// <summary>
///
/// </summary>
public readonly int TrackStartAddress;
/// <summary>
///
/// </summary>
public readonly int NextWritableAddress;
/// <summary>
///
/// </summary>
public readonly int FreeBlocks;
/// <summary>
///
/// </summary>
public readonly int FixedPacketSize;
/// <summary>
///
/// </summary>
public readonly int TrackSize;
/// <summary>
///
/// </summary>
public readonly int LastRecordedAddress;
/// <summary>
///
/// </summary>
public readonly int ReadCompatLBA;
#endregion
/// <summary>
/// Contruct a read track result object from the raw data.
/// </summary>
/// <param name="buf">the raw data buffer</param>
/// <param name="size">the size of the raw buffer in bytes</param>
public TrackInformation(IntPtr buf, int size) : base(buf, size)
{
TrackNumber = Get16(32, 2) ;
SessionNumber = Get16(33, 3) ;
Copy = GetBit(5,4) ;
Damage = GetBit(5,5) ;
TrackMode = (byte)(Get8(5) & 0x0f) ;
RT = GetBit(6,7) ;
Blank = GetBit(6,6) ;
Packet = GetBit(6,5) ;
FP = GetBit(6,4) ;
DataMode = (DataModeType)(Get8(6) & 0x0f);
LRA_V = GetBit(7, 1) ;
NWA_V = GetBit(7, 0) ;
TrackStartAddress = (int)Get32(8) ;
NextWritableAddress = (int)Get32(12) ;
FreeBlocks = Get32Int(16) ;
FixedPacketSize = Get32Int(20) ;
TrackSize = Get32Int(24) ;
LastRecordedAddress = (int)Get32(28) ;
ReadCompatLBA = (int)Get32(36) ;
}
#region public properties
/// <summary>
/// An alias for fixed packet size depending on the mode of the track.
/// </summary>
public int BlockingFactor
{
get
{
return FixedPacketSize;
}
}
#endregion
}
}

190
Bwg.Scsi/WinDev.cs Normal file
View File

@@ -0,0 +1,190 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace Bwg.Scsi
{
/// <summary>
///
/// </summary>
public unsafe class WinDev : IDisposable
{
//
// External functions required to interface to th
//
[DllImport("Kernel32.dll", SetLastError = true)]
private static extern IntPtr CreateFile(string h, uint acc, uint share, IntPtr sec, uint disp, uint flash, uint temp);
[DllImport("Kernel32.dll", SetLastError = true)]
private static extern bool DeviceIoControl(IntPtr h, uint code, IntPtr inbuf, uint insize, IntPtr outbuf, uint outsize, ref uint returned, IntPtr Overlapped);
[DllImport("Kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr h);
[DllImport("Kernel32.dll", SetLastError = false, CharSet = CharSet.Unicode)]
private static extern uint FormatMessage(uint flags, IntPtr src, uint errcode, uint langid, IntPtr str, uint size, IntPtr vargs) ;
/// <summary>
/// The name of the device
/// </summary>
public string Name
{
get { CheckOpen() ; return m_name; }
}
/// <summary>
/// Returns TRUE if the device is open, FALSE otherwise
/// </summary>
public bool IsOpen { get { return m_handle.ToInt32() != -1; } }
private string m_name;
private IntPtr m_handle;
private uint m_last_error;
/// <summary>
///
/// </summary>
public WinDev()
{
m_handle = new IntPtr(-1);
}
/// <summary>
///
/// </summary>
public uint LastError
{
get
{
return m_last_error;
}
}
/// <summary>
///
/// </summary>
public void Dispose()
{
if (IsOpen)
Close();
}
/// <summary>
///
/// </summary>
public void Close()
{
CloseHandle(m_handle);
}
/// <summary>
///
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
virtual public bool Open(string name)
{
string dname = name;
//
// CreateFile
// name
// accessmode = GenericRead | GenericWrite
UInt32 acc = 0x80000000 | 0x40000000;
m_handle = CreateFile(dname, acc, 0x01, (IntPtr)0, 3, 0x00000080, (uint)0);
if (m_handle.ToInt32() == -1)
{
m_last_error = (uint)Marshal.GetLastWin32Error();
return false;
}
m_name = name;
return true;
}
/// <summary>
///
/// </summary>
/// <param name="letter"></param>
/// <returns></returns>
virtual public bool Open(char letter)
{
string dname = "\\\\.\\" + letter + ":";
return Open(dname);
}
/// <summary>
///
/// </summary>
protected void CheckOpen()
{
if (m_handle.ToInt32() == -1)
throw new Exception("device is not open") ;
}
/// <summary>
///
/// </summary>
/// <param name="code"></param>
/// <param name="inbuf"></param>
/// <param name="insize"></param>
/// <param name="outbuf"></param>
/// <param name="outsize"></param>
/// <param name="ret"></param>
/// <param name="overlapped"></param>
/// <returns></returns>
protected bool Control(uint code, IntPtr inbuf, uint insize, IntPtr outbuf, uint outsize, ref uint ret, IntPtr overlapped)
{
bool b;
CheckOpen() ;
b = DeviceIoControl(m_handle, code, inbuf, insize, outbuf, outsize, ref ret, overlapped);
if (!b)
m_last_error = (uint)Marshal.GetLastWin32Error();
return b;
}
/// <summary>
/// Convert a WIN32 error code to an error string.
/// </summary>
/// <param name="error">the error code to convert</param>
/// <returns>the string for the error code</returns>
static public string Win32ErrorToString(uint error)
{
IntPtr buffer = Marshal.AllocHGlobal(1024) ;
uint ret = FormatMessage(0x1000, IntPtr.Zero, error, 0, buffer, 1024, IntPtr.Zero);
if (ret == 0)
return "cannot find win32 error string for this code (" + error.ToString() + ")";
string str = Marshal.PtrToStringUni(buffer);
str = str.Trim();
Marshal.FreeHGlobal(buffer);
return str;
}
}
}

137
Bwg.Scsi/WriteBuffer.cs Normal file
View File

@@ -0,0 +1,137 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices ;
namespace Bwg.Scsi
{
/// <summary>
/// This class is used to buffer data to the SCSI device when
/// writing large amounts of data to the SCSI device.
/// </summary>
public class WriteBuffer : IDisposable
{
[DllImport("ntdll.dll")]
internal static extern void RtlZeroMemory(IntPtr dest, int size);
[DllImport("ntdll.dll")]
internal static extern void RtlFillMemory(IntPtr dest, int size, byte value);
#region public data members
/// <summary>
/// The size of the buffer associated with this object (in sectors)
/// </summary>
public int BufferSize;
/// <summary>
/// The amount of data stored in the buffer (in sectors)
/// </summary>
public int DataSize;
/// <summary>
/// The size of a sector of data stored in this buffer page
/// </summary>
public int SectorSize;
/// <summary>
/// This contains the logical block address for this block of data
/// </summary>
public long LogicalBlockAddress;
/// <summary>
/// The source of this buffer, used only for debugging
/// </summary>
public string SourceString;
#endregion
#region private data members
/// <summary>
/// The actual buffer memory
/// </summary>
private IntPtr m_buffer_ptr;
#endregion
#region public properties
/// <summary>
/// Returns a buffer pointer to the internal buffer.
/// </summary>
public IntPtr BufferPtr
{
get
{
return m_buffer_ptr;
}
}
#endregion
#region constructors
/// <summary>
/// Create a new buffer object
/// </summary>
/// <param name="size">the size of the buffer</param>
public WriteBuffer(int size)
{
m_buffer_ptr = Marshal.AllocHGlobal((int)size);
BufferSize = size;
LogicalBlockAddress = long.MaxValue;
}
#endregion
#region public methods
/// <summary>
/// Free the memory associated with this buffer object
/// </summary>
public void Dispose()
{
Marshal.FreeHGlobal(m_buffer_ptr);
}
/// <summary>
/// Fill the buffer with all zeros
/// </summary>
public void Zero()
{
RtlZeroMemory(m_buffer_ptr, BufferSize) ;
}
/// <summary>
/// Fill the buffer with data of a specific byte.
/// </summary>
/// <param name="b"></param>
public void Fill(byte b)
{
RtlFillMemory(m_buffer_ptr, BufferSize, b);
}
#endregion
}
}

284
Bwg.Scsi/WriteBufferPool.cs Normal file
View File

@@ -0,0 +1,284 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics;
namespace Bwg.Scsi
{
/// <summary>
/// This class manages a series of buffers that are used to provide data
/// for the burning process.
/// </summary>
public class WriteBufferPool
{
#region private data members
int m_count ;
private Object m_buffer_list_lock;
private IList<WriteBuffer> m_buffer_list;
private Object m_free_list_lock;
private IList<WriteBuffer> m_free_list;
private bool m_end_of_data;
private int m_produced;
private int m_consumed;
private int m_pagesize;
private int m_mult;
private bool m_padded;
#endregion
#region public properties
/// <summary>
/// If this property is true, all data has been pushed into the
/// buffer stream.
/// </summary>
public bool EndOfData
{
get
{
return m_end_of_data;
}
set
{
m_end_of_data = value;
}
}
/// <summary>
/// This property returns the number of 2k pages that have been produced by
/// the generator thread.
/// </summary>
public int Produced
{
get
{
return m_produced;
}
}
/// <summary>
/// This property returns the number of 2k pages that have been consumed
/// by the writer thread.
/// </summary>
public int Consumed
{
get
{
return m_consumed;
}
}
/// <summary>
/// This is the size of the pages stored in this buffer pool, in bytes.
/// </summary>
public int PageSize
{
get
{
return m_pagesize;
}
}
/// <summary>
/// Return the percent of the buffers used
/// </summary>
public double PercentUsed
{
get
{
double v;
lock (m_buffer_list_lock)
{
v = (double)m_buffer_list.Count / (double)m_count * 100.0;
}
return v;
}
}
#endregion
#region constructors
/// <summary>
/// Initialize the buffer stream by creating the buffers
/// </summary>
/// <param name="cnt">the number of buffers to create</param>
/// <param name="size">the size of each buffer</param>
/// <param name="mult">the multiple that each buffer must meet for the device</param>
/// <param name="secsize">the size of the sectors in the buffer in bytes</param>
public WriteBufferPool(int cnt, int size, int mult, int secsize)
{
m_count = cnt ;
m_end_of_data = false;
m_pagesize = size;
m_mult = mult;
//
// If the multiple setting is non-zero, we may have to adjust the page size
//
if (m_mult != 0)
{
int blocks = size / (mult * secsize);
m_pagesize = blocks * mult * secsize;
}
// Used to lock the data buffer list
m_buffer_list_lock = new Object();
// Used to lock the free buffer list
m_free_list_lock = new Object();
// The data buffer list
m_buffer_list = new List<WriteBuffer>();
// THe free buffer list
m_free_list = new List<WriteBuffer>() ;
// Create the buffers and place them all in the
// free list.
for(int i = 0 ; i < cnt ; i++)
m_free_list.Add(new WriteBuffer(size)) ;
m_produced = 0;
m_consumed = 0;
//
// This starts out false and is only set to true if we have to pad
// a buffer to reach an appropriate multiple of the multiple count
// for this device. We should only have to pad the last buffer sent
// to the device. This value is used to detect data being supplied
// after having to pad a data buffer, implying that the data put into
// the queue did not full the buffer and was not at the end of the
// queue.
//
m_padded = false;
}
#endregion
#region public methods
/// <summary>
/// Get a free write buffer to fill with data
/// </summary>
/// <returns>a write buffer</returns>
public WriteBuffer GetFreeBuffer()
{
while (true)
{
lock (m_free_list_lock)
{
if (m_free_list.Count > 0)
{
Debug.Assert(m_padded == false);
WriteBuffer buf = m_free_list[0] ;
m_free_list.RemoveAt(0) ;
return buf;
}
if (m_end_of_data == true)
return null;
}
// Sleep for 10 msec while we wait for buffers to become
// availsble.
Thread.Sleep(1) ;
}
}
/// <summary>
/// Add a buffer to the list
/// </summary>
/// <param name="buf"></param>
public void SendBufferToDevice(WriteBuffer buf)
{
lock (m_buffer_list_lock)
{
if (m_mult != 0 && ((buf.DataSize % m_mult) != 0))
System.Diagnostics.Debug.WriteLine("Added a block of " + buf.DataSize.ToString() + " blocks, not an event multiple") ;
m_buffer_list.Add(buf);
m_produced += (int)buf.DataSize;
}
}
/// <summary>
/// Get the next buffer of data from the steam
/// </summary>
/// <returns>the next buffer stream, or null if all data has been processed</returns>
public WriteBuffer GetNextDataBuffer()
{
while (true)
{
lock (m_buffer_list_lock)
{
if (m_buffer_list.Count > 0)
{
WriteBuffer buf = m_buffer_list[0];
m_buffer_list.RemoveAt(0);
m_consumed += (int)buf.DataSize;
if (m_mult != 0 && (buf.DataSize % m_mult) != 0)
{
//
// The buffer is not an even multiple of the
//
m_padded = true;
buf.DataSize = ((buf.DataSize / m_mult) + 1) * m_mult;
}
return buf;
}
if (m_end_of_data)
return null;
}
// Wait for the reader thread to put data into the buffer
// stream
// Thread.Sleep(1);
}
}
/// <summary>
/// Add a buffer back to the free list to be used again
/// </summary>
/// <param name="buf">the buffer to add to the list</param>
public void FreeWriteBuffer(WriteBuffer buf)
{
lock (m_free_list_lock)
{
m_free_list.Add(buf);
}
}
#endregion
}
}

View File

@@ -0,0 +1,267 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
using System.IO ;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace Bwg.Scsi
{
/// <summary>
/// A stream that pushes the output data through the buffer pool to feed
/// the CD/DVD burner.
/// </summary>
public class WriteBufferStream: Stream
{
#region private data members
/// <summary>
/// The current length of the stream in bytes
/// </summary>
private long m_length ;
/// <summary>
/// The buffer pool, used to get buffers to write into and used to send
/// buffers to the device.
/// </summary>
private WriteBufferPool m_pool;
/// <summary>
/// The current buffer we are writing into
/// </summary>
private WriteBuffer m_buffer;
/// <summary>
/// The size of the sectors that will be sent to the device, in bytes
/// </summary>
private int m_sector_size;
/// <summary>
/// The number of sectors that fit into a single write buffer
/// </summary>
private int m_sector_count;
/// <summary>
/// The index into the current write buffer
/// </summary>
private int m_index;
/// <summary>
/// If true, we are closing
/// </summary>
private bool m_closing;
/// <summary>
/// The logical block address for the stream data
/// </summary>
private long m_lba;
#endregion
#region constructors
/// <summary>
/// This is a stream class that writes the data to the write buffer pool to be sent
/// down to the CD/DVD device.
/// </summary>
/// <param name="pool">the buffer pool to get pages from and send data to</param>
/// <param name="sector_size">the size of the sectors to buffer</param>
/// <param name="lba">the logical block address for the first block from this stream</param>
public WriteBufferStream(WriteBufferPool pool, int sector_size, long lba)
{
m_length = 0;
m_pool = pool;
m_buffer = null;
m_index = 0;
m_sector_size = sector_size;
m_sector_count = m_pool.PageSize / m_sector_size;
m_closing = false;
m_lba = lba;
}
#endregion
#region public properties
/// <summary>
///
/// </summary>
public override bool CanRead { get { return false; } }
/// <summary>
///
/// </summary>
public override bool CanSeek { get { return false; } }
/// <summary>
///
/// </summary>
public override bool CanWrite { get { return true ; } }
/// <summary>
///
/// </summary>
public override long Length { get { return m_length ; } }
/// <summary>
///
/// </summary>
public override long Position
{
get
{
return m_length;
}
set
{
throw new Exception("The method or operation is not implemented.");
}
}
#endregion
#region public methods
/// <summary>
/// This method flushes any existing data to the device.
/// </summary>
public override void Flush()
{
if (m_buffer != null)
{
//
// In general using flush, except when closing the device can be very
// dangerous. This method catches those cases where the result sent to
// the device would be incorrect and asserts accordingly. Basically we
// always send data down to the device in sectors. When we flush we send
// down whatever data is left in the buffer. If we are closing, this has
// the effect of rounding the last bit of data to a sector boundary. If
// we are not closing, it can have the effect of inserting data in the
// middle of the data stream. Flusing only works correctly if we are sitting
// on the boundary of a sector. Therefore, if this assert has fired it means
// we are not closing and not sitting on the boundary of a sector.
//
Debug.Assert(m_closing || (m_index % m_sector_size) == 0);
m_buffer.DataSize = m_index / m_sector_size;
if ((m_index % m_sector_size) != 0)
m_buffer.DataSize++;
m_buffer.SectorSize = m_sector_size;
m_buffer.SourceString = "WriteBufferStream, Flush method";
m_buffer.LogicalBlockAddress = m_lba;
m_lba = long.MaxValue;
m_pool.SendBufferToDevice(m_buffer);
}
}
/// <summary>
///
/// </summary>
/// <param name="offset"></param>
/// <param name="origin"></param>
/// <returns></returns>
public override long Seek(long offset, SeekOrigin origin)
{
throw new Exception("The method or operation is not implemented.");
}
/// <summary>
///
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="count"></param>
/// <returns></returns>
public override int Read(byte[] buffer, int offset, int count)
{
throw new Exception("The method or operation is not implemented.");
}
/// <summary>
///
/// </summary>
/// <param name="buffer"></param>
/// <param name="offset"></param>
/// <param name="count"></param>
public override void Write(byte[] buffer, int offset, int count)
{
while (count > 0)
{
if (m_buffer == null)
{
m_buffer = m_pool.GetFreeBuffer();
m_index = 0;
}
//
// Write up to the end of this buffer
//
int remaining = m_sector_count * m_sector_size - m_index;
if (remaining > count)
remaining = count;
IntPtr dest = new IntPtr(m_buffer.BufferPtr.ToInt32() + m_index);
Marshal.Copy(buffer, offset, dest, remaining);
m_index += remaining;
m_length += remaining;
count -= remaining ;
offset += remaining ;
if (m_index == m_sector_count * m_sector_size)
{
m_buffer.DataSize = m_index / m_sector_size;
m_buffer.SectorSize = m_sector_size;
m_buffer.LogicalBlockAddress = m_lba;
m_buffer.SourceString = "WriteBufferStream, Write method";
m_lba = long.MaxValue;
m_pool.SendBufferToDevice(m_buffer);
m_buffer = null;
}
}
}
/// <summary>
///
/// </summary>
/// <param name="value"></param>
public override void SetLength(long value)
{
throw new Exception("The method or operation is not implemented.");
}
/// <summary>
///
/// </summary>
public override void Close()
{
m_closing = true;
Flush();
base.Close();
}
#endregion
}
}

View File

@@ -0,0 +1,584 @@
//
// BwgBurn - CD-R/CD-RW/DVD-R/DVD-RW burning program for Windows XP
//
// Copyright (C) 2006 by Jack W. Griffin (butchg@comcast.net)
//
// 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 2 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, write to the
//
// Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330,
// Boston, MA 02111-1307 USA
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
namespace Bwg.Scsi
{
/// <summary>
/// This class represents mode page 5, Write Parameters Mode Page
/// </summary>
public class WriteParameterModePage : ModePage
{
#region public types
/// <summary>
/// The type of write (packet/incremental, track, session)
/// </summary>
public enum WriteTypeType : byte
{
/// <summary>
/// Packet or incremental
/// </summary>
PacketIncremental = 0,
/// <summary>
/// Track at once
/// </summary>
TrackAtOnce = 1,
/// <summary>
/// Session at once
/// </summary>
SessionAtOnce = 2,
/// <summary>
/// Raw data recording
/// </summary>
Raw = 3,
/// <summary>
/// Layer jump recording
/// </summary>
LayerJumpRecording = 4
}
/// <summary>
/// The multisession state of the write page
/// </summary>
public enum MultiSessionType : byte
{
/// <summary>
/// No B0 pointer, therefore no next session allowed
/// </summary>
NoNextSession = 0,
/// <summary>
/// B0 pointer equal to 0xFFFFFF, therefore not next session
/// allowed
/// </summary>
CDNoNextSessionFFFF = 1,
/// <summary>
/// Reserved, do not use
/// </summary>
Reserved = 2,
/// <summary>
/// B0 pointer points to next session
/// </summary>
NextSessionAllowed = 3
} ;
/// <summary>
///
/// </summary>
public enum TrackModeType : byte
{
/// <summary>
///
/// </summary>
TwoChannelAudio = 0x00,
/// <summary>
///
/// </summary>
TwoChannelAudioWithPreemphasis = 0x01,
/// <summary>
///
/// </summary>
DataUninterrupted = 0x04,
/// <summary>
///
/// </summary>
DataIncremental = 0x05,
/// <summary>
///
/// </summary>
FourChannelAudio = 0x08,
/// <summary>
///
/// </summary>
FourChannelAudioWithPreemphasis = 0x09,
} ;
/// <summary>
///
/// </summary>
public enum DataBlockTypeType : byte
{
/// <summary>
/// Raw data, 2352 bytes
/// </summary>
RawData = 0,
/// <summary>
/// Raw data with P and Q subchannels, 2368 bytes
/// </summary>
RawDataWithPAndQ = 1,
/// <summary>
/// Raw data with P - W subchannels packed, 2448 bytes
/// </summary>
RawDataWithPToWPacked = 2,
/// <summary>
/// Raw data with P - W subchannels raw, 2448 bytes
/// </summary>
RawDataWithPToWRaw = 3,
/// <summary>
/// Data mode 1, 2048 bytes
/// </summary>
DataMode1 = 8,
/// <summary>
/// Data mode 2, 2336 bytes
/// </summary>
DataMode2 = 9,
/// <summary>
/// Data mode 2, sub-header from write params, 2048 bytes
/// </summary>
DataMode2Form1 = 10,
/// <summary>
/// Data mode 2, sub-header included, 2056 bytes
/// </summary>
DataMode2Form1Subheader = 11,
/// <summary>
/// Data mode 2, form 2, sub-header from write params, 2324 bytes
/// </summary>
DataMode2Form2 = 12,
/// <summary>
/// Data mode 2, form 2, sub-header included, 2332 bytes
/// </summary>
DataMode2Form2Subheader = 13,
} ;
/// <summary>
///
/// </summary>
public enum SessionFormatType : byte
{
/// <summary>
/// CD DA, CD ROM or other data disk
/// </summary>
CDDA_CDROM = 0x00,
/// <summary>
/// CD-I disk
/// </summary>
CD_I = 0x10,
/// <summary>
/// CD-ROM XA Disk
/// </summary>
CDROM_XA = 0x20,
} ;
#endregion
#region constructor
/// <summary>
/// Construct the mode page
/// </summary>
/// <param name="buffer">pointer to a buffer contains the mode page data</param>
/// <param name="size">the size of the buffer area</param>
/// <param name="offset">the offset to the mode page</param>
public WriteParameterModePage(IntPtr buffer, int size, ref ushort offset)
: base(buffer, size, ref offset)
{
}
#endregion
#region public properties
/// <summary>
/// This property is the burn proof settings on this mode page
/// </summary>
public bool BurnProof
{
get
{
return (m_page_data[2] & 0x40) != 0;
}
set
{
if (value)
m_page_data[2] |= 0x40;
else
m_page_data[2] &= 0xbf;
}
}
/// <summary>
/// If true, the link size field is valid. If not true, the link size is assumed to be
/// sever (per the SCSI MMC specification).
/// </summary>
public bool LinkSizeValid
{
get
{
return (m_page_data[2] & 0x20) != 0;
}
set
{
if (value)
m_page_data[2] |= 0x20;
else
m_page_data[2] &= 0xdf;
}
}
/// <summary>
/// If true, any write will not effect the disk, and the write operation will only be a test. If
/// false the writes will go to the disk. This is also known as simulation.
/// </summary>
public bool TestWrite
{
get
{
return (m_page_data[2] & 0x10) != 0;
}
set
{
if (value)
m_page_data[2] |= 0x10;
else
m_page_data[2] &= 0xef;
}
}
/// <summary>
/// This property sets the write type
/// </summary>
public WriteTypeType WriteType
{
get
{
return (WriteTypeType)(m_page_data[2] & 0x0f);
}
set
{
m_page_data[2] &= 0xf0;
m_page_data[2] |= (byte)value;
}
}
/// <summary>
/// This property controls the multi-session mode of the session or track to
/// be burned.
/// </summary>
public MultiSessionType MultiSession
{
get
{
return (MultiSessionType)((m_page_data[3] >> 6) & 0x03);
}
set
{
Debug.Assert(value != MultiSessionType.Reserved);
m_page_data[3] &= 0x3F;
m_page_data[3] |= (byte)((byte)value << 6);
}
}
/// <summary>
/// This property controls whether the write mode is fixed packet. This only applies
/// if the write type is set to Packet/Incremental.
/// </summary>
public bool FixedPacket
{
get
{
return (m_page_data[3] & 0x20) != 0;
}
set
{
if (value)
m_page_data[3] |= 0x20;
else
m_page_data[3] &= 0xdf;
}
}
/// <summary>
/// If true and the media is CD, SCMS copy protection is enabled.
/// </summary>
public bool Copy
{
get
{
return (m_page_data[3] & 0x10) != 0;
}
set
{
if (value)
m_page_data[3] |= 0x10;
else
m_page_data[3] &= 0xef;
}
}
/// <summary>
/// The track mode. This should be 5 for DVD media, and is the
/// </summary>
public TrackModeType TrackMode
{
get
{
return (TrackModeType)(m_page_data[3] & 0x0d);
}
set
{
m_page_data[3] &= 0xf2;
m_page_data[3] |= (byte)value;
}
}
/// <summary>
/// If true, digital copy if premitted of the content, otherwise it is not.
/// </summary>
public bool DigitalCopyPermitted
{
get
{
return (m_page_data[3] & 0x02) != 0;
}
set
{
if (value)
m_page_data[3] |= 0x02;
else
m_page_data[3] &= 0xfd;
}
}
/// <summary>
///
/// </summary>
public DataBlockTypeType DataBlockType
{
get
{
return (DataBlockTypeType)(m_page_data[4] & 0x0f);
}
set
{
m_page_data[4] &= 0xf0;
m_page_data[4] |= (byte)value;
}
}
/// <summary>
///
/// </summary>
public byte LinkSize
{
get
{
return m_page_data[5];
}
set
{
m_page_data[5] = value;
}
}
/// <summary>
///
/// </summary>
public byte HostApplicationCode
{
get
{
return (byte)(m_page_data[7] & 0x3f);
}
set
{
m_page_data[7] &= 0xc0;
m_page_data[7] |= (byte)(value & 0x3f);
}
}
/// <summary>
///
/// </summary>
public SessionFormatType SessionFormat
{
get
{
return (SessionFormatType)m_page_data[8];
}
set
{
m_page_data[8] = (byte)value;
}
}
/// <summary>
///
/// </summary>
public int PacketSize
{
get
{
return ModeGet32(10);
}
set
{
ModeSet32(10, value);
}
}
/// <summary>
///
/// </summary>
public ushort AudioPauseLength
{
get
{
return ModeGet16(14);
}
set
{
ModeSet16(14, value);
}
}
/// <summary>
///
/// </summary>
public byte[] MediaCatalogNumber
{
get
{
byte[] num = new byte[16];
for (int i = 0; i < 16; i++)
num[i] = m_page_data[16 + i];
return num;
}
set
{
Debug.Assert(value.GetLength(0) == 16);
for (int i = 0; i < 16; i++)
m_page_data[16 + i] = value[i];
}
}
/// <summary>
///
/// </summary>
public byte[] InternationalStandardRecordingCode
{
get
{
byte[] num = new byte[16];
for (int i = 0; i < 16; i++)
num[i] = m_page_data[32 + i];
return num;
}
set
{
Debug.Assert(value.GetLength(0) == 16);
for (int i = 0; i < 16; i++)
m_page_data[32 + i] = value[i];
}
}
/// <summary>
///
/// </summary>
public byte SubHeaderByte0
{
get
{
return m_page_data[48];
}
set
{
m_page_data[48] = value;
}
}
/// <summary>
///
/// </summary>
public byte SubHeaderByte1
{
get
{
return m_page_data[49];
}
set
{
m_page_data[49] = value;
}
}
/// <summary>
///
/// </summary>
public byte SubHeaderByte2
{
get
{
return m_page_data[50];
}
set
{
m_page_data[50] = value;
}
}
/// <summary>
///
/// </summary>
public byte SubHeaderByte3
{
get
{
return m_page_data[51];
}
set
{
m_page_data[51] = value;
}
}
#endregion
}
}

View File

@@ -0,0 +1,101 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{9253A314-1821-42BF-B02F-2BF986B1765D}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CUETools.Ripper.Console</RootNamespace>
<AssemblyName>CUETools.Ripper.Console</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<OutputPath>..\bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\bin\win32\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>..\bin\win32\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AudioCodecsDotNet\AudioCodecsDotNet.csproj">
<Project>{6458A13A-30EF-45A9-9D58-E5031B17BEE2}</Project>
<Name>AudioCodecsDotNet</Name>
</ProjectReference>
<ProjectReference Include="..\CUETools.Ripper.SCSI\CUETools.Ripper.SCSI.csproj">
<Project>{8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}</Project>
<Name>CUETools.Ripper.SCSI</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,146 @@
// ****************************************************************************
//
// CUERipper
// Copyright (C) 2008 Gregory S. Chudov (gchudov@gmail.com)
//
// 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 2 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, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// ****************************************************************************
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using CUETools.Ripper.SCSI;
using AudioCodecsDotNet;
namespace CUETools.ConsoleRipper
{
class Program
{
static void Usage()
{
Console.WriteLine("Usage : CUETools.Ripper.Console.exe <file.wav>");
Console.WriteLine();
}
static void Main(string[] args)
{
string programVersion = "CUERipper v1.9.3";
Console.SetOut(Console.Error);
Console.WriteLine("{0}", programVersion);
Console.WriteLine("This is free software under the GNU GPLv3+ license; There is NO WARRANTY, to");
Console.WriteLine("the extent permitted by law. <http://www.gnu.org/licenses/> for details.");
if (args.Length < 1)
{
Usage();
return;
}
string destFile = args[0];
#if !DEBUG
try
#endif
{
CDDriveReader audioSource = new CDDriveReader();
audioSource.Open('D');
StreamWriter logWriter = new StreamWriter(Path.ChangeExtension(destFile, ".log"));
logWriter.WriteLine("{0}", programVersion);
logWriter.WriteLine();
logWriter.WriteLine("Extraction logfile from {0}",DateTime.Now);
logWriter.WriteLine();
logWriter.WriteLine("Used drive : {0}", audioSource.Path);
logWriter.WriteLine();
logWriter.WriteLine("TOC of the extracted CD");
logWriter.WriteLine();
logWriter.WriteLine(" Track | Start | Length | Start sector | End sector");
logWriter.WriteLine(" ---------------------------------------------------------");
for (int track = 0; track < audioSource.TOC.tracks.Count; track++)
logWriter.WriteLine("{0,9} | {1,8} | {2,8} | {3,9} | {4,9}",
audioSource.TOC.tracks[track].Number,
audioSource.TOC.tracks[track].Start.MSF,
audioSource.TOC.tracks[track].Length.MSF,
audioSource.TOC.tracks[track].Start.Sector,
audioSource.TOC.tracks[track].End.Sector);
logWriter.Close();
//audioSource.Close();
//return;
bool toStdout = false;
WAVWriter audioDest = new WAVWriter(destFile, audioSource.BitsPerSample, audioSource.ChannelCount, audioSource.SampleRate, toStdout ? Console.OpenStandardOutput() : null);
int[,] buff = new int[audioSource.BestBlockSize, audioSource.ChannelCount];
Console.WriteLine("Filename : {0}", destFile);
Console.WriteLine("File Info : {0}kHz; {1} channel; {2} bit; {3}", audioSource.SampleRate, audioSource.ChannelCount, audioSource.BitsPerSample, TimeSpan.FromSeconds(audioSource.Length * 1.0 / audioSource.SampleRate));
audioDest.FinalSampleCount = (long) audioSource.Length;
DateTime start = DateTime.Now;
TimeSpan lastPrint = TimeSpan.FromMilliseconds(0);
do
{
uint samplesRead = audioSource.Read(buff, Math.Min((uint)buff.GetLength(0), (uint)audioSource.Remaining));
if (samplesRead == 0) break;
audioDest.Write(buff, samplesRead);
TimeSpan elapsed = DateTime.Now - start;
if ((elapsed - lastPrint).TotalMilliseconds > 60)
{
Console.Error.Write("\rProgress : {0:00}%; {1:0.00}x; {2}/{3}",
100.0 * audioSource.Position / audioSource.Length,
audioSource.Position / elapsed.TotalSeconds / audioSource.SampleRate,
elapsed,
TimeSpan.FromMilliseconds(elapsed.TotalMilliseconds / audioSource.Position * audioSource.Length)
);
lastPrint = elapsed;
}
} while (true);
TimeSpan totalElapsed = DateTime.Now - start;
Console.Error.Write("\r \r");
Console.WriteLine("Results : {0:0.00}x; {1}",
audioSource.Length / totalElapsed.TotalSeconds / audioSource.SampleRate,
totalElapsed
);
audioDest.Close();
StreamWriter cueWriter = new StreamWriter(Path.ChangeExtension(destFile, ".cue"));
cueWriter.WriteLine("REM DISCID {0}", audioSource.TOC._cddbId);
cueWriter.WriteLine("REM ACCURATERIPID {0}", audioSource.TOC._ArId);
cueWriter.WriteLine("REM COMMENT \"{0}\"", programVersion);
if (audioSource.TOC._catalog != null)
cueWriter.WriteLine("CATALOG {0}", audioSource.TOC._catalog);
cueWriter.WriteLine("FILE \"{0}\" WAVE", destFile);
for (int track = 0; track < audioSource.TOC.tracks.Count; track++)
{
cueWriter.WriteLine(" TRACK {0:00} AUDIO", audioSource.TOC.tracks[track].Number);
for (int index = 0; index < audioSource.TOC.tracks[track].indexes.Count; index ++)
cueWriter.WriteLine(" INDEX {0:00} {1}", audioSource.TOC.tracks[track].indexes[index].Index, audioSource.TOC.tracks[track].indexes[index].MSF);
}
cueWriter.Close();
audioSource.Close();
}
#if !DEBUG
catch (Exception ex)
{
Console.WriteLine();
Console.WriteLine("Error: {0}", ex.Message);
Console.WriteLine("{0}", ex.StackTrace);
}
#endif
}
}
}

View File

@@ -0,0 +1,33 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("CUETools.Ripper.Console")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("CUETools.Ripper.Console")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2008")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("2d93abce-7d63-4ac0-aa16-faef013f987e")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,109 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CUETools.Ripper.SCSI</RootNamespace>
<AssemblyName>CUETools.Ripper.SCSI</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<OutputPath>..\bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\bin\win32\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>..\bin\win32\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleAssemblies>C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules</CodeAnalysisRuleAssemblies>
<CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
<CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
<ErrorReport>prompt</ErrorReport>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="SCSIDrive.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AudioCodecsDotNet\AudioCodecsDotNet.csproj">
<Project>{6458A13A-30EF-45A9-9D58-E5031B17BEE2}</Project>
<Name>AudioCodecsDotNet</Name>
</ProjectReference>
<ProjectReference Include="..\Bwg.Logging\Bwg.Logging.csproj">
<Project>{F2DFEB00-BB35-4665-85EA-CB8C7729A6B7}</Project>
<Name>Bwg.Logging</Name>
</ProjectReference>
<ProjectReference Include="..\Bwg.Scsi\Bwg.Scsi.csproj">
<Project>{A05B6AA6-0EC3-495D-BCC4-ECE1210071A8}</Project>
<Name>Bwg.Scsi</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("CUETools.Ripper.SCSI")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("CUETools.Ripper.SCSI")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2008")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("f80546ea-7f0c-4a5a-bcf3-fe53820a5bfe")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,452 @@
// ****************************************************************************
//
// CUERipper
// Copyright (C) 2008 Gregory S. Chudov (gchudov@gmail.com)
//
// 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 2 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, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// ****************************************************************************
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using Bwg.Scsi;
using Bwg.Logging;
using AudioCodecsDotNet;
namespace CUETools.Ripper.SCSI
{
/// <summary>
///
/// </summary>
public class CDDriveReader : IAudioSource
{
byte[] cdtext = null;
private Device m_device;
uint _sampleOffset = 0;
uint _samplesInBuffer = 0;
uint _samplesBufferOffset = 0;
uint _samplesBufferSector = 0;
const int CB_AUDIO = 588 * 4 + 16;
const int NSECTORS = 32;
int _currentTrack = -1, _currentIndex = -1, _currentTrackActualStart = -1;
Logger m_logger = null;
CDImage _toc;
public CDImage TOC
{
get
{
return _toc;
}
}
public CDDriveReader()
{
}
public bool Open(char Drive)
{
Device.CommandStatus st;
// Open the base device
m_device = new Device(m_logger);
if (!m_device.Open(Drive))
throw new Exception("SCSI error");
//// Open/Initialize the driver
//Drive m_drive = new Drive(dev);
//DiskOperationError status = m_drive.Initialize();
//if (status != null)
// throw new Exception("SCSI error");
// {
//Drive.FeatureState readfeature = m_drive.GetFeatureState(Feature.FeatureType.CDRead);
//if (readfeature == Drive.FeatureState.Error || readfeature == Drive.FeatureState.NotPresent)
// throw new Exception("SCSI error");
// }{
//st = m_device.GetConfiguration(Device.GetConfigType.OneFeature, 0, out flist);
//if (st != Device.CommandStatus.Success)
// return CreateErrorObject(st, m_device);
//Feature f = flist.Features[0];
//ParseProfileList(f.Data);
// }
SpeedDescriptorList speed_list;
st = m_device.GetSpeed(out speed_list);
if (st != Device.CommandStatus.Success)
throw new Exception("SCSI error");
st = m_device.SetCdSpeed(Device.RotationalControl.CLVandNonPureCav, Device.OptimumSpeed, Device.OptimumSpeed);
if (st != Device.CommandStatus.Success)
throw new Exception("SCSI error");
IList<TocEntry> toc;
st = m_device.ReadToc((byte)0, false, out toc);
if (st != Device.CommandStatus.Success)
throw new Exception("SCSI error");
st = m_device.ReadCDText(out cdtext);
// new CDTextEncoderDecoder
_toc = new CDImage(toc[toc.Count - 1].StartSector);
uint cddbDiscId = 0;
uint discId1 = 0;
uint discId2 = 0;
for (int iTrack = 0; iTrack < toc.Count - 1; iTrack++)
{
_toc.tracks.Add(new CDTrack((uint)iTrack + 1, toc[iTrack].StartSector,
toc[iTrack + 1].StartSector - toc[iTrack].StartSector));
discId1 += toc[iTrack].StartSector;
discId2 += (toc[iTrack].StartSector == 0 ? 1 : toc[iTrack].StartSector) * ((uint)iTrack + 1);
cddbDiscId += sumDigits((uint)(toc[iTrack].StartSector / 75) + 2);
}
discId1 += toc[toc.Count - 1].StartSector;
discId2 += (toc[toc.Count - 1].StartSector == 0 ? 1 : toc[toc.Count - 1].StartSector) * ((uint)toc.Count);
discId1 &= 0xFFFFFFFF;
discId2 &= 0xFFFFFFFF;
cddbDiscId = (((cddbDiscId % 255) << 24) +
(((uint)(toc[toc.Count - 1].StartSector / 75) - (uint)(toc[0].StartSector / 75)) << 8) +
(uint)(toc.Count - 1)) & 0xFFFFFFFF;
_toc._cddbId = string.Format("{0:X8}", cddbDiscId);
_toc._ArId = string.Format("{0:x8}-{1:x8}-{2:x8}", discId1, discId2, cddbDiscId);
return true;
}
public void Close()
{
_toc = null;
}
public int BestBlockSize
{
get
{
return Math.Min(m_device.MaximumTransferLength / CB_AUDIO, NSECTORS) * 588;
}
}
public unsafe uint Read(int[,] buff, uint sampleCount)
{
if (_toc == null)
throw new Exception("invalid TOC");
if (_sampleOffset >= (uint)Length)
return 0;
if (_sampleOffset + sampleCount > Length)
sampleCount = (uint)Length - _sampleOffset;
uint pos = 0;
if (_samplesInBuffer > 0)
{
uint samplesRead = Math.Min(_samplesInBuffer, sampleCount);
AudioSamples.BytesToFLACSamples_16(_sectorBuffer, (int)(_samplesBufferSector * (588 * 4 + 16) + _samplesBufferOffset * 4), buff, (int)pos, samplesRead, 2);
pos += samplesRead;
sampleCount -= samplesRead;
_sampleOffset += samplesRead;
if (sampleCount == 0)
{
_samplesInBuffer -= samplesRead;
_samplesBufferOffset += samplesRead;
return pos;
}
_samplesInBuffer = 0;
_samplesBufferOffset = 0;
_samplesBufferSector = 0;
}
// if (_sampleOffset < PreGapLength && !_overreadIntoPreGap ... ?
int firstSector = (int)_sampleOffset / 588;
int lastSector = (int)(_sampleOffset + sampleCount + 577) / 588;
for (int sector = firstSector; sector < lastSector; sector += NSECTORS)
{
int Sectors2Read = ((sector + NSECTORS) < lastSector) ? NSECTORS : (lastSector - sector);
fixed (byte* data = _sectorBuffer)
{
Device.CommandStatus st = m_device.ReadCDAndSubChannel(2, 1, true, (uint)sector, (uint)Sectors2Read, (IntPtr)((void*)data), Sectors2Read * (2352 + 16));
if (st != Device.CommandStatus.Success)
throw new Exception("SCSI error");
}
for (int iSector = 0; iSector < Sectors2Read; iSector++)
{
uint samplesRead = Math.Min(sampleCount, 588U) - (_sampleOffset % 588);
AudioSamples.BytesToFLACSamples_16(_sectorBuffer, iSector * (588 * 4 + 16) + ((int)_sampleOffset % 588) * 4, buff, (int)pos, samplesRead, 2);
{
int q_pos = (iSector + 1) * (588 * 4 + 16) - 16;
int ctl = _sectorBuffer[q_pos + 0] >> 4;
int adr = _sectorBuffer[q_pos + 0] & 7;
bool preemph = (ctl == 1);
switch (adr)
{
case 1: // current position
{
int iTrack = fromBCD(_sectorBuffer[q_pos + 1]);
int iIndex = fromBCD(_sectorBuffer[q_pos + 2]);
if (iTrack != _currentTrack)
{
_currentTrack = iTrack;
_currentTrackActualStart = sector + iSector;
_currentIndex = iIndex;
if (_currentIndex == 1)
_toc.tracks[iTrack - 1].indexes.Add(new CDTrackIndex(1, _toc.tracks[iTrack - 1].Start.Sector));
else if (_currentIndex != 0)
throw new Exception("invalid index");
}
else
if (iIndex != _currentIndex)
{
if (iIndex != _currentIndex + 1)
throw new Exception("invalid index");
_currentIndex = iIndex;
if (_currentIndex == 1)
{
int pregap = sector + iSector - _currentTrackActualStart;
_toc.tracks[iTrack - 1].indexes.Add(new CDTrackIndex(0, (uint)(_toc.tracks[iTrack - 1].Start.Sector - pregap)));
_currentTrackActualStart = sector + iSector;
}
_toc.tracks[iTrack - 1].indexes.Add(new CDTrackIndex((uint)iIndex, (uint)(_toc.tracks[iTrack - 1].Start.Sector + sector + iSector - _currentTrackActualStart)));
_currentIndex = iIndex;
}
break;
}
case 2: // catalog
if (_toc._catalog == null)
{
StringBuilder catalog = new StringBuilder();
for (int i = 1; i < 8; i++)
catalog.AppendFormat("{0:x2}", _sectorBuffer[q_pos + i]);
_toc._catalog = catalog.ToString(0, 13);
}
break;
case 3: //isrc
break;
}
}
pos += samplesRead;
sampleCount -= samplesRead;
_sampleOffset += samplesRead;
if (sampleCount == 0)
{
_samplesBufferSector = (uint)iSector;
_samplesBufferOffset = samplesRead;
_samplesInBuffer = 588U - samplesRead;
return pos;
}
}
}
return pos;
}
public ulong Length
{
get
{
if (_toc == null)
throw new Exception("invalid TOC");
return (ulong)588 * _toc.Length.Sector;
}
}
public int BitsPerSample
{
get
{
return 16;
}
}
public int ChannelCount
{
get
{
return 2;
}
}
public int SampleRate
{
get
{
return 44100;
}
}
public NameValueCollection Tags
{
get
{
return null;
}
set
{
}
}
public string Path
{
get
{
return m_device.Name;
}
}
public ulong Position
{
get
{
return _sampleOffset;
}
set
{
_sampleOffset = (uint)value;
}
}
public ulong Remaining
{
get
{
return Length - Position;
}
}
byte[] _sectorBuffer = new byte[CB_AUDIO * NSECTORS];
private int fromBCD(byte hex)
{
return (hex >> 4) * 10 + (hex & 15);
}
private uint sumDigits(uint n)
{
uint r = 0;
while (n > 0)
{
r = r + (n % 10);
n = n / 10;
}
return r;
}
}
public class CDTrackIndex
{
public CDTrackIndex(uint index, uint sector)
{
_sector = sector;
_index = index;
}
public uint Sector
{
get
{
return _sector;
}
}
public uint Index
{
get
{
return _index;
}
}
public string MSF
{
get
{
return new MinuteSecondFrame(_sector).ToString("M:S:F");
}
}
uint _sector;
uint _index;
}
public class CDTrack
{
public CDTrack(uint number, uint start, uint length)
{
_number = number;
_start = start;
_length = length;
indexes = new List<CDTrackIndex>();
}
public CDTrackIndex Start
{
get
{
return new CDTrackIndex(0, _start);
}
}
public CDTrackIndex Length
{
get
{
return new CDTrackIndex(0, _length);
}
}
public CDTrackIndex End
{
get
{
return new CDTrackIndex(0, _start + _length - 1);
}
}
public uint Number
{
get
{
return _number;
}
}
public IList<CDTrackIndex> indexes;
uint _start;
uint _length;
uint _number;
}
public class CDImage
{
public CDImage(uint length)
{
tracks = new List<CDTrack>();
_length = length;
}
public IList<CDTrack> tracks;
public CDTrackIndex Length
{
get
{
return new CDTrackIndex(0, _length);
}
}
public string _catalog;
public string _cddbId;
public string _ArId;
uint _length;
}
}