# SCSI programming (pointer help..)



## Dr.Zoidberg (Nov 21, 2008)

Hello, I'm having some problems with pointers whilst trying to program scsi commands. The error comes from:

"driveInquiry.OperationCode6 = "SCSIOP_INQUIRY"; /*ERROR OCCURS HERE*/"

error - c71 assignment makers integer from pointer without cast

I got a similar section of code compiling further down in the SCSI pass through direct structure however I dont think its the correct way, which wont work.

"UCHAR dataIn;
strcpy(&dataIn, "SCSI_IOCTL_DATA_IN"); /*THIS ISNT CORRECT EITHER*/"

I had the code compiling but it wasnt returning drive info. I did this by putting pointers struct's at the top of the code which isnt correct.

Any help would be appriciated.

Thanks!


```
#include <stdlib.h>   
#include <string.h> 
#include <stdio.h>  
#include <windows.h>
#include <winioctl.h>

      
        //*Reference region code - chech data types - UCHAR etc...
        typedef struct _inquiryCDB{
          UCHAR OperationCode6;    //* 0x12 - SCSIOP_INQUIRY
          UCHAR Reserved1 : 5;
          UCHAR LogicalUnitNumber : 3;
          UCHAR PageCode;
          UCHAR IReserved;
          UCHAR AllocationLength;
          UCHAR Control;
        } inquiryCDB;
        
        //Check pointers - shouldnt be here
        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;
          void * DataBuffer;
          ULONG SenseInfoOffset;
          UCHAR Cdb[16];
        } SCSI_PASS_THROUGH_DIRECT;
    

        typedef struct _SCSI_INQUIRY_STD_DATA{
          UCHAR preipheral_device_type : 5;
          UCHAR peripheral_qualifier: 3;
          UCHAR rsvrd : 7;
          UCHAR rmb: 1;
          UCHAR version;
          UCHAR RESPONSE_DATA_FORMAT;                // 7 = AERC, 6 = Obsolete, 5 = NormACA, 4 = HiSup 3-0 = Response data format.
          // If ANSI Version = 0, this is ATAPI and bits 7-4 = ATAPI version.
          UCHAR        ADDITIONAL_LENGTH;                    // Number of additional bytes available in inquiry data
          UCHAR        SCCSReserved;                        // SCC-2 device flag and reserved fields
          UCHAR        flags1;                                // First byte of support flags
          UCHAR        flags2;                                // Second byte of support flags (Byte 7)
          char        vendor_id[8];
          char        product_id[16];
          char        product_revision_level[4];
        } SCSI_INQUIRY_STD_DATA;
                    

        /*Uses Inquire commnand defined in SCSI MMC doc*/
     void enquireDriveInfo(HANDLE device)
    {
        inquiryCDB driveInquiry  = {0};   //Creates CDB structure
        SCSI_INQUIRY_STD_DATA recvInquiry  = {0};  //receive data
        DWORD returnedBuf;           //Bytes received through DeviceIoControl
        
        
        unsigned char cmdLen[sizeof(SCSI_PASS_THROUGH_DIRECT) + 96]  = {0}; 
        //Creates structure - SCSI pass through direct
        SCSI_PASS_THROUGH_DIRECT * driveInquirySCSIptd = (SCSI_PASS_THROUGH_DIRECT *) cmdLen;  
        

        //UCHAR scsiInq = SCSIOP_INQUIRY;
        //CHECK HERE- allocation Length etc
        //Sets variables in driveInquiary CDB
        driveInquiry.OperationCode6 = "SCSIOP_INQUIRY";   /*ERROR OCCURS HERE*/
        //strcpy(driveInquiry.OperationCode6, SCSIOP_INQUIRY);
        //driveInquiry.OperationCode6 = SCSIOP_INQUIRY;
        //driveInquiry.Reserved1= 5;
        //driveInquiry.LogicalUnitNumber= 3;
        //driveInquiry.PageCode= "0";
        //driveInquiry.IReserved= "0";
        driveInquiry.AllocationLength= sizeof(recvInquiry);  
        //driveInquiry.Control= "0";
        
        
        
        
        // -> = pointer to structure (instead of .)        & = refernece (copies but doesnt destroy source)
        memcpy(driveInquirySCSIptd->Cdb, &driveInquiry, sizeof(driveInquiry));
        
        //Sets SCSI PASS THROUGH DIRECT (CDB already in place) - next step DeviceIoControl
        void * buffer;
        DWORD bufferLength;
        UCHAR dataIn;
        strcpy(&dataIn, "SCSI_IOCTL_DATA_IN");   /*THIS ISNT CORRECT EITHER*/
        UCHAR inquirycdbLength;
        driveInquirySCSIptd->DataBuffer             = buffer;
        driveInquirySCSIptd->DataTransferLength = bufferLength;
        driveInquirySCSIptd->DataIn                  = dataIn;
        driveInquirySCSIptd->CdbLength             = inquirycdbLength;
        driveInquirySCSIptd->Length                  = sizeof(SCSI_PASS_THROUGH_DIRECT);
        driveInquirySCSIptd->SenseInfoLength     = sizeof(cmdLen) - sizeof(SCSI_PASS_THROUGH_DIRECT);
        driveInquirySCSIptd->SenseInfoOffset      = sizeof(SCSI_PASS_THROUGH_DIRECT);
        driveInquirySCSIptd->TimeOutValue         = 6000; 
        
        //Send SCSI PASS THROUGH DIRECT
    
        
        DeviceIoControl(
          device,
          (DWORD)"IOCTL_SCSI_PASS_THROUGH_DIRECT",
          (LPVOID)&cmdLen,
          sizeof(cmdLen), 
          (LPVOID)&cmdLen,
          sizeof(cmdLen), 
                  &returnedBuf,
          NULL);   //take out...  (LPOVERLAPPED)
          
          DWORD error = GetLastError();
          if (error == 0)
          {
            printf("carry_cdb(): last error = %08X\n", error);
          }
          
          
        char inquiryExtract[100];
        int i = 0;
        /*Prints info from drive*/
          strncpy(inquiryExtract, recvInquiry.vendor_id, i = sizeof(recvInquiry.vendor_id));
          inquiryExtract[i] = 0;
          printf("vendor id: %s\n", inquiryExtract);
          
          strncpy(inquiryExtract, recvInquiry.product_id, i = sizeof(recvInquiry.product_id));
          inquiryExtract[i] = 0;
          printf("product id: %s\n", inquiryExtract);
          
          strncpy(inquiryExtract, recvInquiry.product_revision_level, i = sizeof(recvInquiry.product_revision_level));
          inquiryExtract[i] = 0;
          printf("product_revision_level: %s\n", inquiryExtract);
                  
          
        
        
    }
    
    
    int main()
    {   
       //reference region code
        HANDLE device;
        char deviceName[20];

        
        

        strcpy(deviceName, "\\\\.\\e:");
                
        device = CreateFile(deviceName, 
                                   GENERIC_READ | GENERIC_WRITE, 
                                  FILE_SHARE_READ | FILE_SHARE_WRITE, 
                                  NULL, OPEN_EXISTING, 
                                  FILE_ATTRIBUTE_NORMAL, NULL);
        
        if(device == INVALID_HANDLE_VALUE) //Error opening drive
        {
           printf("Error accessing rom drive - creating handle (%d)\n", GetLastError());
        }
        
        printf("%s", deviceName);

        printf("debug1");
        
         enquireDriveInfo(device);
     

    }
```


