Home     |     .Net Programming    |     cSharp Home    |     Sql Server Home    |     Javascript / Client Side Development     |     Ajax Programming

Ruby on Rails Development     |     Perl Programming     |     C Programming Language     |     C++ Programming     |     IT Jobs

Python Programming Language     |     Laptop Suggestions?    |     TCL Scripting     |     Fortran Programming     |     Scheme Programming Language


 
 
Cervo Technologies
The Right Source to Outsource

MS Dynamics CRM 3.0

C# Programming

How to use the DataBuffer of SCSI_PASS_THROUGH_DIRECT in c# ?


Hi All;

  I need to send a READ command to CD-ROM drive by SCSI_PASS_THROUGH_DIRECT.

  int inputSize = Marshal.SizeOf(typeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
  IntPtr input = Marshal.AllocHGlobal(inputSize);
  Marshal.StructureToPtr(sptdwb, input, true)

  In my code, the  Marshal.StructureToPtr(sptdwb, input, true) will return
error, because the sptdwb and input size are not equal, then the PVOID
DataBuffer can't be access.

  Do you have any ideas ?

Sorry, modify some message.

  I need to send a READ command to CD-ROM drive by SCSI_PASS_THROUGH_DIRECT.
As SCSI_PASS_THROUGH_DIRECT struct:

typedef struct _SCSI_PASS_THROUGH_DIRECT {
  USHORT  Length;
  UCHAR  ScsiStatus;
  UCHAR  PathId;
  UCHAR  TargetId;
  UCHAR  Lun;
  UCHAR  CdbLength;
  UCHAR  SenseInfoLength;
  UCHAR  DataIn;
  ULONG  DataTransferLength;
  ULONG  TimeOutValue;
  PVOID  DataBuffer;
  ULONG  SenseInfoOffset;
  UCHAR  Cdb[16];

}SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;

  int inputSize = Marshal.SizeOf(typeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
  IntPtr input = Marshal.AllocHGlobal(inputSize);
  Marshal.StructureToPtr(sptdwb, input, true)

  In my code, the  Marshal.StructureToPtr(sptdwb, input, true) will return
error, because I need to modify the DataBuffer size for each command, the
sptdwb and input size will not equal, then the PVOID DataBuffer can't be
access.

  Do you have any ideas ?

  Thank you for your help !!

-----------------------------------------------Reply-----------------------------------------------

We need your SCSI_PASS_THROUGH_DIRECT structure declaration in C# to help
you with this.

Willy.

-----------------------------------------------Reply-----------------------------------------------

Willy Denoyette [MVP] wrote:
>> Sorry, modify some message.

>[quoted text clipped - 30 lines]

>>  Thank you for your help !!

>We need your SCSI_PASS_THROUGH_DIRECT structure declaration in C# to help
>you with this.

>Willy.

Thank you Willy!

[StructLayout(LayoutKind.Sequential)]
    class SCSI_PASS_THROUGH_DIRECT
    {

        public UInt16 Length = (UInt16)Marshal.SizeOf(typeof
(SCSI_PASS_THROUGH_DIRECT));
        public byte ScsiStatus = 0;
        public byte PathId= 0;
        public byte TargetId= 0;
        public byte Lun = 0;
        public byte CdbLength = 12;
        public byte SenseInfoLength = 24;
        public byte DataIn ;
        public Int32 DataTransferLength;
        public Int32 TimeOutValue= 30;
        public IntPtr DataBuffer;  
        public UInt32 SenseInfoOffset = (UInt32)Marshal.OffsetOf(typeof
(SCSI_PASS_THROUGH_WITH_BUFFERS), "ucSenseBuf");
        [MarshalAs(UnmanagedType.ByValArray,SizeConst = 16)]
        public byte[] Cdb = new byte[16];
    }

FYI.

--
Message posted via DotNetMonster.com
http://www.dotnetmonster.com/Uwe/Forums.aspx/dotnet-csharp/200705/1

-----------------------------------------------Reply-----------------------------------------------

--
Message posted via DotNetMonster.com
http://www.dotnetmonster.com/Uwe/Forums.aspx/dotnet-csharp/200705/1

-----------------------------------------------Reply-----------------------------------------------
Sorry, modify some error message !

[StructLayout(LayoutKind.Sequential)]
   class SCSI_PASS_THROUGH_DIRECT
   {

       public UInt16 Length = (UInt16)Marshal.SizeOf(typeof
(SCSI_PASS_THROUGH_DIRECT));
       public byte ScsiStatus = 0;
       public byte PathId= 0;
       public byte TargetId= 0;
       public byte Lun = 0;
       public byte CdbLength = 12;
       public byte SenseInfoLength = 24;
       public byte DataIn ;
       public Int32 DataTransferLength;
       public Int32 TimeOutValue= 30;
       public IntPtr DataBuffer;  
       public UInt32 SenseInfoOffset = (UInt32)Marshal.OffsetOf(typeof
(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFERS), "ucSenseBuf");
       [MarshalAs(UnmanagedType.ByValArray,SizeConst = 16)]
       public byte[] Cdb = new byte[16];
   }

--
Message posted via DotNetMonster.com
http://www.dotnetmonster.com/Uwe/Forums.aspx/dotnet-csharp/200705/1

-----------------------------------------------Reply-----------------------------------------------

"Marce via DotNetMonster.com" <u34601@uwe> wrote in message
news:72e5d0179de3d@uwe...

You have to take care that you pass a correctly filled and aligned
structure, the buffers need to be fields in the same marshaled structure
(here SCSI_PASS_THROUGH_WITH_BUFFERS).

Here is how you could declare the structure and the
SCSI_PASS_THROUGH_WITH_BUFFERS class.

 [StructLayout(LayoutKind.Sequential)]
 struct SCSI_PASS_THROUGH_DIRECT
 {
     public short Length;
     public byte ScsiStatus;
     public byte PathId;
     public byte TargetId;
     public byte Lun;
     public byte CdbLength;
     public byte SenseInfoLength;
     public byte DataIn ;
     public int DataTransferLength;
     public int TimeOutValue;
     public IntPtr DataBufferOffset;
     public uint SenseInfoOffset;
     [MarshalAs(UnmanagedType.ByValArray,SizeConst = 16)]
     public byte[] Cdb;
 };

 [StructLayout(LayoutKind.Sequential)]
 class SCSI_PASS_THROUGH_WITH_BUFFERS
 {
  internal SCSI_PASS_THROUGH_DIRECT sptd = new SCSI_PASS_THROUGH_DIRECT();
    // // adapt size to suit your needs!!!!!!
  [MarshalAs(UnmanagedType.ByValArray,SizeConst = 18)]
  internal byte[] sense ;
    // adapt to suit your needs!!!!!!!
  [MarshalAs(UnmanagedType.ByValArray,SizeConst = 36)]
  internal byte[] data ;
 };

// usage ...

   SCSI_PASS_THROUGH_WITH_BUFFERS info = new
SCSI_PASS_THROUGH_WITH_BUFFERS();
   info.sptd.Cdb = new byte[16];
   info.sense = new byte[18]; // adapt to suit your needs!!!!!!
   info.data = new byte[36];    // adapt to suit your needs!!!!!!

   info.sptd.Length = (short)Marshal.SizeOf(info.sptd);
   info.sptd.SenseInfoOffset =
(uint)Marshal.OffsetOf(typeof(SCSI_PASS_THROUGH_WITH_BUFFERS), "sense");
   info.sptd.SenseInfoLength = (byte)info.sense.Length;
   info.sptd.DataTransferLength = info.data.Length;
   info.sptd.DataBufferOffset =
Marshal.OffsetOf(typeof(SCSI_PASS_THROUGH_WITH_BUFFERS), "data");
   info.sptd.TimeOutValue = 30;
   info.sptd.DataIn = SCSI_IOCTL_DATA_IN;
// initilalize the cdb
   info.sptd.CdbLength = x; // length of CDB
   info.sptd.Cdb[0] = ...;
   ....

   IntPtr inpBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(info));
   Marshal.StructureToPtr(info, inpBuffer, false);
    // call DeviceIoControl passing the buffer inpBuffer as inp buffer
and/or output buffer depending on the command.
   int ret = DeviceIoControl(...., inpBuffer, Marshal.SizeOf(info), ...);
...

Willy.

-----------------------------------------------Reply-----------------------------------------------

Thanks Willy.

It works ok by SCSI_PASS_THROUGH_WITH_BUFFERS, and the data buffer size need
to fixed.
As this:
 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 30*2048)]
        public byte[] ucDataBuf = new byte[30 * 2048];

