Added SSC report to DiscImageChef.Device.Report.

This commit is contained in:
2017-12-18 07:56:03 +00:00
parent 935d4b9e96
commit bb895360e6
6 changed files with 454 additions and 2 deletions

View File

@@ -7,5 +7,5 @@ find_package(LibXml2)
include_directories(${LIBXML2_INCLUDE_DIR})
add_executable(DiscImageChef_Device_Report main.c scsi.c scsi.h main.h ata.h ata.c atapi.c atapi.h atapi_report.c atapi_report.h identify_decode.c identify_decode.h scsi_report.c scsi_report.h inquiry_decode.c inquiry_decode.h scsi_mode.h scsi_mode.c mmc_report.c mmc_report.h cdrom_mode.h)
add_executable(DiscImageChef_Device_Report main.c scsi.c scsi.h main.h ata.h ata.c atapi.c atapi.h atapi_report.c atapi_report.h identify_decode.c identify_decode.h scsi_report.c scsi_report.h inquiry_decode.c inquiry_decode.h scsi_mode.h scsi_mode.c mmc_report.c mmc_report.h cdrom_mode.h ssc_report.c ssc_report.h)
target_link_libraries(DiscImageChef_Device_Report ${LIBXML2_LIBRARIES})

View File

@@ -847,3 +847,83 @@ int HlDtStReadRawDvd(int fd, unsigned char **buffer, unsigned char **senseBuffer
return error;
}
int ReadBlockLimits(int fd, unsigned char **buffer, unsigned char **senseBuffer)
{
unsigned char cmd_len = 6;
unsigned int buffer_len = 6;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
unsigned char cdb[] = {SCSI_READ_BLOCK_LIMITS, 0, 0, 0, 0, 0};
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int ReportDensitySupport(int fd, unsigned char **buffer, unsigned char **senseBuffer, int mediumType, int currentMedia)
{
unsigned char cmd_len = 10;
unsigned int buffer_len = 256;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
unsigned char cdb[] = {SCSI_REPORT_DENSITY_SUPPORT, 0, 0, 0, 0, 0, 0, 0, 0, 0};
if(currentMedia)
cdb[1] |= 0x01;
if(mediumType)
cdb[1] |= 0x02;
cdb[7] = (uint8_t)((buffer_len & 0xFF00) >> 8);
cdb[8] = (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) << 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;
}
int ReadMediaSerialNumber(int fd, unsigned char **buffer, unsigned char **senseBuffer)
{
unsigned char cmd_len = 12;
unsigned int buffer_len = 256;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
unsigned char cdb[] = {SCSI_READ_MEDIA_SERIAL, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
cdb[6] = (uint8_t)((buffer_len & 0xFF000000) >> 24);
cdb[7] = (uint8_t)((buffer_len & 0xFF0000) >> 16);
cdb[8] = (uint8_t)((buffer_len & 0xFF00) >> 8);
cdb[9] = (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) << 24) + (*(*buffer + 1) << 16)) + (*(*buffer + 2) << 8) + *(*buffer + 3) + 4;
free(*buffer);
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
cdb[6] = (uint8_t)((buffer_len & 0xFF000000) >> 24);
cdb[7] = (uint8_t)((buffer_len & 0xFF0000) >> 16);
cdb[8] = (uint8_t)((buffer_len & 0xFF00) >> 8);
cdb[9] = (uint8_t)(buffer_len & 0xFF);
error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}

View File

