mirror of
https://github.com/aaru-dps/Aaru.Server.git
synced 2025-12-16 19:24:27 +00:00
Added SSC report to DiscImageChef.Device.Report.
This commit is contained in:
307
DiscImageChef.Device.Report/ssc_report.c
Normal file
307
DiscImageChef.Device.Report/ssc_report.c
Normal 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++;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user