diff --git a/DiscImageChef.Device.Report/CMakeLists.txt b/DiscImageChef.Device.Report/CMakeLists.txt index 12c3de57..9794ec71 100644 --- a/DiscImageChef.Device.Report/CMakeLists.txt +++ b/DiscImageChef.Device.Report/CMakeLists.txt @@ -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}) \ No newline at end of file diff --git a/DiscImageChef.Device.Report/scsi.c b/DiscImageChef.Device.Report/scsi.c index f7e6097a..e8bf6a6f 100644 --- a/DiscImageChef.Device.Report/scsi.c +++ b/DiscImageChef.Device.Report/scsi.c @@ -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; +} diff --git a/DiscImageChef.Device.Report/scsi.h b/DiscImageChef.Device.Report/scsi.h index 584cbb8d..344dc829 100644 --- a/DiscImageChef.Device.Report/scsi.h +++ b/DiscImageChef.Device.Report/scsi.h @@ -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, diff --git a/DiscImageChef.Device.Report/scsi_report.c b/DiscImageChef.Device.Report/scsi_report.c index 55bac98a..d8eeaa48 100644 --- a/DiscImageChef.Device.Report/scsi_report.c +++ b/DiscImageChef.Device.Report/scsi_report.c @@ -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 { diff --git a/DiscImageChef.Device.Report/ssc_report.c b/DiscImageChef.Device.Report/ssc_report.c new file mode 100644 index 00000000..d79735b4 --- /dev/null +++ b/DiscImageChef.Device.Report/ssc_report.c @@ -0,0 +1,307 @@ +// +// Created by claunia on 18/12/17. +// + +#include +#include +#include +#include +#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"); // + + 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"); // + + for(i = 0; i < dsh->count; i++) + { + xmlTextWriterStartElement(xmlWriter, BAD_CAST "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); // + } + + xmlTextWriterEndElement(xmlWriter); // + } + + 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"); // + + for(i = 0; i < mtsh->count; i++) + { + xmlTextWriterStartElement(xmlWriter, BAD_CAST "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"); // + // TODO: Density codes + xmlTextWriterEndElement(xmlWriter); // + } + + xmlTextWriterEndElement(xmlWriter); // + } + + 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"); // + + xmlTextWriterStartElement(xmlWriter, BAD_CAST "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"); // + + for(i = 0; i < dsh->count; i++) + { + xmlTextWriterStartElement(xmlWriter, BAD_CAST "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); // + } + + xmlTextWriterEndElement(xmlWriter); // + } + + + 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"); // + + for(i = 0; i < mtsh->count; i++) + { + xmlTextWriterStartElement(xmlWriter, BAD_CAST "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"); // + // TODO: Density codes + xmlTextWriterEndElement(xmlWriter); // + } + + xmlTextWriterEndElement(xmlWriter); // + } + + printf("Trying SCSI READ MEDIA SERIAL NUMBER...\n"); + xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead", "%s", !ReadMediaSerialNumber(fd, &buffer, &sense) ? "true" : "false"); + } + + xmlTextWriterEndElement(xmlWriter); // + + if(!anyMedia) + { + xmlTextWriterEndElement(xmlWriter); // + anyMedia = TRUE; + } + } + } + + xmlTextWriterEndElement(xmlWriter); // +} + +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++; + } +} \ No newline at end of file diff --git a/DiscImageChef.Device.Report/ssc_report.h b/DiscImageChef.Device.Report/ssc_report.h new file mode 100644 index 00000000..46dff102 --- /dev/null +++ b/DiscImageChef.Device.Report/ssc_report.h @@ -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