Added SCSI MODE SENSE report to DiscImageChef.Device.Report.

This commit is contained in:
2017-12-16 20:02:16 +00:00
parent 8930336221
commit 1b75ca78f8
5 changed files with 657 additions and 6 deletions

View File

@@ -8,8 +8,12 @@
#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
#include "scsi.h"
#define FALSE 0
#define TRUE 1
int SendScsiCommand(int fd, void *cdb, unsigned char cdb_len, unsigned char *buffer, unsigned int buffer_len, unsigned char **senseBuffer, int direction)
{
if(buffer == NULL || cdb == NULL)
@@ -62,5 +66,200 @@ int Inquiry(int fd, unsigned char **buffer, unsigned char **senseBuffer)
cdb[4] = pagesLength;
error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, pagesLength, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int PreventMediumRemoval(int fd, unsigned char **senseBuffer)
{
return PreventAllowMediumRemoval(fd, senseBuffer, FALSE, TRUE);
}
int AllowMediumRemoval(int fd, unsigned char **senseBuffer)
{
return PreventAllowMediumRemoval(fd, senseBuffer, FALSE, FALSE);
}
int PreventAllowMediumRemoval(int fd, unsigned char **senseBuffer, int persistent, int prevent)
{
unsigned char cmd_len = 6;
char cdb[] = {SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL, 0, 0, 0, 0, 0};
unsigned char *buffer = malloc(0);
if(prevent)
cdb[4] += 0x01;
if(persistent)
cdb[4] += 0x02;
int error = SendScsiCommand(fd, &cdb, cmd_len, buffer, 0, senseBuffer, SG_DXFER_NONE);
return error;
}
int LoadTray(int fd, unsigned char **senseBuffer)
{
return StartStopUnit(fd, senseBuffer, FALSE, 0, 0, FALSE, TRUE, TRUE);
}
int EjectTray(int fd, unsigned char **senseBuffer)
{
return StartStopUnit(fd, senseBuffer, FALSE, 0, 0, FALSE, TRUE, FALSE);
}
int StartUnit(int fd, unsigned char **senseBuffer)
{
return StartStopUnit(fd, senseBuffer, FALSE, 0, 0, FALSE, FALSE, TRUE);
}
int StopUnit(int fd, unsigned char **senseBuffer)
{
return StartStopUnit(fd, senseBuffer, FALSE, 0, 0, FALSE, FALSE, FALSE);
}
int StartStopUnit(int fd, unsigned char **senseBuffer, int immediate, uint8_t formatLayer, uint8_t powerConditions, int changeFormatLayer, int loadEject, int start)
{
unsigned char cmd_len = 6;
char cdb[] = {SCSI_START_STOP_UNIT, 0, 0, 0, 0, 0};
unsigned char *buffer = malloc(0);
if(immediate)
cdb[1] += 0x01;
if(changeFormatLayer)
{
cdb[3] = (formatLayer & 0x03);
cdb[4] += 0x04;
}
else
{
if(loadEject)
cdb[4] += 0x02;
if(start)
cdb[4] += 0x01;
}
cdb[4] += ((powerConditions & 0x0F) << 4);
int error = SendScsiCommand(fd, &cdb, cmd_len, buffer, 0, senseBuffer, SG_DXFER_NONE);
return error;
}
int SpcPreventMediumRemoval(int fd, unsigned char **senseBuffer)
{
return SpcPreventAllowMediumRemoval(fd, senseBuffer, 0x01);
}
int SpcAllowMediumRemoval(int fd, unsigned char **senseBuffer)
{
return SpcPreventAllowMediumRemoval(fd, senseBuffer, 0x00);
}
int SpcPreventAllowMediumRemoval(int fd, unsigned char **senseBuffer, uint8_t preventMode)
{
unsigned char cmd_len = 6;
char cdb[] = {SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL, 0, 0, 0, 0, 0};
unsigned char *buffer = malloc(0);
cdb[4] = (preventMode & 0x03);
int error = SendScsiCommand(fd, &cdb, cmd_len, buffer, 0, senseBuffer, SG_DXFER_NONE);
return error;
}
int Load(int fd, unsigned char **senseBuffer)
{
return LoadUnload(fd, senseBuffer, FALSE, TRUE, FALSE, FALSE, FALSE);
}
int Unload(int fd, unsigned char **senseBuffer)
{
return LoadUnload(fd, senseBuffer, FALSE, FALSE, FALSE, FALSE, FALSE);
}
int LoadUnload(int fd, unsigned char **senseBuffer, int immediate, int load, int retense, int endOfTape, int hold)
{
unsigned char cmd_len = 6;
char cdb[] = {SCSI_LOAD_UNLOAD, 0, 0, 0, 0, 0};
unsigned char *buffer = malloc(0);
if(immediate)
cdb[1] = 0x01;
if(load)
cdb[4] += 0x01;
if(retense)
cdb[4] += 0x02;
if(endOfTape)
cdb[4] += 0x04;
if(hold)
cdb[4] += 0x08;
int error = SendScsiCommand(fd, &cdb, cmd_len, buffer, 0, senseBuffer, SG_DXFER_NONE);
return error;
}
int ModeSense6(int fd, unsigned char **buffer, unsigned char **senseBuffer, int DBD, uint8_t pageControl, uint8_t pageCode, uint8_t subPageCode)
{
unsigned char cmd_len = 6;
unsigned int buffer_len = 255;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
unsigned char cdb[] = {SCSI_MODE_SENSE, 0, 0, 0, 0, 0};
if(DBD)
cdb[1] |= 0x08;
cdb[2] |= pageControl;
cdb[2] |= (pageCode & 0x3F);
cdb[3] = subPageCode;
cdb[4] = (uint8_t)(buffer_len & 0xFF);
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
if(error)
return error;
buffer_len = (unsigned int)*(*buffer + 0) + 1;
free(*buffer);
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
cdb[4] = (uint8_t)(buffer_len & 0xFF);
error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int ModeSense10(int fd, unsigned char **buffer, unsigned char **senseBuffer, int LLBAA, int DBD, uint8_t pageControl, uint8_t pageCode, uint8_t subPageCode)
{
unsigned char cmd_len = 10;
unsigned int buffer_len = 4096;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
unsigned char cdb[] = {SCSI_MODE_SENSE_10, 0, 0, 0, 0, 0, 0, 0, 0, 0};
if(LLBAA)
cdb[1] |= 0x10;
if(DBD)
cdb[1] |= 0x08;
cdb[2] |= pageControl;
cdb[2] |= (pageCode & 0x3F);
cdb[3] = subPageCode;
cdb[7] = (uint8_t)((buffer_len & 0xFF00) >> 8);
cdb[8] = (uint8_t)(buffer_len & 0xFF);
cdb[9] = 0;
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
if(error)
return error;
buffer_len = (unsigned int)(*(*buffer + 0) << 8) + *(*buffer + 1) + 2;
free(*buffer);
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
cdb[7] = (uint8_t)((buffer_len & 0xFF00) >> 8);
cdb[8] = (uint8_t)(buffer_len & 0xFF);
error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}