@@ -47,10 +47,14 @@ int PioneerReadCdDa(int fd, unsigned char **buffer, unsigned char **senseBuffer,
int PioneerReadCdDaMsf(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t startMsf, uint32_t endMsf, uint32_t blockSize, uint8_t subchannel);
int NecReadCdDa(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t transferLength);
int HlDtStReadRawDvd(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t transferLength);
int ReadBlockLimits(int fd, unsigned char **buffer, unsigned char **senseBuffer);
int ReportDensitySupport(int fd, unsigned char **buffer, unsigned char **senseBuffer, int mediumType, int currentMedia);
int ReadMediaSerialNumber(int fd, unsigned char **buffer, unsigned char **senseBuffer);
typedef enum
{
SCSI_TEST_UNIT_READY = 0x00,
SCSI_READ_BLOCK_LIMITS = 0x05,
SCSI_READ = 0x08,
SCSI_SEEK = 0x0B,
SCSI_INQUIRY = 0x12,
@@ -64,12 +68,14 @@ typedef enum
SCSI_SEEK_10 = 0x2B,
SCSI_READ_BUFFER = 0x3C,
MMC_READ_TOC_PMA_ATIP = 0x43,
SCSI_REPORT_DENSITY_SUPPORT = 0x44,
MMC_GET_CONFIGURATION = 0x46,
SCSI_MODE_SENSE_10 = 0x5A,
SCSI_ATA_PASSTHROUGH_16 = 0x85,
SCSI_READ_16 = 0x88,
SCSI_SERVICE_ACTION_IN = 0x9E,
SCSI_READ_12 = 0xA8,
SCSI_READ_MEDIA_SERIAL = 0xAB,
MMC_READ_DISC_STRUCTURE = 0xAD,
MMC_READ_CD_MSF = 0xB9,
MMC_READ_CD = 0xBE,

View File

@@ -10,6 +10,7 @@
#include "inquiry_decode.h"
#include "scsi_mode.h"
#include "mmc_report.h"
#include "ssc_report.h"
void ScsiReport(int fd, xmlTextWriterPtr xmlWriter)
{
@@ -251,7 +252,7 @@ void ScsiReport(int fd, xmlTextWriterPtr xmlWriter)
}
else if(inquiry->PeripheralDeviceType == 0x01) // SequentialAccess
{
// TODO: Report SSC
SscReport(fd, xmlWriter);
}
else
{

View File

@@ -0,0 +1,307 @@
//
// Created by claunia on 18/12/17.
//
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <libxml/xmlwriter.h>
#include "ssc_report.h"
#include "scsi.h"
#include "scsi_mode.h"
DensitySupport *DecodeDensity(unsigned char *response);
MediaTypeSupport *DecodeMediumTypes(unsigned char *response);
void SscReport(int fd, xmlTextWriterPtr xmlWriter)
{
unsigned char *sense = NULL;
unsigned char *buffer = NULL;
int i, error, len;
char user_response = ' ';
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SequentialDevice"); // <SequentialDevice>
printf("Querying SCSI READ BLOCK LIMITS...\n");
error = ReadBlockLimits(fd, &buffer, &sense);
if(!error)
{
uint8_t granularity = (uint8_t)(buffer[0] & 0x1F);
uint32_t maxBlockLen = (uint32_t)((buffer[1] << 16) + (buffer[2] << 8) + buffer[3]);
uint16_t minBlockLen = (uint16_t)((buffer[4] << 8) + buffer[5]);
if(granularity > 0)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BlockSizeGranularity", "%d", granularity);
if(maxBlockLen > 0)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MaxBlockLength", "%d", maxBlockLen);
if(minBlockLen > 0)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinBlockLength", "%d", minBlockLen);
}
printf("Querying SCSI REPORT DENSITY SUPPORT...\n");
error = ReportDensitySupport(fd, &buffer, &sense, FALSE, FALSE);
if(!error)
{
DensitySupport *dsh = DecodeDensity(buffer);
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedDensities"); // <SupportedDensities>
for(i = 0; i < dsh->count; i++)
{
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedDensity"); // <SupportedDensity>
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BitsPerMm", "%d", (dsh->descriptors[i]->bitsPerMm[0] << 16) + (dsh->descriptors[i]->bitsPerMm[1] << 8) + dsh->descriptors[i]->bitsPerMm[2]);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Capacity", "%d", be32toh(dsh->descriptors[i]->capacity));
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "DefaultDensity", "%s", dsh->descriptors[i]->deflt ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Description", "%20s", dsh->descriptors[i]->description);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Duplicate", "%s", dsh->descriptors[i]->dup ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Name", "%8s", dsh->descriptors[i]->densityName);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Organization", "%8s", dsh->descriptors[i]->organization);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PrimaryCode", "%d", dsh->descriptors[i]->primaryCode);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SecondaryCode", "%d", dsh->descriptors[i]->secondaryCode);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Tracks", "%d", be16toh(dsh->descriptors[i]->tracks));
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Width", "%d", be16toh(dsh->descriptors[i]->mediaWidth));
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Writable", "%s", dsh->descriptors[i]->wrtok ? "true" : "false");
xmlTextWriterEndElement(xmlWriter); // </SupportedDensity>
}
xmlTextWriterEndElement(xmlWriter); // </SupportedDensities>
}
printf("Querying SCSI REPORT DENSITY SUPPORT for medium types...\n");
error = ReportDensitySupport(fd, &buffer, &sense, TRUE, FALSE);
if(!error)
{
MediaTypeSupport *mtsh = DecodeMediumTypes(buffer);
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedMediaTypes"); // <SupportedMediaTypes>
for(i = 0; i < mtsh->count; i++)
{
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedMedia"); // <SupportedMedia>
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Description", "%20s", mtsh->descriptors[i]->description);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Length", "%d", be16toh(mtsh->descriptors[i]->length));
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediumType", "%d", mtsh->descriptors[i]->mediumType);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Name", "%8s", mtsh->descriptors[i]->densityName);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Organization", "%8s", mtsh->descriptors[i]->organization);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Width", "%d", be16toh(mtsh->descriptors[i]->mediaWidth));
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedDensity"); // <SupportedDensity>
// TODO: Density codes
xmlTextWriterEndElement(xmlWriter); // </SupportedMedia>
}
xmlTextWriterEndElement(xmlWriter); // </SupportedMediaTypes>
}
user_response = ' ';
int anyMedia = FALSE;
DecodedMode *decMode;
while(user_response != 'N' && user_response != 'n')
{
do
{
printf("Do you have media that you can insert in the drive? (Y/N): ");
scanf("%c", &user_response);
printf("\n");
} while(user_response != 'Y' && user_response != 'y' && user_response != 'N' && user_response != 'n');
if(user_response == 'Y' || user_response == 'y')
{
printf("Please insert it in the drive and press any key when it is ready.\n");
scanf("%c");
char mediaManufacturer[256], mediaName[256], mediaModel[256];
printf("Please write a description of the media type and press enter: ");
gets(mediaName);
printf("Please write the media manufacturer and press enter: ");
gets(mediaManufacturer);
printf("Please write the media model and press enter: ");
gets(mediaModel);
error = TestUnitReady(fd, &sense);
int mediaRecognized = TRUE;
int leftRetries = 20;
if(error)
{
if((sense[0] == 0x70 || sense[0] == 0x71) && (sense[2] & 0x0F) != 0x00)
{
if(sense[12] == 0x3A || (sense[12] == 0x04 && sense[13] == 0x01))
{
while(leftRetries > 0)
{
printf("\rWating for drive to become ready");
sleep(2);
error = TestUnitReady(fd, &sense);
if(!error)
break;
leftRetries--;
}
printf("\n");
mediaRecognized = !error;
}
else
mediaRecognized = FALSE;
}
else
mediaRecognized = FALSE;
}
if(!anyMedia)
xmlTextWriterStartElement(xmlWriter, BAD_CAST "TestedMedia"); // <TestedMedia>
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SequentialMedia"); // <SequentialMedia>
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediaIsRecognized", "%s", mediaRecognized ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Manufacturer", "%s", mediaManufacturer);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediumTypeName", "%s",mediaName);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Model", "%s", mediaModel);
if(mediaRecognized)
{
printf("Querying SCSI MODE SENSE (10)...\n");
error = ModeSense10(fd, &buffer, &sense, FALSE, TRUE, MODE_PAGE_DEFAULT, 0x3F, 0x00);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsModeSense10", "%s", !error ? "true" : "false");
if(!error)
{
xmlTextWriterStartElement(xmlWriter, BAD_CAST "ModeSense10Data");
xmlTextWriterWriteBase64(xmlWriter, buffer, 0, (*(buffer + 0) << 8) + *(buffer + 1) + 2);
xmlTextWriterEndElement(xmlWriter);
decMode = DecodeMode10(buffer, 0x01);
}
printf("Querying SCSI MODE SENSE (6)...\n");
error = ModeSense6(fd, &buffer, &sense, FALSE, MODE_PAGE_DEFAULT, 0x00, 0x00);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsModeSense6", "%s", !error ? "true" : "false");
if(!error)
{
xmlTextWriterStartElement(xmlWriter, BAD_CAST "ModeSense6Data");
xmlTextWriterWriteBase64(xmlWriter, buffer, 0, *(buffer + 0) + 1);
xmlTextWriterEndElement(xmlWriter);
if(!decMode->decoded)
decMode = DecodeMode6(buffer, 0x01);
}
if(decMode->decoded)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediumType", "%d", decMode->Header.MediumType);
if(decMode->Header.descriptorsLength > 0)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Density", "%d", decMode->Header.BlockDescriptors[0].Density);
}
printf("Querying SCSI REPORT DENSITY SUPPORT for current media...\n");
error = ReportDensitySupport(fd, &buffer, &sense, FALSE, TRUE);
if(!error)
{
DensitySupport *dsh = DecodeDensity(buffer);
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedDensities"); // <SupportedDensities>
for(i = 0; i < dsh->count; i++)
{
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedDensity"); // <SupportedDensity>
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BitsPerMm", "%d", (dsh->descriptors[i]->bitsPerMm[0] << 16) + (dsh->descriptors[i]->bitsPerMm[1] << 8) + dsh->descriptors[i]->bitsPerMm[2]);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Capacity", "%d", be32toh(dsh->descriptors[i]->capacity));
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "DefaultDensity", "%s", dsh->descriptors[i]->deflt ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Description", "%20s", dsh->descriptors[i]->description);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Duplicate", "%s", dsh->descriptors[i]->dup ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Name", "%8s", dsh->descriptors[i]->densityName);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Organization", "%8s", dsh->descriptors[i]->organization);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PrimaryCode", "%d", dsh->descriptors[i]->primaryCode);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SecondaryCode", "%d", dsh->descriptors[i]->secondaryCode);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Tracks", "%d", be16toh(dsh->descriptors[i]->tracks));
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Width", "%d", be16toh(dsh->descriptors[i]->mediaWidth));
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Writable", "%s", dsh->descriptors[i]->wrtok ? "true" : "false");
xmlTextWriterEndElement(xmlWriter); // </SupportedDensity>
}
xmlTextWriterEndElement(xmlWriter); // </SupportedDensities>
}
printf("Querying SCSI REPORT DENSITY SUPPORT for medium types for current media...\n");
error = ReportDensitySupport(fd, &buffer, &sense, TRUE, TRUE);
if(!error)
{
MediaTypeSupport *mtsh = DecodeMediumTypes(buffer);
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedMediaTypes"); // <SupportedMediaTypes>
for(i = 0; i < mtsh->count; i++)
{
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedMedia"); // <SupportedMedia>
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Description", "%20s", mtsh->descriptors[i]->description);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Length", "%d", be16toh(mtsh->descriptors[i]->length));
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediumType", "%d", mtsh->descriptors[i]->mediumType);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Name", "%8s", mtsh->descriptors[i]->densityName);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Organization", "%8s", mtsh->descriptors[i]->organization);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Width", "%d", be16toh(mtsh->descriptors[i]->mediaWidth));
xmlTextWriterStartElement(xmlWriter, BAD_CAST "SupportedDensity"); // <SupportedDensity>
// TODO: Density codes
xmlTextWriterEndElement(xmlWriter); // </SupportedMedia>
}
xmlTextWriterEndElement(xmlWriter); // </SupportedMediaTypes>
}
printf("Trying SCSI READ MEDIA SERIAL NUMBER...\n");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead", "%s", !ReadMediaSerialNumber(fd, &buffer, &sense) ? "true" : "false");
}
xmlTextWriterEndElement(xmlWriter); // </SequentialMedia>
if(!anyMedia)
{
xmlTextWriterEndElement(xmlWriter); // </TestedMedia>
anyMedia = TRUE;
}
}
}
xmlTextWriterEndElement(xmlWriter); // </SequentialDevice>
}
DensitySupport *DecodeDensity(unsigned char *response)
{
DensitySupport *decoded = malloc(sizeof(DensitySupport));
memset(decoded, 0, sizeof(DensitySupport));
uint16_t responseLen = (uint16_t)((response[0] << 8) + response[1] + 2);
int offset = 4;
while(offset + 3 < responseLen)
{
int lenValid = response[offset + 2] & 0x20;
uint16_t descLen = (uint16_t)((response[offset + 3] << 8) + response[offset + 4] + 5);
decoded->descriptors[decoded->count] = malloc(sizeof(DensityDescriptor));
memset(decoded->descriptors[decoded->count], 0, sizeof(DensityDescriptor));
memcpy(decoded->descriptors[decoded->count], response + offset, sizeof(DensityDescriptor));
if(lenValid)
offset += descLen;
else
offset += 52;
decoded->count++;
}
}
MediaTypeSupport *DecodeMediumTypes(unsigned char *response)
{
MediaTypeSupport *decoded = malloc(sizeof(MediaTypeSupport));
memset(decoded, 0, sizeof(MediaTypeSupport));
uint16_t responseLen = (uint16_t)((response[0] << 8) + response[1] + 2);
int offset = 4;
while(offset + 3 < responseLen)
{
decoded->descriptors[decoded->count] = malloc(sizeof(MediumDescriptor));
memset(decoded->descriptors[decoded->count], 0, sizeof(MediumDescriptor));
memcpy(decoded->descriptors[decoded->count], response + offset, sizeof(MediumDescriptor));
offset += 56;
decoded->count++;
}
}