But In the SCSI_PASS_THROUGH_DIRECT_BUFFERS structure, the DataBuffer is
IntPtr point.
How can I send a ATAPI cmd with databuffer by
SCSI_PASS_THROUGH_DIRECT_BUFFERS ?

--
Message posted via http://www.dotnetmonster.com

-----------------------------------------------Reply-----------------------------------------------

"Marce via DotNetMonster.com" <u34601@uwe> wrote in message
news:72f0129368a0e@uwe...

Ok, if you need to pass such large buffers you will have to use the
IOCTL_SCSI_PASS_THROUGH_DIRECT ioctl command and define your structures as
follows:

 [StructLayout(LayoutKind.Sequential)]
 struct SCSI_PASS_THROUGH_DIRECT
 {
     public short Length;
     public byte ScsiStatus;
     public byte PathId;
     public byte TargetId;
     public byte Lun;
     public byte CdbLength;
     public byte SenseInfoLength;
     public byte DataIn ;
     public int DataTransferLength;
     public int TimeOutValue;
     public IntPtr DataBuffer;  // note this is now interpreted as a
pointer, not an offset!!
     public uint SenseInfoOffset;
     [MarshalAs(UnmanagedType.ByValArray,SizeConst = 16)]
     public byte[] Cdb;
 };
 [StructLayout(LayoutKind.Sequential)]
 class SCSI_PASS_THROUGH_DIRECT_WITH_BUFFERS
 {
  internal SCSI_PASS_THROUGH_DIRECT sptd = new SCSI_PASS_THROUGH_DIRECT();
  [MarshalAs(UnmanagedType.ByValArray,SizeConst = 18)]
  internal byte[] sense ;
 };

in your code, you'll have to allocate the data buffer like this:

SCSI_PASS_THROUGH_DIRECT_WITH_BUFFERS info = new
SCSI_PASS_THROUGH_DIRECT_WITH_BUFFERS();
...
info.sptd.DataBuffer = Marshal.AllocHGlobal(30 * 2048); // allocate
correctly aligned buffer

marshal the data to/from  the buffer using Marshal.Copy, and...
use the IOCTL_SCSI_PASS_THROUGH_DIRECT command in the call to the
DeviceIOControl API like this:

const int IOCTL_SCSI_PASS_THROUGH_DIRECT = 0x4D014; // IOCTL cmd
...
DeviceIoControl(fh, IOCTL_SCSI_PASS_THROUGH_DIRECT,....

don't forget to Marshal.FreeHGlobal when done with the unmanaged buffer!!

Willy.

-----------------------------------------------Reply-----------------------------------------------

Dear Willy:
Thank you for your help!
This help me more !

--
Message posted via DotNetMonster.com
http://www.dotnetmonster.com/Uwe/Forums.aspx/dotnet-csharp/200705/1
Add to del.icio.us | Digg this | Stumble it | Powered by Megasolutions Inc