----------



## IMM (Feb 1, 2002)

driveInquiry.OperationCode6 is a char
SCSIOP_INQUIRY should be a char (UCHAR) which is defined in some header (take the quotes off of it)
I don't know offhand where the declaration of it should reside -- on the net there are examples of includes which do define it
eg. http://read.pudn.com/downloads110/sourcecode/others/454447/scsi_struct.h__.htm
You will need a header file which is appropriate for this -- what are you using as a model?

The same issue exists with the other "quoted value"

You seem to know what the value should be -- perhaps you could always just use it as
driveInquiry.OperationCode6 = 0x12;
or define SCSIOP_INQUIRY in a header as:
#define SCSIOP_INQUIRY 0x12


----------



## IMM (Feb 1, 2002)

I didn't clean it up much to make good code -- but if you create the header file "scsi_struct.h" (linked above) using notepad or similar in the same folder as your cpp source file -- then the following should work.
You need to edit it to remove the #include line in it, which doesn't have anything following it and the stuff at the top (or comment it out)

```
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <windows.h>
#include <winioctl.h>
#include "scsi_struct.h"

int enquireDriveInfo(HANDLE hdev)
{
  CDB_INQUIRY6 driveInquiry = {0};           //Creates CDB structure
  SCSI_INQUIRY_STD_DATA recvInquiry  = {0};  //receive data
  DWORD returnedBuf_size;                    //Bytes received through DeviceIoControl
  
  unsigned char cmdLen[sizeof(SCSI_PASS_THROUGH_DIRECT) + 96]  = {0};
  SCSI_PASS_THROUGH_DIRECT *driveInquirySCSIptd = (SCSI_PASS_THROUGH_DIRECT *) cmdLen;

  driveInquiry.OperationCode6 = SCSIOP_INQUIRY;
  driveInquiry.AllocationLength = sizeof(recvInquiry);
  // Copy the CDB to the SCSI_PASS_THROUGH structure 
  memcpy(driveInquirySCSIptd->Cdb, &driveInquiry, sizeof(driveInquiry));
  
  driveInquirySCSIptd->DataBuffer         = &recvInquiry;
  driveInquirySCSIptd->DataTransferLength = sizeof(recvInquiry);
  driveInquirySCSIptd->DataIn             = SCSI_IOCTL_DATA_IN;
  driveInquirySCSIptd->CdbLength          = sizeof(driveInquiry);
  driveInquirySCSIptd->Length             = sizeof(SCSI_PASS_THROUGH_DIRECT);
  driveInquirySCSIptd->SenseInfoLength    = sizeof(cmdLen) - sizeof(SCSI_PASS_THROUGH_DIRECT);
  driveInquirySCSIptd->SenseInfoOffset    = sizeof(SCSI_PASS_THROUGH_DIRECT);
  driveInquirySCSIptd->TimeOutValue       = 6000;
  
  BOOL bRet = DeviceIoControl(hdev, IOCTL_SCSI_PASS_THROUGH_DIRECT, (LPVOID)&cmdLen,
                              sizeof(cmdLen),(LPVOID)&cmdLen,sizeof(cmdLen),
                              &returnedBuf_size,NULL);
  
  DWORD error = GetLastError();
  if (error != ERROR_SUCCESS) {
    printf("carry_cdb(): last error = %08X\n", error);
    return 1;
  }
  
  
  if (bRet) {
    char inquiryExtract[100];
    int i = 0;
    /*Prints info from drive*/
    strncpy(inquiryExtract, recvInquiry.vendor_id, i = sizeof(recvInquiry.vendor_id));
    inquiryExtract[i] = 0;
    printf("vendor id: %s\n", inquiryExtract);
    
    strncpy(inquiryExtract, recvInquiry.product_id, i = sizeof(recvInquiry.product_id));
    inquiryExtract[i] = 0;
    printf("product id: %s\n", inquiryExtract);
    
    strncpy(inquiryExtract, recvInquiry.product_revision_level, i = sizeof(recvInquiry.product_revision_level));
    inquiryExtract[i] = 0;
    printf("product_revision_level: %s\n", inquiryExtract);
  }
  return 0;
}


int main()
{
  HANDLE hdevice;
  char deviceName[20];
  strcpy(deviceName, "\\\\.\\e:");
  hdevice = CreateFile(deviceName,GENERIC_READ |  GENERIC_WRITE,
                       FILE_SHARE_READ | FILE_SHARE_WRITE,
                       NULL, OPEN_EXISTING, 0, 0);
  if(hdevice == INVALID_HANDLE_VALUE) {        //Error opening drive
    printf("Error accessing rom drive - creating handle (%d)\n", GetLastError());
    return 1;
  }
  printf("%s", deviceName);
  printf("debug1\n");
  enquireDriveInfo(hdevice);
  CloseHandle(hdevice);
  return 0;
}
```


----------



## Dr.Zoidberg (Nov 21, 2008)

Sorry for the late reply. Many thanks though! 

I looked into using defined and ifndef but wasnt sure how to use them. At least I can keep my hair now...


----------



## IMM (Feb 1, 2002)

Dr.Zoidberg said:


> At least I can keep my hair now...


A lobster with hair?


----------