View File

@@ -0,0 +1,58 @@
//
// Created by claunia on 18/12/17.
//
#ifndef DISCIMAGECHEF_DEVICE_REPORT_SSC_REPORT_H
#define DISCIMAGECHEF_DEVICE_REPORT_SSC_REPORT_H
void SscReport(int fd, xmlTextWriterPtr xmlWriter);
#pragma pack(push, 1)
typedef struct
{
uint8_t primaryCode;
uint8_t secondaryCode;
uint8_t dlv : 1;
uint8_t reserved : 4;
uint8_t deflt : 1;
uint8_t dup : 1;
uint8_t wrtok : 1;
uint16_t length;
uint8_t bitsPerMm[3];
uint16_t mediaWidth;
uint16_t tracks;
uint32_t capacity;
unsigned char organization[8];
unsigned char densityName[8];
unsigned char description[20];
} DensityDescriptor;
#pragma pack(pop)
#pragma pack(push, 1)
typedef struct
{
uint8_t mediumType;
uint8_t reserved;
uint16_t length;
uint8_t codes_len;
uint8_t codes[9];
uint16_t mediaWidth;
uint16_t mediumLength;
uint16_t reserved2;
unsigned char organization[8];
unsigned char densityName[8];
unsigned char description[20];
} MediumDescriptor;
#pragma pack(pop)
typedef struct
{
uint16_t count;
DensityDescriptor *descriptors[1260];
} DensitySupport;
typedef struct
{
uint16_t count;
MediumDescriptor *descriptors[1170];
} MediaTypeSupport;
#endif //DISCIMAGECHEF_DEVICE_REPORT_SSC_REPORT_H