Move DiscImageChef.Device.Report to its own repository.

This commit is contained in:
2019-03-14 23:41:09 +00:00
parent c997ad3780
commit 6d629bacd0
33 changed files with 0 additions and 11034 deletions

View File

@@ -1 +0,0 @@
DiscImageChef_Device_Report

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />

View File

@@ -1,5 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

View File

@@ -1,8 +0,0 @@
<component name="ProjectDictionaryState">
<dictionary name="claunia">
<words>
<w>claunia</w>
<w>discimagechef</w>
</words>
</dictionary>
</component>

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/DiscImageChef.Device.Report.iml" filepath="$PROJECT_DIR$/.idea/DiscImageChef.Device.Report.iml" />
</modules>
</component>
</project>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

View File

@@ -1,11 +0,0 @@
cmake_minimum_required(VERSION 3.9)
project(DiscImageChef_Device_Report C)
set(CMAKE_C_STANDARD 90)
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 ssc_report.c ssc_report.h ata_report.c ata_report.h)
target_link_libraries(DiscImageChef_Device_Report ${LIBXML2_LIBRARIES})

View File

@@ -1,537 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : ata.c
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Contains ATA commands.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#include <scsi/sg.h>
#include <malloc.h>
#include <stdint.h>
#include <string.h>
#include "ata.h"
#include "scsi.h"
int AtaProtocolToScsiDirection(int protocol)
{
switch(protocol)
{
case ATA_PROTOCOL_DEVICE_DIAGNOSTICS:
case ATA_PROTOCOL_DEVICE_RESET:
case ATA_PROTOCOL_HARD_RESET:
case ATA_PROTOCOL_NO_DATA:
case ATA_PROTOCOL_SOFT_RESET:
case ATA_PROTOCOL_RETURN_RESPONSE:
return SG_DXFER_NONE;
case ATA_PROTOCOL_PIO_IN:
case ATA_PROTOCOL_UDMA_IN:
return SG_DXFER_FROM_DEV;
case ATA_PROTOCOL_PIO_OUT:
case ATA_PROTOCOL_UDMA_OUT:
return SG_DXFER_TO_DEV;
default:
return SG_DXFER_TO_FROM_DEV;
}
}
unsigned char *AtaToCString(unsigned char *string, int len)
{
unsigned char *buffer = malloc(len + 1);
unsigned char *ptr = buffer;
int i;
for(i = 0; i < len; i += 2)
{
*ptr++ = *(string + i + 1);
*ptr++ = *(string + i);
}
buffer[len] = 0x00;
*ptr = *(buffer + len);
for(i = len; i >= 0; i--, *ptr--)
{
if(*ptr == 0x20 || *ptr == 0x00)
*ptr = 0;
else
break;
}
return buffer;
}
int SendAtaCommandChs(int fd, AtaRegistersCHS registers, AtaErrorRegistersCHS **errorRegisters, int protocol,
int transferRegister, unsigned char *buffer, unsigned int buffer_len, int transferBlocks)
{
unsigned char cdb[16];
memset(&cdb, 0, 16);
cdb[0] = SCSI_ATA_PASSTHROUGH_16;
cdb[1] = (unsigned char)((protocol << 1) & 0x1E);
if(transferRegister != ATA_TRANSFER_NONE && protocol != ATA_PROTOCOL_NO_DATA)
{
switch(protocol)
{
case ATA_PROTOCOL_PIO_IN:
case ATA_PROTOCOL_UDMA_IN:
cdb[2] = 0x08;
break;
default:
cdb[2] = 0x00;
break;
}
if(transferBlocks)
cdb[2] |= 0x04;
cdb[2] |= (transferRegister & 0x03);
}
cdb[4] = registers.feature;
cdb[6] = registers.sectorCount;
cdb[8] = registers.sector;
cdb[10] = registers.cylinderLow;
cdb[12] = registers.cylinderHigh;
cdb[13] = registers.deviceHead;
cdb[14] = registers.command;
unsigned char *sense_buf;
int error = SendScsiCommand(fd, &cdb, 16, buffer, buffer_len, &sense_buf,
AtaProtocolToScsiDirection(protocol));
*errorRegisters = malloc(sizeof(AtaErrorRegistersCHS));
memset(*errorRegisters, 0, sizeof(AtaErrorRegistersCHS));
(*errorRegisters)->error = sense_buf[11];
(*errorRegisters)->sectorCount = sense_buf[13];
(*errorRegisters)->sector = sense_buf[15];
(*errorRegisters)->cylinderLow = sense_buf[17];
(*errorRegisters)->cylinderHigh = sense_buf[19];
(*errorRegisters)->deviceHead = sense_buf[20];
(*errorRegisters)->status = sense_buf[21];
if(error != 0)
return error;
return (*errorRegisters)->error;
}
int SendAtaCommandLba28(int fd, AtaRegistersLBA28 registers, AtaErrorRegistersLBA28 **errorRegisters, int protocol,
int transferRegister, unsigned char *buffer, unsigned int buffer_len, int transferBlocks)
{
unsigned char cdb[16];
memset(&cdb, 0, 16);
cdb[0] = SCSI_ATA_PASSTHROUGH_16;
cdb[1] = (unsigned char)((protocol << 1) & 0x1E);
if(transferRegister != ATA_TRANSFER_NONE && protocol != ATA_PROTOCOL_NO_DATA)
{
switch(protocol)
{
case ATA_PROTOCOL_PIO_IN:
case ATA_PROTOCOL_UDMA_IN:
cdb[2] = 0x08;
break;
default:
cdb[2] = 0x00;
break;
}
if(transferBlocks)
cdb[2] |= 0x04;
cdb[2] |= (transferRegister & 0x03);
}
cdb[2] |= 0x20;
cdb[4] = registers.feature;
cdb[6] = registers.sectorCount;
cdb[8] = registers.lbaLow;
cdb[10] = registers.lbaMid;
cdb[12] = registers.lbaHigh;
cdb[13] = registers.deviceHead;
cdb[14] = registers.command;
unsigned char *sense_buf;
int error = SendScsiCommand(fd, &cdb, 16, buffer, buffer_len, &sense_buf,
AtaProtocolToScsiDirection(protocol));
*errorRegisters = malloc(sizeof(AtaErrorRegistersLBA28));
memset(*errorRegisters, 0, sizeof(AtaErrorRegistersLBA28));
(*errorRegisters)->error = sense_buf[11];
(*errorRegisters)->sectorCount = sense_buf[13];
(*errorRegisters)->lbaLow = sense_buf[15];
(*errorRegisters)->lbaMid = sense_buf[17];
(*errorRegisters)->lbaHigh = sense_buf[19];
(*errorRegisters)->deviceHead = sense_buf[20];
(*errorRegisters)->status = sense_buf[21];
if(error != 0)
return error;
return (*errorRegisters)->error;
}
int SendAtaCommandLba48(int fd, AtaRegistersLBA48 registers, AtaErrorRegistersLBA48 **errorRegisters, int protocol,
int transferRegister, unsigned char *buffer, unsigned int buffer_len, int transferBlocks)
{
unsigned char cdb[16];
memset(&cdb, 0, 16);
cdb[0] = SCSI_ATA_PASSTHROUGH_16;
cdb[1] = (unsigned char)((protocol << 1) & 0x1E);
cdb[1] |= 0x01;
if(transferRegister != ATA_TRANSFER_NONE && protocol != ATA_PROTOCOL_NO_DATA)
{
switch(protocol)
{
case ATA_PROTOCOL_PIO_IN:
case ATA_PROTOCOL_UDMA_IN:
cdb[2] = 0x08;
break;
default:
cdb[2] = 0x00;
break;
}
if(transferBlocks)
cdb[2] |= 0x04;
cdb[2] |= (transferRegister & 0x03);
}
cdb[2] |= 0x20;
cdb[3] = (uint8_t)((registers.feature & 0xFF00) >> 8);
cdb[4] = (uint8_t)(registers.feature & 0xFF);
cdb[5] = (uint8_t)((registers.sectorCount & 0xFF00) >> 8);
cdb[6] = (uint8_t)(registers.sectorCount & 0xFF);
cdb[7] = (uint8_t)((registers.lbaLow & 0xFF00) >> 8);
cdb[8] = (uint8_t)(registers.lbaLow & 0xFF);
cdb[9] = (uint8_t)((registers.lbaMid & 0xFF00) >> 8);
cdb[10] = (uint8_t)(registers.lbaMid & 0xFF);
cdb[11] = (uint8_t)((registers.lbaHigh & 0xFF00) >> 8);
cdb[12] = (uint8_t)(registers.lbaHigh & 0xFF);
cdb[13] = registers.deviceHead;
cdb[14] = registers.command;
unsigned char *sense_buf;
int error = SendScsiCommand(fd, &cdb, 16, buffer, buffer_len, &sense_buf,
AtaProtocolToScsiDirection(protocol));
*errorRegisters = malloc(sizeof(AtaErrorRegistersLBA48));
memset(*errorRegisters, 0, sizeof(AtaErrorRegistersLBA48));
(*errorRegisters)->error = sense_buf[11];
(*errorRegisters)->sectorCount = (uint16_t)((sense_buf[12] << 8) + sense_buf[13]);
(*errorRegisters)->lbaLow = (uint16_t)((sense_buf[14] << 8) + sense_buf[15]);
(*errorRegisters)->lbaMid = (uint16_t)((sense_buf[16] << 8) + sense_buf[17]);
(*errorRegisters)->lbaHigh = (uint16_t)((sense_buf[18] << 8) + sense_buf[19]);
(*errorRegisters)->deviceHead = sense_buf[20];
(*errorRegisters)->status = sense_buf[21];
if(error != 0)
return error;
return (*errorRegisters)->error;
}
int Identify(int fd, unsigned char **buffer, AtaErrorRegistersCHS **errorRegisters)
{
*buffer = malloc(512);
memset(*buffer, 0, 512);
AtaRegistersCHS registers;
memset(&registers, 0, sizeof(AtaRegistersCHS));
registers.command = ATA_IDENTIFY_DEVICE;
int error = SendAtaCommandChs(fd, registers, errorRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_NONE, *buffer, 512,
0);
return error;
}
int
Read(int fd, unsigned char **buffer, AtaErrorRegistersCHS **statusRegisters, int retry, uint16_t cylinder, uint8_t head,
uint8_t sector, uint8_t count)
{
int buffer_len;
if(count == 0)
buffer_len = 512 * 256;
else
buffer_len = 512 * count;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
AtaRegistersCHS registers;
memset(&registers, 0, sizeof(AtaRegistersCHS));
if(retry)
registers.command = ATA_READ_RETRY;
else
registers.command = ATA_READ_SECTORS;
registers.sectorCount = count;
registers.cylinderHigh = (uint8_t)((cylinder & 0xFF00) / 0x100);
registers.cylinderLow = (uint8_t)((cylinder & 0xFF) / 0x1);
registers.deviceHead = (uint8_t)(head & 0x0F);
registers.sector = sector;
int error = SendAtaCommandChs(fd, registers, statusRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_SECTORCOUNT,
*buffer, buffer_len, 1);
return error;
}
int ReadLong(int fd, unsigned char **buffer, AtaErrorRegistersCHS **statusRegisters, int retry, uint16_t cylinder,
uint8_t head, uint8_t sector, uint32_t blockSize)
{
*buffer = malloc(blockSize);
memset(*buffer, 0, blockSize);
AtaRegistersCHS registers;
memset(&registers, 0, sizeof(AtaRegistersCHS));
if(retry)
registers.command = ATA_READ_LONG_RETRY;
else
registers.command = ATA_READ_LONG;
registers.sectorCount = 1;
registers.cylinderHigh = (uint8_t)((cylinder & 0xFF00) / 0x100);
registers.cylinderLow = (uint8_t)((cylinder & 0xFF) / 0x1);
registers.deviceHead = (uint8_t)(head & 0x0F);
registers.sector = sector;
int error = SendAtaCommandChs(fd, registers, statusRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_SECTORCOUNT,
*buffer, blockSize, 1);
return error;
}
int Seek(int fd, AtaErrorRegistersCHS **statusRegisters, uint16_t cylinder, uint8_t head, uint8_t sector)
{
unsigned char *buffer = malloc(0);
memset(*buffer, 0, 0);
AtaRegistersCHS registers;
memset(&registers, 0, sizeof(AtaRegistersCHS));
registers.command = ATA_SEEK;
registers.cylinderHigh = (uint8_t)((cylinder & 0xFF00) / 0x100);
registers.cylinderLow = (uint8_t)((cylinder & 0xFF) / 0x1);
registers.deviceHead = (uint8_t)(head & 0x0F);
registers.sector = sector;
int error = SendAtaCommandChs(fd, registers, statusRegisters, ATA_PROTOCOL_NO_DATA, ATA_TRANSFER_NONE, *buffer, 0,
0);
return error;
}
int ReadDma(int fd, unsigned char **buffer, AtaErrorRegistersCHS **statusRegisters, int retry, uint16_t cylinder,
uint8_t head, uint8_t sector, uint8_t count)
{
int buffer_len;
if(count == 0)
buffer_len = 512 * 256;
else
buffer_len = 512 * count;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
AtaRegistersCHS registers;
memset(&registers, 0, sizeof(AtaRegistersCHS));
if(retry)
registers.command = ATA_READ_DMA_RETRY;
else
registers.command = ATA_READ_DMA;
registers.sectorCount = count;
registers.cylinderHigh = (uint8_t)((cylinder & 0xFF00) / 0x100);
registers.cylinderLow = (uint8_t)((cylinder & 0xFF) / 0x1);
registers.deviceHead = (uint8_t)(head & 0x0F);
registers.sector = sector;
int error = SendAtaCommandChs(fd, registers, statusRegisters, ATA_PROTOCOL_DMA, ATA_TRANSFER_SECTORCOUNT, *buffer,
buffer_len, 1);
return error;
}
int ReadDmaLba(int fd, unsigned char **buffer, AtaErrorRegistersLBA28 **statusRegisters, int retry, uint32_t lba,
uint8_t count)
{
int buffer_len;
if(count == 0)
buffer_len = 512 * 256;
else
buffer_len = 512 * count;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
AtaRegistersLBA28 registers;
memset(&registers, 0, sizeof(AtaRegistersLBA28));
if(retry)
registers.command = ATA_READ_DMA_RETRY;
else
registers.command = ATA_READ_DMA;
registers.sectorCount = count;
registers.deviceHead = (uint8_t)((lba & 0xF000000) / 0x1000000);
registers.lbaHigh = (uint8_t)((lba & 0xFF0000) / 0x10000);
registers.lbaMid = (uint8_t)((lba & 0xFF00) / 0x100);
registers.lbaLow = (uint8_t)((lba & 0xFF) / 0x1);
registers.deviceHead += 0x40;
int error = SendAtaCommandLba28(fd, registers, statusRegisters, ATA_PROTOCOL_DMA, ATA_TRANSFER_SECTORCOUNT, *buffer,
buffer_len, 1);
return error;
}
int ReadLba(int fd, unsigned char **buffer, AtaErrorRegistersLBA28 **statusRegisters, int retry, uint32_t lba,
uint8_t count)
{
int buffer_len;
if(count == 0)
buffer_len = 512 * 256;
else
buffer_len = 512 * count;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
AtaRegistersLBA28 registers;
memset(&registers, 0, sizeof(AtaRegistersLBA28));
if(retry)
registers.command = ATA_READ_RETRY;
else
registers.command = ATA_READ_SECTORS;
registers.sectorCount = count;
registers.deviceHead = (uint8_t)((lba & 0xF000000) / 0x1000000);
registers.lbaHigh = (uint8_t)((lba & 0xFF0000) / 0x10000);
registers.lbaMid = (uint8_t)((lba & 0xFF00) / 0x100);
registers.lbaLow = (uint8_t)((lba & 0xFF) / 0x1);
registers.deviceHead += 0x40;
int error = SendAtaCommandLba28(fd, registers, statusRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_SECTORCOUNT,
*buffer, buffer_len, 1);
return error;
}
int ReadLongLba(int fd, unsigned char **buffer, AtaErrorRegistersLBA28 **statusRegisters, int retry, uint32_t lba,
uint32_t blockSize)
{
*buffer = malloc(blockSize);
memset(*buffer, 0, blockSize);
AtaRegistersLBA28 registers;
memset(&registers, 0, sizeof(AtaRegistersLBA28));
if(retry)
registers.command = ATA_READ_LONG_RETRY;
else
registers.command = ATA_READ_LONG;
registers.sectorCount = 1;
registers.sectorCount = 1;
registers.deviceHead = (uint8_t)((lba & 0xF000000) / 0x1000000);
registers.lbaHigh = (uint8_t)((lba & 0xFF0000) / 0x10000);
registers.lbaMid = (uint8_t)((lba & 0xFF00) / 0x100);
registers.lbaLow = (uint8_t)((lba & 0xFF) / 0x1);
registers.deviceHead += 0x40;
int error = SendAtaCommandLba28(fd, registers, statusRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_SECTORCOUNT,
*buffer, blockSize, 1);
return error;
}
int SeekLba(int fd, AtaErrorRegistersLBA28 **statusRegisters, uint32_t lba)
{
unsigned char *buffer = malloc(0);
memset(*buffer, 0, 0);
AtaRegistersLBA28 registers;
memset(&registers, 0, sizeof(AtaRegistersLBA28));
registers.command = ATA_SEEK;
registers.deviceHead = (uint8_t)((lba & 0xF000000) / 0x1000000);
registers.lbaHigh = (uint8_t)((lba & 0xFF0000) / 0x10000);
registers.lbaMid = (uint8_t)((lba & 0xFF00) / 0x100);
registers.lbaLow = (uint8_t)((lba & 0xFF) / 0x1);
registers.deviceHead += 0x40;
int error = SendAtaCommandLba28(fd, registers, statusRegisters, ATA_PROTOCOL_NO_DATA, ATA_TRANSFER_NONE, *buffer, 0,
0);
return error;
}
int ReadDmaLba48(int fd, unsigned char **buffer, AtaErrorRegistersLBA48 **statusRegisters, uint64_t lba, uint16_t count)
{
int buffer_len;
if(count == 0)
buffer_len = 512 * 65536;
else
buffer_len = 512 * count;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
AtaRegistersLBA48 registers;
memset(&registers, 0, sizeof(AtaRegistersLBA48));
registers.command = ATA_READ_DMA_EXT;
registers.sectorCount = count;
registers.lbaHigh = (uint16_t)((lba & 0xFFFF00000000) / 0x100000000);
registers.lbaMid = (uint16_t)((lba & 0xFFFF0000) / 0x10000);
registers.lbaLow = (uint16_t)((lba & 0xFFFF) / 0x1);
registers.deviceHead += 0x40;
int error = SendAtaCommandLba48(fd, registers, statusRegisters, ATA_PROTOCOL_DMA, ATA_TRANSFER_SECTORCOUNT, *buffer,
buffer_len, 1);
return error;
}
int ReadLba48(int fd, unsigned char **buffer, AtaErrorRegistersLBA48 **statusRegisters, uint64_t lba, uint16_t count)
{
int buffer_len;
if(count == 0)
buffer_len = 512 * 65536;
else
buffer_len = 512 * count;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
AtaRegistersLBA48 registers;
memset(&registers, 0, sizeof(AtaRegistersLBA48));
registers.command = ATA_READ_EXT;
registers.sectorCount = count;
registers.lbaHigh = (uint16_t)((lba & 0xFFFF00000000) / 0x100000000);
registers.lbaMid = (uint16_t)((lba & 0xFFFF0000) / 0x10000);
registers.lbaLow = (uint16_t)((lba & 0xFFFF) / 0x1);
registers.deviceHead += 0x40;
int error = SendAtaCommandLba48(fd, registers, statusRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_SECTORCOUNT,
*buffer, buffer_len, 1);
return error;
}

View File

@@ -1,919 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : ata.h
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Contains ATA definitions.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#ifndef DISCIMAGECHEF_DEVICE_REPORT_ATA_H
#define DISCIMAGECHEF_DEVICE_REPORT_ATA_H
#pragma pack(1)
typedef struct
{
uint8_t feature;
uint8_t sectorCount;
uint8_t sector;
uint8_t cylinderLow;
uint8_t cylinderHigh;
uint8_t deviceHead;
uint8_t command;
} AtaRegistersCHS;
typedef struct
{
uint8_t feature;
uint8_t sectorCount;
uint8_t lbaLow;
uint8_t lbaMid;
uint8_t lbaHigh;
uint8_t deviceHead;
uint8_t command;
} AtaRegistersLBA28;
typedef struct
{
uint16_t feature;
uint16_t sectorCount;
uint16_t lbaLow;
uint16_t lbaMid;
uint16_t lbaHigh;
uint8_t deviceHead;
uint8_t command;
} AtaRegistersLBA48;
typedef struct
{
uint8_t status;
uint8_t error;
uint8_t sectorCount;
uint8_t sector;
uint8_t cylinderLow;
uint8_t cylinderHigh;
uint8_t deviceHead;
uint8_t command;
} AtaErrorRegistersCHS;
typedef struct
{
uint8_t status;
uint8_t error;
uint8_t sectorCount;
uint8_t lbaLow;
uint8_t lbaMid;
uint8_t lbaHigh;
uint8_t deviceHead;
uint8_t command;
} AtaErrorRegistersLBA28;
typedef struct
{
uint8_t status;
uint8_t error;
uint16_t sectorCount;
uint16_t lbaLow;
uint16_t lbaMid;
uint16_t lbaHigh;
uint8_t deviceHead;
uint8_t command;
} AtaErrorRegistersLBA48;
typedef enum
{
ATA_TRANSFER_NONE = 0, ATA_TRANSFER_FEATURE, ATA_TRANSFER_SECTORCOUNT, ATA_TRANSFTER_SPTSIU
} AtaTransferRegister;
typedef enum
{
ATA_PROTOCOL_HARD_RESET = 0,
ATA_PROTOCOL_SOFT_RESET = 1,
ATA_PROTOCOL_NO_DATA = 3,
ATA_PROTOCOL_PIO_IN = 4,
ATA_PROTOCOL_PIO_OUT = 5,
ATA_PROTOCOL_DMA = 6,
ATA_PROTOCOL_DMA_QUEUED = 7,
ATA_PROTOCOL_DEVICE_DIAGNOSTICS = 8,
ATA_PROTOCOL_DEVICE_RESET = 9,
ATA_PROTOCOL_UDMA_IN = 10,
ATA_PROTOCOL_UDMA_OUT = 11,
ATA_PROTOCOL_FPDMA = 12,
ATA_PROTOCOL_RETURN_RESPONSE = 15
} AtaProtocol;
typedef enum
{
ATA_READ_RETRY = 0x20,
ATA_READ_SECTORS = 0x21,
ATA_READ_LONG_RETRY = 0x22,
ATA_READ_LONG = 0x23,
ATA_READ_EXT = 0x24,
ATA_READ_DMA_EXT = 0x25,
ATA_SEEK = 0x70,
ATA_READ_DMA_RETRY = 0xC8,
ATA_READ_DMA = 0xC9,
ATA_IDENTIFY_PACKET_DEVICE = 0xA1,
ATA_IDENTIFY_DEVICE = 0xEC
} AtaCommands;
typedef struct
{
/*
Word 0
General device configuration
On ATAPI devices:
Bits 12 to 8 indicate device type as SCSI defined
Bits 6 to 5:
0 = Device shall set DRQ within 3 ms of receiving PACKET
1 = Device shall assert INTRQ when DRQ is set to one
2 = Device shall set DRQ within 50 µs of receiving PACKET
Bits 1 to 0:
0 = 12 byte command packet
1 = 16 byte command packet
CompactFlash is 0x848A (non magnetic, removable, not MFM, hardsector, and UltraFAST)
*/
uint16_t GeneralConfiguration;
/*
Word 1
Cylinders in default translation mode
Obsoleted in ATA/ATAPI-6
*/
uint16_t Cylinders;
/*
Word 2
Specific configuration
*/
uint16_t SpecificConfiguration;
/*
Word 3
Heads in default translation mode
Obsoleted in ATA/ATAPI-6
*/
uint16_t Heads;
/*
Word 4
Unformatted bytes per track in default translation mode
Obsoleted in ATA-2
*/
uint16_t UnformattedBPT;
/*
Word 5
Unformatted bytes per sector in default translation mode
Obsoleted in ATA-2
*/
uint16_t UnformattedBPS;
/*
Word 6
Sectors per track in default translation mode
Obsoleted in ATA/ATAPI-6
*/
uint16_t SectorsPerTrack;
/*
Words 7 to 8
CFA: Number of sectors per card
*/
uint32_t SectorsPerCard;
/*
Word 9
Vendor unique
Obsoleted in ATA/ATAPI-4
*/
uint16_t VendorWord9;
/*
Words 10 to 19
Device serial number, right justified, padded with spaces
*/
uint8_t SerialNumber[20];
/*
Word 20
Manufacturer defined
Obsoleted in ATA-2
0x0001 = single ported single sector buffer
0x0002 = dual ported multi sector buffer
0x0003 = dual ported multi sector buffer with reading
*/
uint16_t BufferType;
/*
Word 21
Size of buffer in 512 byte increments
Obsoleted in ATA-2
*/
uint16_t BufferSize;
/*
Word 22
Bytes of ECC available in READ/WRITE LONG commands
Obsoleted in ATA/ATAPI-4
*/
uint16_t EccBytes;
/*
Words 23 to 26
Firmware revision, left justified, padded with spaces
*/
uint8_t FirmwareRevision[8];
/*
Words 27 to 46
Model number, left justified, padded with spaces
*/
uint8_t Model[40];
/*
Word 47 bits 7 to 0
Maximum number of sectors that can be transferred per
interrupt on read and write multiple commands
*/
uint8_t MultipleMaxSectors;
/*
Word 47 bits 15 to 8
Vendor unique
ATA/ATAPI-4 says it must be 0x80
*/
uint8_t VendorWord47;
/*
Word 48
ATA-1: Set to 1 if it can perform doubleword I/O
ATA-2 to ATA/ATAPI-7: Reserved
ATA8-ACS: Trusted Computing feature set
*/
uint16_t TrustedComputing;
/*
Word 49
Capabilities
*/
uint16_t Capabilities;
/*
Word 50
Capabilities
*/
uint16_t Capabilities2;
/*
Word 51 bits 7 to 0
Vendor unique
Obsoleted in ATA/ATAPI-4
*/
uint8_t VendorWord51;
/*
Word 51 bits 15 to 8
Transfer timing mode in PIO
Obsoleted in ATA/ATAPI-4
*/
uint8_t PIOTransferTimingMode;
/*
Word 52 bits 7 to 0
Vendor unique
Obsoleted in ATA/ATAPI-4
*/
uint8_t VendorWord52;
/*
Word 52 bits 15 to 8
Transfer timing mode in DMA
Obsoleted in ATA/ATAPI-4
*/
uint8_t DMATransferTimingMode;
/*
Word 53 bits 7 to 0
Reports if words 54 to 58 are valid
*/
uint8_t ExtendedIdentify;
/*
Word 53 bits 15 to 8
Free-fall Control Sensitivity
*/
uint8_t FreeFallSensitivity;
/*
Word 54
Cylinders in current translation mode
Obsoleted in ATA/ATAPI-6
*/
uint16_t CurrentCylinders;
/*
Word 55
Heads in current translation mode
Obsoleted in ATA/ATAPI-6
*/
uint16_t CurrentHeads;
/*
Word 56
Sectors per track in current translation mode
Obsoleted in ATA/ATAPI-6
*/
uint16_t CurrentSectorsPerTrack;
/*
Words 57 to 58
Total sectors currently user-addressable
Obsoleted in ATA/ATAPI-6
*/
uint32_t CurrentSectors;
/*
Word 59 bits 7 to 0
Number of sectors currently set to transfer on a READ/WRITE MULTIPLE command
*/
uint8_t MultipleSectorNumber;
/*
Word 59 bits 15 to 8
Indicates if <see cref="MultipleSectorNumber"/> is valid
*/
uint8_t Capabilities3;
/*
Words 60 to 61
If drive supports LBA, how many sectors are addressable using LBA
*/
uint32_t LBASectors;
/*
Word 62 bits 7 to 0
Single word DMA modes available
Obsoleted in ATA/ATAPI-4
In ATAPI it's not obsolete, indicates UDMA mode (UDMA7 is instead MDMA0)
*/
uint8_t DMASupported;
/*
Word 62 bits 15 to 8
Single word DMA mode currently active
Obsoleted in ATA/ATAPI-4
In ATAPI it's not obsolete, bits 0 and 1 indicate MDMA mode+1,
bit 10 indicates DMA is supported and bit 15 indicates DMADIR bit
in PACKET is required for DMA transfers
*/
uint8_t DMAActive;
/*
Word 63 bits 7 to 0
Multiword DMA modes available
*/
uint8_t MDMASupported;
/*
Word 63 bits 15 to 8
Multiword DMA mode currently active
*/
uint8_t MDMAActive;
/*
Word 64 bits 7 to 0
Supported Advanced PIO transfer modes
*/
uint8_t APIOSupported;
/*
Word 64 bits 15 to 8
Reserved
*/
uint8_t ReservedWord64;
/*
Word 65
Minimum MDMA transfer cycle time per word in nanoseconds
*/
uint16_t MinMDMACycleTime;
/*
Word 66
Recommended MDMA transfer cycle time per word in nanoseconds
*/
uint16_t RecMDMACycleTime;
/*
Word 67
Minimum PIO transfer cycle time without flow control in nanoseconds
*/
uint16_t MinPIOCycleTimeNoFlow;
/*
Word 68
Minimum PIO transfer cycle time with IORDY flow control in nanoseconds
*/
uint16_t MinPIOCycleTimeFlow;
/*
Word 69
Additional supported
*/
uint16_t CommandSet5;
/*
Word 70
Reserved
*/
uint16_t ReservedWord70;
/*
Word 71
ATAPI: Typical time in ns from receipt of PACKET to release bus
*/
uint16_t PacketBusRelease;
/*
Word 72
ATAPI: Typical time in ns from receipt of SERVICE to clear BSY
*/
uint16_t ServiceBusyClear;
/*
Word 73
Reserved
*/
uint16_t ReservedWord73;
/*
Word 74
Reserved
*/
uint16_t ReservedWord74;
/*
Word 75
Maximum Queue depth
*/
uint16_t MaxQueueDepth;
/*
Word 76
Serial ATA Capabilities
*/
uint16_t SATACapabilities;
/*
Word 77
Serial ATA Additional Capabilities
*/
uint16_t SATACapabilities2;
/*
Word 78
Supported Serial ATA features
*/
uint16_t SATAFeatures;
/*
Word 79
Enabled Serial ATA features
*/
uint16_t EnabledSATAFeatures;
/*
Word 80
Major version of ATA/ATAPI standard supported
*/
uint16_t MajorVersion;
/*
Word 81
Minimum version of ATA/ATAPI standard supported
*/
uint16_t MinorVersion;
/*
Word 82
Supported command/feature sets
*/
uint16_t CommandSet;
/*
Word 83
Supported command/feature sets
*/
uint16_t CommandSet2;
/*
Word 84
Supported command/feature sets
*/
uint16_t CommandSet3;
/*
Word 85
Enabled command/feature sets
*/
uint16_t EnabledCommandSet;
/*
Word 86
Enabled command/feature sets
*/
uint16_t EnabledCommandSet2;
/*
Word 87
Enabled command/feature sets
*/
uint16_t EnabledCommandSet3;
/*
Word 88 bits 7 to 0
Supported Ultra DMA transfer modes
*/
uint8_t UDMASupported;
/*
Word 88 bits 15 to 8
Selected Ultra DMA transfer modes
*/
uint8_t UDMAActive;
/*
Word 89
Time required for security erase completion
*/
uint16_t SecurityEraseTime;
/*
Word 90
Time required for enhanced security erase completion
*/
uint16_t EnhancedSecurityEraseTime;
/*
Word 91
Current advanced power management value
*/
uint16_t CurrentAPM;
/*
Word 92
Master password revision code
*/
uint16_t MasterPasswordRevisionCode;
/*
Word 93
Hardware reset result
*/
uint16_t HardwareResetResult;
/*
Word 94 bits 7 to 0
Current AAM value
*/
uint8_t CurrentAAM;
/*
Word 94 bits 15 to 8
Vendor's recommended AAM value
*/
uint8_t RecommendedAAM;
/*
Word 95
Stream minimum request size
*/
uint16_t StreamMinReqSize;
/*
Word 96
Streaming transfer time in DMA
*/
uint16_t StreamTransferTimeDMA;
/*
Word 97
Streaming access latency in DMA and PIO
*/
uint16_t StreamAccessLatency;
/*
Words 98 to 99
Streaming performance granularity
*/
uint32_t StreamPerformanceGranularity;
/*
Words 100 to 103
48-bit LBA addressable sectors
*/
uint64_t LBA48Sectors;
/*
Word 104
Streaming transfer time in PIO
*/
uint16_t StreamTransferTimePIO;
/*
Word 105
Maximum number of 512-byte block per DATA SET MANAGEMENT command
*/
uint16_t DataSetMgmtSize;
/*
Word 106
Bit 15 should be zero
Bit 14 should be one
Bit 13 set indicates device has multiple logical sectors per physical sector
Bit 12 set indicates logical sector has more than 256 words (512 bytes)
Bits 11 to 4 are reserved
Bits 3 to 0 indicate power of two of logical sectors per physical sector
*/
uint16_t PhysLogSectorSize;
/*
Word 107
Interseek delay for ISO-7779 acoustic testing, in microseconds
*/
uint16_t InterseekDelay;
/*
Words 108 to 111
World Wide Name
*/
uint64_t WWN;
/*
Words 112 to 115
Reserved for WWN extension to 128 bit
*/
uint64_t WWNExtension;
/*
Word 116
Reserved for technical report
*/
uint16_t ReservedWord116;
/*
Words 117 to 118
Words per logical sector
*/
uint32_t LogicalSectorWords;
/*
Word 119
Supported command/feature sets
*/
uint16_t CommandSet4;
/*
Word 120
Supported command/feature sets
*/
uint16_t EnabledCommandSet4;
/*
Words 121 to 125
Reserved
*/
uint16_t ReservedWords121[5];
/*
Word 126
ATAPI byte count limit
*/
uint16_t ATAPIByteCount;
/*
Word 127
Removable Media Status Notification feature set support
Bits 15 to 2 are reserved
Bits 1 to 0 must be 0 for not supported or 1 for supported. 2 and 3 are reserved.
Obsoleted in ATA8-ACS
*/
uint16_t RemovableStatusSet;
/*
Word 128
Security status
*/
uint16_t SecurityStatus;
/*
Words 129 to 159
*/
uint16_t ReservedWords129[31];
/*
Word 160
CFA power mode
Bit 15 must be set
Bit 13 indicates mode 1 is required for one or more commands
Bit 12 indicates mode 1 is disabled
Bits 11 to 0 indicates maximum current in mA
*/
uint16_t CFAPowerMode;
/*
Words 161 to 167
Reserved for CFA
*/
uint16_t ReservedCFA[7];
/*
Word 168
Bits 15 to 4, reserved
Bits 3 to 0, device nominal form factor
*/
uint16_t DeviceFormFactor;
/*
Word 169
DATA SET MANAGEMENT support
*/
uint16_t DataSetMgmt;
/*
Words 170 to 173
Additional product identifier
*/
uint8_t AdditionalPID[8];
/*
Word 174
Reserved
*/
uint16_t ReservedWord174;
/*
Word 175
Reserved
*/
uint16_t ReservedWord175;
/*
Words 176 to 195
Current media serial number
*/
uint8_t MediaSerial[40];
/*
Words 196 to 205
Current media manufacturer
*/
uint8_t MediaManufacturer[20];
/*
Word 206
SCT Command Transport features
*/
uint16_t SCTCommandTransport;
/*
Word 207
Reserved for CE-ATA
*/
uint16_t ReservedCEATAWord207;
/*
Word 208
Reserved for CE-ATA
*/
uint16_t ReservedCEATAWord208;
/*
Word 209
Alignment of logical block within a larger physical block
Bit 15 shall be cleared to zero
Bit 14 shall be set to one
Bits 13 to 0 indicate logical sector offset within the first physical sector
*/
uint16_t LogicalAlignment;
/*
Words 210 to 211
Write/Read/Verify sector count mode 3 only
*/
uint32_t WRVSectorCountMode3;
/*
Words 212 to 213
Write/Read/Verify sector count mode 2 only
*/
uint32_t WRVSectorCountMode2;
/*
Word 214
NV Cache capabilities
Bits 15 to 12 feature set version
Bits 11 to 18 power mode feature set version
Bits 7 to 5 reserved
Bit 4 feature set enabled
Bits 3 to 2 reserved
Bit 1 power mode feature set enabled
Bit 0 power mode feature set supported
*/
uint16_t NVCacheCaps;
/*
Words 215 to 216
NV Cache Size in Logical BLocks
*/
uint32_t NVCacheSize;
/*
Word 217
Nominal media rotation rate
In ACS-1 meant NV Cache read speed in MB/s
*/
uint16_t NominalRotationRate;
/*
Word 218
NV Cache write speed in MB/s
Reserved since ACS-2
*/
uint16_t NVCacheWriteSpeed;
/*
Word 219 bits 7 to 0
Estimated device spin up in seconds
*/
uint8_t NVEstimatedSpinUp;
/*
Word 219 bits 15 to 8
NV Cache reserved
*/
uint8_t NVReserved;
/*
Word 220 bits 7 to 0
Write/Read/Verify feature set current mode
*/
uint8_t WRVMode;
/*
Word 220 bits 15 to 8
Reserved
*/
uint8_t WRVReserved;
/*
Word 221
Reserved
*/
uint16_t ReservedWord221;
/*
Word 222
Transport major revision number
Bits 15 to 12 indicate transport type. 0 parallel, 1 serial, 0xE PCIe.
Bits 11 to 0 indicate revision
*/
uint16_t TransportMajorVersion;
/*
Word 223
Transport minor revision number
*/
uint16_t TransportMinorVersion;
/*
Words 224 to 229
Reserved for CE-ATA
*/
uint16_t ReservedCEATA224[6];
/*
Words 230 to 233
48-bit LBA if Word 69 bit 3 is set
*/
uint64_t ExtendedUserSectors;
/*
Word 234
Minimum number of 512 byte units per DOWNLOAD MICROCODE mode 3
*/
uint16_t MinDownloadMicroMode3;
/*
Word 235
Maximum number of 512 byte units per DOWNLOAD MICROCODE mode 3
*/
uint16_t MaxDownloadMicroMode3;
/*
Words 236 to 254
*/
uint16_t ReservedWords[19];
/*
Word 255 bits 7 to 0
Should be 0xA5
*/
uint8_t Signature;
/*
Word 255 bits 15 to 8
Checksum
*/
uint8_t Checksum;
} IdentifyDevice;
unsigned char *AtaToCString(unsigned char *string, int len);
int SendAtaCommandChs(int fd, AtaRegistersCHS registers, AtaErrorRegistersCHS **errorRegisters, int protocol,
int transferRegister, unsigned char *buffer, unsigned int buffer_len, int transferBlocks);
int SendAtaCommandLba28(int fd, AtaRegistersLBA28 registers, AtaErrorRegistersLBA28 **errorRegisters, int protocol,
int transferRegister, unsigned char *buffer, unsigned int buffer_len, int transferBlocks);
int SendAtaCommandLba48(int fd, AtaRegistersLBA48 registers, AtaErrorRegistersLBA48 **errorRegisters, int protocol,
int transferRegister, unsigned char *buffer, unsigned int buffer_len, int transferBlocks);
int Identify(int fd, unsigned char **buffer, AtaErrorRegistersCHS **errorRegisters);
int
Read(int fd, unsigned char **buffer, AtaErrorRegistersCHS **statusRegisters, int retry, uint16_t cylinder, uint8_t head,
uint8_t sector, uint8_t count);
int ReadLong(int fd, unsigned char **buffer, AtaErrorRegistersCHS **statusRegisters, int retry, uint16_t cylinder,
uint8_t head, uint8_t sector, uint32_t blockSize);
int Seek(int fd, AtaErrorRegistersCHS **statusRegisters, uint16_t cylinder, uint8_t head, uint8_t sector);
int ReadDma(int fd, unsigned char **buffer, AtaErrorRegistersCHS **statusRegisters, int retry, uint16_t cylinder,
uint8_t head, uint8_t sector, uint8_t count);
int ReadDmaLba(int fd, unsigned char **buffer, AtaErrorRegistersLBA28 **statusRegisters, int retry, uint32_t lba,
uint8_t count);
int ReadLba(int fd, unsigned char **buffer, AtaErrorRegistersLBA28 **statusRegisters, int retry, uint32_t lba,
uint8_t count);
int ReadLongLba(int fd, unsigned char **buffer, AtaErrorRegistersLBA28 **statusRegisters, int retry, uint32_t lba,
uint32_t blockSize);
int SeekLba(int fd, AtaErrorRegistersLBA28 **statusRegisters, uint32_t lba);
int
ReadDmaLba48(int fd, unsigned char **buffer, AtaErrorRegistersLBA48 **statusRegisters, uint64_t lba, uint16_t count);
int ReadLba48(int fd, unsigned char **buffer, AtaErrorRegistersLBA48 **statusRegisters, uint64_t lba, uint16_t count);
#endif //DISCIMAGECHEF_DEVICE_REPORT_ATA_H

View File

@@ -1,812 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : ata_report.c
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Creates report for ATA devices.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#include <string.h>
#include <libxml/xmlwriter.h>
#include "ata_report.h"
#include "ata.h"
#include "identify_decode.h"
void AtaReport(int fd, xmlTextWriterPtr xmlWriter)
{
unsigned char *ata_ident = NULL;
unsigned char *buffer = NULL;
AtaErrorRegistersCHS *ata_error_chs;
AtaErrorRegistersLBA28 *ata_error_lba;
AtaErrorRegistersLBA48 *ata_error_lba48;
int error;
int removable = FALSE;
char user_response = ' ';
printf("Querying ATA IDENTIFY...\n");
error = Identify(fd, &ata_ident, &ata_error_chs);
if(error)
{
fprintf(stderr, "Error {0} requesting IDENTIFY DEVICE", error);
return;
}
IdentifyDevice *identify = malloc(512);
memcpy(identify, ata_ident, 512);
xmlTextWriterStartElement(xmlWriter, BAD_CAST DIC_ATA_REPORT_ELEMENT);
if(le16toh(identify->GeneralConfiguration) == 0x848A)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CompactFlash", "%s", "TRUE");
removable = FALSE;
}
else if(identify->GeneralConfiguration & 0x0080)
{
do
{
printf("Is the media removable from the reading/writing elements (flash memories ARE NOT removable)? (Y/N): ");
scanf("%c", &user_response);
printf("\n");
}while(user_response != 'Y' && user_response != 'y' && user_response != 'N' && user_response != 'n');
removable = (user_response == 'Y' || user_response == 'y');
}
if(removable)
{
printf("Please remove any media from the device and press any key when it is out.\n");
scanf("%c");
printf("Querying ATA IDENTIFY...\n");
error = Identify(fd, &ata_ident, &ata_error_chs);
free(identify);
identify = malloc(512);
memcpy(identify, ata_ident, 512);
}
if((uint64_t)*identify->AdditionalPID != 0 && (uint64_t)*identify->AdditionalPID != 0x2020202020202020)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "AdditionalPid", AtaToCString(identify->AdditionalPID, 8));
if(identify->APIOSupported)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "APIOSupported",
DecodeTransferMode(le16toh(identify->APIOSupported)));
if(identify->BufferType)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BufferType", "%u", le16toh(identify->BufferType));
if(identify->BufferSize)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BufferSize", "%u", le16toh(identify->BufferSize));
if(identify->Capabilities)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Capabilities",
DecodeCapabilities(le16toh(identify->Capabilities)));
if(identify->Capabilities2)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Capabilities2",
DecodeCapabilities2(le16toh(identify->Capabilities2)));
if(identify->Capabilities3)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Capabilities3", DecodeCapabilities3(identify->Capabilities3));
if(identify->CFAPowerMode)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CFAPowerMode", "%u", le16toh(identify->CFAPowerMode));
if(identify->CommandSet)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet", DecodeCommandSet(le16toh(identify->CommandSet)));
if(identify->CommandSet2)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet2", DecodeCommandSet2(le16toh(identify->CommandSet2)));
if(identify->CommandSet3)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet3", DecodeCommandSet3(le16toh(identify->CommandSet3)));
if(identify->CommandSet4)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet4", DecodeCommandSet4(le16toh(identify->CommandSet4)));
if(identify->CommandSet5)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet5", DecodeCommandSet5(le16toh(identify->CommandSet5)));
if(identify->CurrentAAM)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CurrentAAM", "%u", identify->CurrentAAM);
if(identify->CurrentAPM)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CurrentAPM", "%u", le16toh(identify->CurrentAPM));
if(identify->DataSetMgmt)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DataSetMgmt", DecodeDataSetMgmt(le16toh(identify->DataSetMgmt)));
if(identify->DataSetMgmtSize)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "DataSetMgmtSize", "%u",
le16toh(identify->DataSetMgmtSize));
if(identify->DeviceFormFactor)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DeviceFormFactor",
DecodeDeviceFormFactor(le16toh(identify->DeviceFormFactor)));
if(identify->DMAActive)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DMAActive", DecodeTransferMode(le16toh(identify->DMAActive)));
if(identify->DMASupported)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DMASupported",
DecodeTransferMode(le16toh(identify->DMASupported)));
if(identify->DMATransferTimingMode)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "DMATransferTimingMode", "%u",
identify->DMATransferTimingMode);
if(identify->EnhancedSecurityEraseTime)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "EnhancedSecurityEraseTime", "%u",
le16toh(identify->EnhancedSecurityEraseTime));
if(identify->EnabledCommandSet)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet",
DecodeCommandSet(le16toh(identify->EnabledCommandSet)));
if(identify->EnabledCommandSet2)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet2",
DecodeCommandSet2(le16toh(identify->EnabledCommandSet2)));
if(identify->EnabledCommandSet3)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet3",
DecodeCommandSet3(le16toh(identify->EnabledCommandSet3)));
if(identify->EnabledCommandSet4)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet4",
DecodeCommandSet4(le16toh(identify->EnabledCommandSet4)));
if(identify->EnabledSATAFeatures)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledSATAFeatures",
DecodeSATAFeatures(le16toh(identify->EnabledSATAFeatures)));
if(identify->ExtendedUserSectors)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ExtendedUserSectors", "%llu",
le64toh(identify->ExtendedUserSectors));
if(identify->FreeFallSensitivity)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "FreeFallSensitivity", "%u", identify->FreeFallSensitivity);
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "FirmwareRevision", AtaToCString(identify->FirmwareRevision, 8));
if(identify->GeneralConfiguration)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "GeneralConfiguration",
DecodeGeneralConfiguration(le16toh(identify->GeneralConfiguration)));
if(identify->HardwareResetResult)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "HardwareResetResult", "%u",
le16toh(identify->HardwareResetResult));
if(identify->InterseekDelay)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "InterseekDelay", "%u", le16toh(identify->InterseekDelay));
if(identify->MajorVersion)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "MajorVersion",
DecodeMajorVersion(le16toh(identify->MajorVersion)));
if(identify->MasterPasswordRevisionCode)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MasterPasswordRevisionCode", "%u",
le16toh(identify->MasterPasswordRevisionCode));
if(identify->MaxDownloadMicroMode3)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MaxDownloadMicroMode3", "%u",
le16toh(identify->MaxDownloadMicroMode3));
if(identify->MaxQueueDepth)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MaxQueueDepth", "%u", le16toh(identify->MaxQueueDepth));
if(identify->MDMAActive)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "MDMAActive", DecodeTransferMode(le16toh(identify->MDMAActive)));
if(identify->MDMASupported)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "MDMASupported",
DecodeTransferMode(le16toh(identify->MDMASupported)));
if(identify->MinDownloadMicroMode3)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinDownloadMicroMode3", "%u",
le16toh(identify->MinDownloadMicroMode3));
if(identify->MinMDMACycleTime)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinMDMACycleTime", "%u",
le16toh(identify->MinMDMACycleTime));
if(identify->MinorVersion)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinorVersion", "%u", le16toh(identify->MinorVersion));
if(identify->MinPIOCycleTimeNoFlow)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinPIOCycleTimeNoFlow", "%u",
le16toh(identify->MinPIOCycleTimeNoFlow));
if(identify->MinPIOCycleTimeFlow)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinPIOCycleTimeFlow", "%u",
le16toh(identify->MinPIOCycleTimeFlow));
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Model", AtaToCString(identify->Model, 40));
if(identify->MultipleMaxSectors)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MultipleMaxSectors", "%u", identify->MultipleMaxSectors);
if(identify->MultipleSectorNumber)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MultipleSectorNumber", "%u",
identify->MultipleSectorNumber);
if(identify->NVCacheCaps)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVCacheCaps", "%u", le16toh(identify->NVCacheCaps));
if(identify->NVCacheSize)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVCacheSize", "%u", le32toh(identify->NVCacheSize));
if(identify->NVCacheWriteSpeed)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVCacheWriteSpeed", "%u",
le16toh(identify->NVCacheWriteSpeed));
if(identify->NVEstimatedSpinUp)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVEstimatedSpinUp", "%u", identify->NVEstimatedSpinUp);
if(identify->PacketBusRelease)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PacketBusRelease", "%u",
le16toh(identify->PacketBusRelease));
if(identify->PIOTransferTimingMode)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PIOTransferTimingMode", "%u",
identify->PIOTransferTimingMode);
if(identify->RecommendedAAM)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "RecommendedAAM", "%u", identify->RecommendedAAM);
if(identify->RecMDMACycleTime)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "RecMDMACycleTime", "%u",
le16toh(identify->RecMDMACycleTime));
if(identify->RemovableStatusSet)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "RemovableStatusSet", "%u",
le16toh(identify->RemovableStatusSet));
if(identify->SATACapabilities)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SATACapabilities",
DecodeSATACapabilities(le16toh(identify->SATACapabilities)));
if(identify->SATACapabilities2)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SATACapabilities2",
DecodeSATACapabilities2(le16toh(identify->SATACapabilities2)));
if(identify->SATAFeatures)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SATAFeatures",
DecodeSATAFeatures(le16toh(identify->SATAFeatures)));
if(identify->SCTCommandTransport)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SCTCommandTransport",
DecodeSCTCommandTransport(le16toh(identify->SCTCommandTransport)));
if(identify->SectorsPerCard)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SectorsPerCard", "%u", le32toh(identify->SectorsPerCard));
if(identify->SecurityEraseTime)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SecurityEraseTime", "%u",
le16toh(identify->SecurityEraseTime));
if(identify->SecurityStatus)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SecurityStatus",
DecodeSecurityStatus(le16toh(identify->SecurityStatus)));
if(identify->ServiceBusyClear)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ServiceBusyClear", "%u",
le16toh(identify->ServiceBusyClear));
if(identify->SpecificConfiguration)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SpecificConfiguration",
DecodeSpecificConfiguration(le16toh(identify->SpecificConfiguration)));
if(identify->StreamAccessLatency)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamAccessLatency", "%u",
le16toh(identify->StreamAccessLatency));
if(identify->StreamMinReqSize)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamMinReqSize", "%u",
le16toh(identify->StreamMinReqSize));
if(identify->StreamPerformanceGranularity)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamPerformanceGranularity", "%u",
le32toh(identify->StreamPerformanceGranularity));
if(identify->StreamTransferTimeDMA)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamTransferTimeDMA", "%u",
le16toh(identify->StreamTransferTimeDMA));
if(identify->StreamTransferTimePIO)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamTransferTimePIO", "%u",
le16toh(identify->StreamTransferTimePIO));
if(identify->TransportMajorVersion)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "TransportMajorVersion", "%u",
le16toh(identify->TransportMajorVersion));
if(identify->TransportMinorVersion)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "TransportMinorVersion", "%u",
le16toh(identify->TransportMinorVersion));
if(identify->TrustedComputing)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "TrustedComputing",
DecodeTrustedComputing(le16toh(identify->TrustedComputing)));
if(identify->UDMAActive)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "UDMAActive", DecodeTransferMode(le16toh(identify->UDMAActive)));
if(identify->UDMASupported)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "UDMASupported",
DecodeTransferMode(le16toh(identify->UDMASupported)));
if(identify->WRVMode)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WRVMode", "%u", identify->WRVMode);
if(identify->WRVSectorCountMode3)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WRVSectorCountMode3", "%u",
le32toh(identify->WRVSectorCountMode3));
if(identify->WRVSectorCountMode2)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WRVSectorCountMode2", "%u",
le32toh(identify->WRVSectorCountMode2));
xmlTextWriterStartElement(xmlWriter, BAD_CAST "Identify");
xmlTextWriterWriteBase64(xmlWriter, ata_ident, 0, 512);
xmlTextWriterEndElement(xmlWriter);
if(removable)
{
user_response = ' ';
int anyMedia = FALSE;
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 = Identify(fd, &ata_ident, &ata_error_chs);
if(!anyMedia)
xmlTextWriterStartElement(xmlWriter, BAD_CAST "RemovableMedias"); // <RemovableMedias>
xmlTextWriterStartElement(xmlWriter, BAD_CAST "testedMediaType"); // <testedMediaType>
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediaIsRecognized", "%s",
!error ? "TRUE" : "FALSE");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediumTypeName", "%s", mediaName);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Model", "%s", mediaModel);
if(error)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Manufacturer", "%s", mediaManufacturer);
xmlTextWriterEndElement(xmlWriter); // </testedMediaType>
anyMedia = TRUE;
continue;
}
free(identify);
identify = malloc(512);
memcpy(identify, ata_ident, 512);
if(identify->UnformattedBPT)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "UnformattedBPT", "%u",
le16toh(identify->UnformattedBPT));
if(identify->UnformattedBPS)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "UnformattedBPS", "%u",
le16toh(identify->UnformattedBPS));
uint64_t blocks = 0;
if(identify->Cylinders > 0 && identify->Heads > 0 && identify->SectorsPerTrack != 0)
{
xmlTextWriterStartElement(xmlWriter, BAD_CAST "CHS"); // <CHS>
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Cylinders", "%u",
le16toh(identify->Cylinders));
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Heads", "%u", le16toh(identify->Heads));
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Sectors", "%u",
le16toh(identify->SectorsPerTrack));
blocks = le16toh(identify->Cylinders) * le16toh(identify->Heads) *
le16toh(identify->SectorsPerTrack);
xmlTextWriterEndElement(xmlWriter); // </CHS>
}
if(identify->CurrentCylinders > 0 && identify->CurrentHeads > 0 &&
identify->CurrentSectorsPerTrack != 0)
{
xmlTextWriterStartElement(xmlWriter, BAD_CAST "CurrentCHS"); // <CurrentCHS>
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Cylinders", "%u",
le16toh(identify->CurrentCylinders));
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Heads", "%u", le16toh(identify->CurrentHeads));
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Sectors", "%u",
le16toh(identify->CurrentSectorsPerTrack));
if(blocks == 0)
blocks = le16toh(identify->CurrentCylinders) * le16toh(identify->CurrentHeads) *
le16toh(identify->CurrentSectorsPerTrack);
xmlTextWriterEndElement(xmlWriter); // </CurrentCHS>
}
if(le16toh(identify->Capabilities) & 0x0200)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LBASectors", "%u",
le32toh(identify->LBASectors));
blocks = le32toh(identify->LBASectors);
}
if(le16toh(identify->CommandSet2) & 0x0400)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LBA48Sectors", "%llu",
le64toh(identify->LBA48Sectors));
blocks = le64toh(identify->LBA48Sectors);
}
if(identify->NominalRotationRate != 0x0000 && identify->NominalRotationRate != 0xFFFF)
{
if(le16toh(identify->NominalRotationRate) == 0x0001)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SolidStateDevice", "%s", "TRUE");
else
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SolidStateDevice", "%s", "TRUE");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NominalRotationRate", "%u",
le16toh(identify->NominalRotationRate));
}
}
uint32_t logicalsectorsize = 0;
uint32_t physicalsectorsize = 0;
if((le16toh(identify->PhysLogSectorSize) & 0x8000) == 0x0000 &&
(le16toh(identify->PhysLogSectorSize) & 0x4000) == 0x4000)
{
if(le16toh(identify->PhysLogSectorSize) & 0x1000)
{
if(le16toh(identify->LogicalSectorWords) <= 255 || identify->LogicalAlignment == 0xFFFF)
logicalsectorsize = 512;
else
logicalsectorsize = le16toh(identify->LogicalSectorWords) * 2;
}
else
logicalsectorsize = 512;
if(le16toh(identify->PhysLogSectorSize) & 0x2000)
physicalsectorsize = logicalsectorsize * (1 << (le16toh(identify->PhysLogSectorSize) & 0xF));
else
physicalsectorsize = logicalsectorsize;
}
else
{
logicalsectorsize = 512;
physicalsectorsize = 512;
}
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BlockSize", "%u", logicalsectorsize);
if(physicalsectorsize != logicalsectorsize)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PhysicalBlockSize", "%u", physicalsectorsize);
if((le16toh(identify->LogicalAlignment) & 0x8000) == 0x0000 &&
(le16toh(identify->LogicalAlignment) & 0x4000) == 0x4000)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LogicalAlignment", "%u",
le16toh(identify->LogicalAlignment) & 0x3FFF);
}
uint16_t longblocksize = 0;
if(identify->EccBytes != 0x0000 && identify->EccBytes != 0xFFFF)
longblocksize = le16toh(identify->EccBytes);
if(le16toh(identify->UnformattedBPS) > logicalsectorsize &&
(longblocksize == 0 || longblocksize == 516))
longblocksize = le16toh(identify->UnformattedBPS);
if(longblocksize > 0)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LongBlockSize", "%u", longblocksize);
if((le16toh(identify->CommandSet3) & 0x8000) == 0x0000 &&
(le16toh(identify->CommandSet3) & 0x4000) == 0x4000 &&
(le16toh(identify->EnabledCommandSet3) & 0x0004) == 0x0004)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CanReadMediaSerial", "%s", "TRUE");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Manufacturer", "%s",
AtaToCString(identify->MediaManufacturer, 20));
}
else
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Manufacturer", "%s", mediaManufacturer);
printf("Trying READ SECTOR(S) in CHS mode...\n");
error = Read(fd, &buffer, &ata_error_chs, FALSE, 0, 0, 1, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead", "%s",
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying READ SECTOR(S) RETRY in CHS mode...\n");
error = Read(fd, &buffer, &ata_error_chs, TRUE, 0, 0, 1, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadRetry", "%s",
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying READ DMA in CHS mode...\n");
error = ReadDma(fd, &buffer, &ata_error_chs, FALSE, 0, 0, 1, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDma", "%s",
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying READ DMA RETRY in CHS mode...\n");
error = ReadDma(fd, &buffer, &ata_error_chs, TRUE, 0, 0, 1, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaRetry", "%s",
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying SEEK in CHS mode...\n");
error = Seek(fd, &ata_error_chs, 0, 0, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsSeek", "%s",
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
ata_error_chs->error == 0) ? "true" : "false");
printf("Trying READ SECTOR(S) in LBA mode...\n");
error = ReadLba(fd, &buffer, &ata_error_lba, FALSE, 0, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLba", "%s",
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying READ SECTOR(S) RETRY in LBA mode...\n");
error = ReadLba(fd, &buffer, &ata_error_lba, TRUE, 0, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadRetryLba", "%s",
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying READ DMA in LBA mode...\n");
error = ReadDmaLba(fd, &buffer, &ata_error_lba, FALSE, 0, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaLba", "%s",
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying READ DMA RETRY in LBA mode...\n");
error = ReadDmaLba(fd, &buffer, &ata_error_lba, TRUE, 0, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaRetryLba", "%s",
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying SEEK in LBA mode...\n");
error = SeekLba(fd, &ata_error_lba, 0);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsSeekLba", "%s",
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
ata_error_lba->error == 0) ? "true" : "false");
printf("Trying READ SECTOR(S) in LBA48 mode...\n");
error = ReadLba48(fd, &buffer, &ata_error_lba48, 0, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLba48", "%s",
(!error && (ata_error_lba48->status & 0x01) != 0x01 &&
ata_error_lba48->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying READ DMA in LBA48 mode...\n");
error = ReadDmaLba48(fd, &buffer, &ata_error_lba48, 0, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaLba48", "%s",
(!error && (ata_error_lba48->status & 0x01) != 0x01 &&
ata_error_lba48->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying READ LONG in CHS mode...\n");
error = ReadLong(fd, &buffer, &ata_error_chs, FALSE, 0, 0, 1, longblocksize);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLong", "%s",
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
ata_error_chs->error == 0 && buffer != NULL &&
(uint64_t)(*buffer) != 0) ? "true" : "false");
printf("Trying READ LONG RETRY in CHS mode...\n");
error = ReadLong(fd, &buffer, &ata_error_chs, TRUE, 0, 0, 1, longblocksize);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLongRetry", "%s",
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
ata_error_chs->error == 0 && buffer != NULL &&
(uint64_t)(*buffer) != 0) ? "true" : "false");
printf("Trying READ LONG in LBA mode...\n");
error = ReadLongLba(fd, &buffer, &ata_error_lba, FALSE, 0, longblocksize);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLongLba", "%s",
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
ata_error_lba->error == 0 && buffer != NULL &&
(uint64_t)(*buffer) != 0) ? "true" : "false");
printf("Trying READ LONG RETRY in LBA mode...\n");
error = ReadLongLba(fd, &buffer, &ata_error_lba, TRUE, 0, longblocksize);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLongRetryLba", "%s",
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
ata_error_lba->error == 0 && buffer != NULL &&
(uint64_t)(*buffer) != 0) ? "true" : "false");
xmlTextWriterEndElement(xmlWriter); // </testedMediaType>
if(!anyMedia)
anyMedia = TRUE;
}
}
if(anyMedia)
xmlTextWriterEndElement(xmlWriter); // </RemovableMedias>
}
else
{
error = Identify(fd, &ata_ident, &ata_error_chs);
xmlTextWriterStartElement(xmlWriter, BAD_CAST "ReadCapabilities"); // <RemovableMedias>
free(identify);
identify = malloc(512);
memcpy(identify, ata_ident, 512);
if(identify->UnformattedBPT)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "UnformattedBPT", "%u",
le16toh(identify->UnformattedBPT));
if(identify->UnformattedBPS)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "UnformattedBPS", "%u",
le16toh(identify->UnformattedBPS));
uint64_t blocks;
if(identify->Cylinders > 0 && identify->Heads > 0 && identify->SectorsPerTrack != 0)
{
xmlTextWriterStartElement(xmlWriter, BAD_CAST "CHS"); // <CHS>
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Cylinders", "%u", le16toh(identify->Cylinders));
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Heads", "%u", le16toh(identify->Heads));
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Sectors", "%u", le16toh(identify->SectorsPerTrack));
blocks = le16toh(identify->Cylinders) * le16toh(identify->Heads) * le16toh(identify->SectorsPerTrack);
xmlTextWriterEndElement(xmlWriter); // </CHS>
}
if(identify->CurrentCylinders > 0 && identify->CurrentHeads > 0 && identify->CurrentSectorsPerTrack != 0)
{
xmlTextWriterStartElement(xmlWriter, BAD_CAST "CurrentCHS"); // <CurrentCHS>
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Cylinders", "%u", le16toh(identify->CurrentCylinders));
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Heads", "%u", le16toh(identify->CurrentHeads));
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Sectors", "%u",
le16toh(identify->CurrentSectorsPerTrack));
if(blocks == 0)
blocks = le16toh(identify->CurrentCylinders) * le16toh(identify->CurrentHeads) *
le16toh(identify->CurrentSectorsPerTrack);
xmlTextWriterEndElement(xmlWriter); // </CurrentCHS>
}
if(le16toh(identify->Capabilities) & 0x0200)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LBASectors", "%u", le32toh(identify->LBASectors));
blocks = le32toh(identify->LBASectors);
}
if(le16toh(identify->CommandSet2) & 0x0400)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LBA48Sectors", "%llu",
le64toh(identify->LBA48Sectors));
blocks = le64toh(identify->LBA48Sectors);
}
if(identify->NominalRotationRate != 0x0000 && identify->NominalRotationRate != 0xFFFF)
{
if(le16toh(identify->NominalRotationRate) == 0x0001)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SolidStateDevice", "%s", "TRUE");
else
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SolidStateDevice", "%s", "TRUE");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NominalRotationRate", "%u",
le16toh(identify->NominalRotationRate));
}
}
uint32_t logicalsectorsize = 0;
uint32_t physicalsectorsize = 0;
if((le16toh(identify->PhysLogSectorSize) & 0x8000) == 0x0000 &&
(le16toh(identify->PhysLogSectorSize) & 0x4000) == 0x4000)
{
if(le16toh(identify->PhysLogSectorSize) & 0x1000)
{
if(le16toh(identify->LogicalSectorWords) <= 255 || identify->LogicalAlignment == 0xFFFF)
logicalsectorsize = 512;
else
logicalsectorsize = le16toh(identify->LogicalSectorWords) * 2;
}
else
logicalsectorsize = 512;
if(le16toh(identify->PhysLogSectorSize) & 0x2000)
physicalsectorsize = logicalsectorsize * (1 << (le16toh(identify->PhysLogSectorSize) & 0xF));
else
physicalsectorsize = logicalsectorsize;
}
else
{
logicalsectorsize = 512;
physicalsectorsize = 512;
}
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BlockSize", "%u", logicalsectorsize);
if(physicalsectorsize != logicalsectorsize)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PhysicalBlockSize", "%u", physicalsectorsize);
if((le16toh(identify->LogicalAlignment) & 0x8000) == 0x0000 &&
(le16toh(identify->LogicalAlignment) & 0x4000) == 0x4000)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LogicalAlignment", "%u",
le16toh(identify->LogicalAlignment) & 0x3FFF);
}
uint16_t longblocksize = 0;
if(identify->EccBytes != 0x0000 && identify->EccBytes != 0xFFFF)
longblocksize = le16toh(identify->EccBytes);
if(le16toh(identify->UnformattedBPS) > logicalsectorsize && (longblocksize == 0 || longblocksize == 516))
longblocksize = le16toh(identify->UnformattedBPS);
if(longblocksize > 0)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LongBlockSize", "%u", longblocksize);
if((le16toh(identify->CommandSet3) & 0x8000) == 0x0000 && (le16toh(identify->CommandSet3) & 0x4000) == 0x4000 &&
(le16toh(identify->EnabledCommandSet3) & 0x0004) == 0x0004)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CanReadMediaSerial", "%s", "TRUE");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Manufacturer", "%s",
AtaToCString(identify->MediaManufacturer, 20));
}
printf("Trying READ SECTOR(S) in CHS mode...\n");
error = Read(fd, &buffer, &ata_error_chs, FALSE, 0, 0, 1, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead", "%s",
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying READ SECTOR(S) RETRY in CHS mode...\n");
error = Read(fd, &buffer, &ata_error_chs, TRUE, 0, 0, 1, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadRetry", "%s",
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying READ DMA in CHS mode...\n");
error = ReadDma(fd, &buffer, &ata_error_chs, FALSE, 0, 0, 1, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDma", "%s",
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying READ DMA RETRY in CHS mode...\n");
error = ReadDma(fd, &buffer, &ata_error_chs, TRUE, 0, 0, 1, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaRetry", "%s",
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
ata_error_chs->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying SEEK in CHS mode...\n");
error = Seek(fd, &ata_error_chs, 0, 0, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsSeek", "%s",
(!error && (ata_error_chs->status & 0x01) != 0x01 && ata_error_chs->error == 0)
? "true" : "false");
printf("Trying READ SECTOR(S) in LBA mode...\n");
error = ReadLba(fd, &buffer, &ata_error_lba, FALSE, 0, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLba", "%s",
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying READ SECTOR(S) RETRY in LBA mode...\n");
error = ReadLba(fd, &buffer, &ata_error_lba, TRUE, 0, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadRetryLba", "%s",
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying READ DMA in LBA mode...\n");
error = ReadDmaLba(fd, &buffer, &ata_error_lba, FALSE, 0, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaLba", "%s",
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying READ DMA RETRY in LBA mode...\n");
error = ReadDmaLba(fd, &buffer, &ata_error_lba, TRUE, 0, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaRetryLba", "%s",
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
ata_error_lba->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying SEEK in LBA mode...\n");
error = SeekLba(fd, &ata_error_lba, 0);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsSeekLba", "%s",
(!error && (ata_error_lba->status & 0x01) != 0x01 && ata_error_lba->error == 0)
? "true" : "false");
printf("Trying READ SECTOR(S) in LBA48 mode...\n");
error = ReadLba48(fd, &buffer, &ata_error_lba48, 0, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLba48", "%s",
(!error && (ata_error_lba48->status & 0x01) != 0x01 &&
ata_error_lba48->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying READ DMA in LBA48 mode...\n");
error = ReadDmaLba48(fd, &buffer, &ata_error_lba48, 0, 1);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadDmaLba48", "%s",
(!error && (ata_error_lba48->status & 0x01) != 0x01 &&
ata_error_lba48->error == 0 && buffer != NULL) ? "true" : "false");
printf("Trying READ LONG in CHS mode...\n");
error = ReadLong(fd, &buffer, &ata_error_chs, FALSE, 0, 0, 1, longblocksize);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLong", "%s",
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
ata_error_chs->error == 0 && buffer != NULL && (uint64_t)(*buffer) != 0)
? "true" : "false");
printf("Trying READ LONG RETRY in CHS mode...\n");
error = ReadLong(fd, &buffer, &ata_error_chs, TRUE, 0, 0, 1, longblocksize);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLongRetry", "%s",
(!error && (ata_error_chs->status & 0x01) != 0x01 &&
ata_error_chs->error == 0 && buffer != NULL && (uint64_t)(*buffer) != 0)
? "true" : "false");
printf("Trying READ LONG in LBA mode...\n");
error = ReadLongLba(fd, &buffer, &ata_error_lba, FALSE, 0, longblocksize);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLongLba", "%s",
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
ata_error_lba->error == 0 && buffer != NULL && (uint64_t)(*buffer) != 0)
? "true" : "false");
printf("Trying READ LONG RETRY in LBA mode...\n");
error = ReadLongLba(fd, &buffer, &ata_error_lba, TRUE, 0, longblocksize);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLongRetryLba", "%s",
(!error && (ata_error_lba->status & 0x01) != 0x01 &&
ata_error_lba->error == 0 && buffer != NULL && (uint64_t)(*buffer) != 0)
? "true" : "false");
xmlTextWriterEndElement(xmlWriter); // </ReadCapabilities>
}
xmlTextWriterEndElement(xmlWriter);
}

View File

@@ -1,39 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : ata_report.h
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Contains definitions used in ATA reports.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#ifndef DISCIMAGECHEF_DEVICE_REPORT_ATA_REPORT_H
#define DISCIMAGECHEF_DEVICE_REPORT_ATA_REPORT_H
#define DIC_ATA_REPORT_ELEMENT "ATA"
void AtaReport(int fd, xmlTextWriterPtr xmlWriter);
#endif //DISCIMAGECHEF_DEVICE_REPORT_ATA_REPORT_H

View File

@@ -1,52 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : atapi.c
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Contains ATAPI commands.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#include <malloc.h>
#include <string.h>
#include <stdint.h>
#include "ata.h"
#include "atapi.h"
int IdentifyPacket(int fd, unsigned char **buffer, AtaErrorRegistersCHS **errorRegisters)
{
*buffer = malloc(512);
memset(*buffer, 0, 512);
AtaRegistersCHS registers;
memset(&registers, 0, sizeof(AtaRegistersCHS));
registers.command = ATA_IDENTIFY_PACKET_DEVICE;
int error = SendAtaCommandChs(fd, registers, errorRegisters, ATA_PROTOCOL_PIO_IN, ATA_TRANSFER_NONE, *buffer, 512,
0);
return error;
}

View File

@@ -1,38 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : atapi.h
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Contains ATAPI definitions.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#ifndef DISCIMAGECHEF_DEVICE_REPORT_ATAPI_H
#define DISCIMAGECHEF_DEVICE_REPORT_ATAPI_H
int IdentifyPacket(int fd, unsigned char **buffer, AtaErrorRegistersCHS **errorRegisters);
#endif //DISCIMAGECHEF_DEVICE_REPORT_ATAPI_H

View File

@@ -1,272 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : atapi_report.c
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Creates report for ATAPI devices.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#include <string.h>
#include <libxml/xmlwriter.h>
#include "atapi_report.h"
#include "ata.h"
#include "atapi.h"
#include "identify_decode.h"
void AtapiReport(int fd, xmlTextWriterPtr xmlWriter)
{
unsigned char *atapi_ident = NULL;
AtaErrorRegistersCHS *ata_error_chs;
int error;
printf("Querying ATAPI IDENTIFY...\n");
error = IdentifyPacket(fd, &atapi_ident, &ata_error_chs);
if(error)
{
fprintf(stderr, "Error {0} requesting IDENTIFY PACKET DEVICE", error);
return;
}
IdentifyDevice *identify = malloc(512);
memcpy(identify, atapi_ident, 512);
xmlTextWriterStartElement(xmlWriter, BAD_CAST DIC_ATAPI_REPORT_ELEMENT); // <ATA>
if((uint64_t)*identify->AdditionalPID != 0 && (uint64_t)*identify->AdditionalPID != 0x2020202020202020)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "AdditionalPid", AtaToCString(identify->AdditionalPID, 8));
if(identify->APIOSupported)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "APIOSupported",
DecodeTransferMode(le16toh(identify->APIOSupported)));
if(identify->ATAPIByteCount)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ATAPIByteCount", "%u", le16toh(identify->ATAPIByteCount));
if(identify->BufferType)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BufferType", "%u", le16toh(identify->BufferType));
if(identify->BufferSize)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BufferSize", "%u", le16toh(identify->BufferSize));
if(identify->Capabilities)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Capabilities",
DecodeCapabilities(le16toh(identify->Capabilities)));
if(identify->Capabilities2)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Capabilities2",
DecodeCapabilities2(le16toh(identify->Capabilities2)));
if(identify->Capabilities3)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Capabilities3", DecodeCapabilities3(identify->Capabilities3));
if(identify->CFAPowerMode)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CFAPowerMode", "%u", le16toh(identify->CFAPowerMode));
if(identify->CommandSet)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet", DecodeCommandSet(le16toh(identify->CommandSet)));
if(identify->CommandSet2)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet2", DecodeCommandSet2(le16toh(identify->CommandSet2)));
if(identify->CommandSet3)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet3", DecodeCommandSet3(le16toh(identify->CommandSet3)));
if(identify->CommandSet4)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet4", DecodeCommandSet4(le16toh(identify->CommandSet4)));
if(identify->CommandSet5)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "CommandSet5", DecodeCommandSet5(le16toh(identify->CommandSet5)));
if(identify->CurrentAAM)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CurrentAAM", "%u", identify->CurrentAAM);
if(identify->CurrentAPM)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "CurrentAPM", "%u", le16toh(identify->CurrentAPM));
if(identify->DataSetMgmt)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DataSetMgmt", DecodeDataSetMgmt(le16toh(identify->DataSetMgmt)));
if(identify->DataSetMgmtSize)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "DataSetMgmtSize", "%u",
le16toh(identify->DataSetMgmtSize));
if(identify->DeviceFormFactor)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DeviceFormFactor",
DecodeDeviceFormFactor(le16toh(identify->DeviceFormFactor)));
if(identify->DMAActive)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DMAActive", DecodeTransferMode(le16toh(identify->DMAActive)));
if(identify->DMASupported)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "DMASupported",
DecodeTransferMode(le16toh(identify->DMASupported)));
if(identify->DMATransferTimingMode)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "DMATransferTimingMode", "%u",
identify->DMATransferTimingMode);
if(identify->EnhancedSecurityEraseTime)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "EnhancedSecurityEraseTime", "%u",
le16toh(identify->EnhancedSecurityEraseTime));
if(identify->EnabledCommandSet)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet",
DecodeCommandSet(le16toh(identify->EnabledCommandSet)));
if(identify->EnabledCommandSet2)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet2",
DecodeCommandSet2(le16toh(identify->EnabledCommandSet2)));
if(identify->EnabledCommandSet3)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet3",
DecodeCommandSet3(le16toh(identify->EnabledCommandSet3)));
if(identify->EnabledCommandSet4)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledCommandSet4",
DecodeCommandSet4(le16toh(identify->EnabledCommandSet4)));
if(identify->EnabledSATAFeatures)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "EnabledSATAFeatures",
DecodeSATAFeatures(le16toh(identify->EnabledSATAFeatures)));
if(identify->ExtendedUserSectors)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ExtendedUserSectors", "%llu",
le64toh(identify->ExtendedUserSectors));
if(identify->FreeFallSensitivity)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "FreeFallSensitivity", "%u", identify->FreeFallSensitivity);
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "FirmwareRevision", AtaToCString(identify->FirmwareRevision, 8));
if(identify->GeneralConfiguration)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "GeneralConfiguration",
DecodeGeneralConfiguration(le16toh(identify->GeneralConfiguration)));
if(identify->HardwareResetResult)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "HardwareResetResult", "%u",
le16toh(identify->HardwareResetResult));
if(identify->InterseekDelay)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "InterseekDelay", "%u", le16toh(identify->InterseekDelay));
if(identify->MajorVersion)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "MajorVersion",
DecodeMajorVersion(le16toh(identify->MajorVersion)));
if(identify->MasterPasswordRevisionCode)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MasterPasswordRevisionCode", "%u",
le16toh(identify->MasterPasswordRevisionCode));
if(identify->MaxDownloadMicroMode3)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MaxDownloadMicroMode3", "%u",
le16toh(identify->MaxDownloadMicroMode3));
if(identify->MaxQueueDepth)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MaxQueueDepth", "%u", le16toh(identify->MaxQueueDepth));
if(identify->MDMAActive)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "MDMAActive", DecodeTransferMode(le16toh(identify->MDMAActive)));
if(identify->MDMASupported)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "MDMASupported",
DecodeTransferMode(le16toh(identify->MDMASupported)));
if(identify->MinDownloadMicroMode3)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinDownloadMicroMode3", "%u",
le16toh(identify->MinDownloadMicroMode3));
if(identify->MinMDMACycleTime)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinMDMACycleTime", "%u",
le16toh(identify->MinMDMACycleTime));
if(identify->MinorVersion)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinorVersion", "%u", le16toh(identify->MinorVersion));
if(identify->MinPIOCycleTimeNoFlow)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinPIOCycleTimeNoFlow", "%u",
le16toh(identify->MinPIOCycleTimeNoFlow));
if(identify->MinPIOCycleTimeFlow)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MinPIOCycleTimeFlow", "%u",
le16toh(identify->MinPIOCycleTimeFlow));
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "Model", AtaToCString(identify->Model, 40));
if(identify->MultipleMaxSectors)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MultipleMaxSectors", "%u", identify->MultipleMaxSectors);
if(identify->MultipleSectorNumber)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MultipleSectorNumber", "%u",
identify->MultipleSectorNumber);
if(identify->NVCacheCaps)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVCacheCaps", "%u", le16toh(identify->NVCacheCaps));
if(identify->NVCacheSize)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVCacheSize", "%u", le32toh(identify->NVCacheSize));
if(identify->NVCacheWriteSpeed)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVCacheWriteSpeed", "%u",
le16toh(identify->NVCacheWriteSpeed));
if(identify->NVEstimatedSpinUp)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NVEstimatedSpinUp", "%u", identify->NVEstimatedSpinUp);
if(identify->PacketBusRelease)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PacketBusRelease", "%u",
le16toh(identify->PacketBusRelease));
if(identify->PIOTransferTimingMode)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PIOTransferTimingMode", "%u",
identify->PIOTransferTimingMode);
if(identify->RecommendedAAM)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "RecommendedAAM", "%u", identify->RecommendedAAM);
if(identify->RecMDMACycleTime)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "RecMDMACycleTime", "%u",
le16toh(identify->RecMDMACycleTime));
if(identify->RemovableStatusSet)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "RemovableStatusSet", "%u",
le16toh(identify->RemovableStatusSet));
if(identify->SATACapabilities)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SATACapabilities",
DecodeSATACapabilities(le16toh(identify->SATACapabilities)));
if(identify->SATACapabilities2)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SATACapabilities2",
DecodeSATACapabilities2(le16toh(identify->SATACapabilities2)));
if(identify->SATAFeatures)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SATAFeatures",
DecodeSATAFeatures(le16toh(identify->SATAFeatures)));
if(identify->SCTCommandTransport)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SCTCommandTransport",
DecodeSCTCommandTransport(le16toh(identify->SCTCommandTransport)));
if(identify->SectorsPerCard)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SectorsPerCard", "%u", le32toh(identify->SectorsPerCard));
if(identify->SecurityEraseTime)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SecurityEraseTime", "%u",
le16toh(identify->SecurityEraseTime));
if(identify->SecurityStatus)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SecurityStatus",
DecodeSecurityStatus(le16toh(identify->SecurityStatus)));
if(identify->ServiceBusyClear)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ServiceBusyClear", "%u",
le16toh(identify->ServiceBusyClear));
if(identify->SpecificConfiguration)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "SpecificConfiguration",
DecodeSpecificConfiguration(le16toh(identify->SpecificConfiguration)));
if(identify->StreamAccessLatency)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamAccessLatency", "%u",
le16toh(identify->StreamAccessLatency));
if(identify->StreamMinReqSize)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamMinReqSize", "%u",
le16toh(identify->StreamMinReqSize));
if(identify->StreamPerformanceGranularity)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamPerformanceGranularity", "%u",
le32toh(identify->StreamPerformanceGranularity));
if(identify->StreamTransferTimeDMA)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamTransferTimeDMA", "%u",
le16toh(identify->StreamTransferTimeDMA));
if(identify->StreamTransferTimePIO)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StreamTransferTimePIO", "%u",
le16toh(identify->StreamTransferTimePIO));
if(identify->TransportMajorVersion)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "TransportMajorVersion", "%u",
le16toh(identify->TransportMajorVersion));
if(identify->TransportMinorVersion)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "TransportMinorVersion", "%u",
le16toh(identify->TransportMinorVersion));
if(identify->TrustedComputing)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "TrustedComputing",
DecodeTrustedComputing(le16toh(identify->TrustedComputing)));
if(identify->UDMAActive)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "UDMAActive", DecodeTransferMode(le16toh(identify->UDMAActive)));
if(identify->UDMASupported)
xmlTextWriterWriteElement(xmlWriter, BAD_CAST "UDMASupported",
DecodeTransferMode(le16toh(identify->UDMASupported)));
if(identify->WRVMode)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WRVMode", "%u", identify->WRVMode);
if(identify->WRVSectorCountMode3)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WRVSectorCountMode3", "%u",
le32toh(identify->WRVSectorCountMode3));
if(identify->WRVSectorCountMode2)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WRVSectorCountMode2", "%u",
le32toh(identify->WRVSectorCountMode2));
xmlTextWriterStartElement(xmlWriter, BAD_CAST "Identify"); // <Identify>
xmlTextWriterWriteBase64(xmlWriter, atapi_ident, 0, 512);
xmlTextWriterEndElement(xmlWriter); // </Identify>
xmlTextWriterEndElement(xmlWriter); // </ATA>
}

View File

@@ -1,40 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : atapi_report.h
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Contains definitions used in ATAPI reports.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#ifndef DISCIMAGECHEF_DEVICE_REPORT_ATAPI_REPORT_H
#define DISCIMAGECHEF_DEVICE_REPORT_ATAPI_REPORT_H
#define DIC_ATAPI_REPORT_ELEMENT "ATAPI"
void AtapiReport(int fd, xmlTextWriterPtr xmlWriter);
#endif //DISCIMAGECHEF_DEVICE_REPORT_ATAPI_REPORT_H

View File

@@ -1,142 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : cdrom_mode.h
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Contains definitions for CD-ROM MODE PAGE (2Ah).
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#ifndef DISCIMAGECHEF_DEVICE_REPORT_CDROM_MODE_H
#define DISCIMAGECHEF_DEVICE_REPORT_CDROM_MODE_H
#pragma pack(push, 1)
typedef struct
{
uint8_t Reserved1;
uint8_t RotationControl : 3;
uint8_t Reserved2 : 5;
uint16_t WriteSpeed;
} ModePage_2A_WriteDescriptor;
#pragma pack(pop)
#pragma pack(push, 1)
typedef struct
{
uint8_t PageCode : 6;
uint8_t Reserved1 : 1;
/* Parameters can be saved */
uint8_t PS : 1;
uint8_t PageLength;
uint8_t ReadCDR : 1;
uint8_t ReadCDRW : 1;
uint8_t Method2 : 1;
uint8_t ReadDVDROM : 1;
uint8_t ReadDVDR : 1;
uint8_t ReadDVDRAM : 1;
uint8_t Reserved2 : 2;
uint8_t WriteCDR : 1;
uint8_t WriteCDRW : 1;
uint8_t TestWrite : 1;
uint8_t Reserved3 : 1;
uint8_t WriteDVDR : 1;
uint8_t WriteDVDRAM : 1;
uint8_t Reserved4 : 2;
/* Drive is capable of playing audio */
uint8_t AudioPlay : 1;
uint8_t Composite : 1;
uint8_t DigitalPort1 : 1;
uint8_t DigitalPort2 : 1;
/* Drive is capable of reading sectors in Mode 2 Form 1 format */
uint8_t Mode2Form1 : 1;
/* Drive is capable of reading sectors in Mode 2 Form 2 format */
uint8_t Mode2Form2 : 1;
/* Drive supports multi-session and/or Photo-CD */
uint8_t MultiSession : 1;
uint8_t BUF : 1;
/* Audio can be read as digital data */
uint8_t CDDACommand : 1;
/* Drive can continue from a loss of streaming on audio reading */
uint8_t AccurateCDDA : 1;
/* Drive can read interleaved and uncorrected R-W subchannels */
uint8_t Subchannel : 1;
/* Drive can read, deinterlave and correct R-W subchannels */
uint8_t DeinterlaveSubchannel : 1;
/* Drive can return C2 pointers */
uint8_t C2Pointer : 1;
/* Drive can return the media catalogue number */
uint8_t UPC : 1;
/* Drive can return the ISRC */
uint8_t ISRC : 1;
uint8_t ReadBarcode : 1;
/* Drive can lock media */
uint8_t Lock : 1;
/* Current lock status */
uint8_t LockState : 1;
/* Drive's optional prevent jumper status */
uint8_t PreventJumper : 1;
/* Drive can eject discs */
uint8_t Eject : 1;
uint8_t Reserved5 : 1;
/* Loading Mechanism Type */
uint8_t LoadingMechanism : 3;
/* Each channel's volume can be controlled independently */
uint8_t SeparateChannelVolume : 1;
/* Each channel can be muted independently */
uint8_t SeparateChannelMute : 1;
uint8_t SDP : 1;
uint8_t SSS : 1;
uint8_t SCC : 1;
uint8_t LeadInPW : 1;
uint8_t Reserved6 : 2;
/* Maximum drive speed in Kbytes/second */
uint16_t MaximumSpeed;
/* Supported volume levels */
uint16_t SupportedVolumeLevels;
/* Buffer size in Kbytes */
uint16_t BufferSize;
/* Current drive speed in Kbytes/second */
uint16_t CurrentSpeed;
uint8_t Reserved7;
uint8_t Reserved8 : 1;
uint8_t BCK : 1;
uint8_t RCK : 1;
uint8_t LSBF : 1;
uint8_t Length : 2;
uint8_t Reserved9 : 2;
uint16_t MaxWriteSpeed;
uint16_t CurrentWriteSpeed;
uint16_t CMRSupported;
uint8_t Reserved10[3];
uint8_t RotationControlSelected : 2;
uint8_t Reserved11 : 6;
uint16_t CurrentWriteSpeedSelected;
uint16_t LogicalWriteSpeedDescriptors;
ModePage_2A_WriteDescriptor WriteSpeedPerformanceDescriptors[56];
} ModePage_2A;
#pragma pack(pop)
#endif //DISCIMAGECHEF_DEVICE_REPORT_CDROM_MODE_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,76 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : identify_decode.h
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Contains definitions for ATA IDENTIFY (PACKET) DEVICE structure.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#ifndef DISCIMAGECHEF_DEVICE_REPORT_IDENTIFY_DECODE_H
#define DISCIMAGECHEF_DEVICE_REPORT_IDENTIFY_DECODE_H
char *DecodeGeneralConfiguration(uint16_t configuration);
char *DecodeTransferMode(uint16_t transferMode);
char *DecodeCapabilities(uint16_t capabilities);
char *DecodeCapabilities2(uint16_t capabilities);
char *DecodeCapabilities3(uint8_t capabilities);
char *DecodeCommandSet(uint16_t commandset);
char *DecodeCommandSet2(uint16_t commandset);
char *DecodeCommandSet3(uint16_t commandset);
char *DecodeCommandSet4(uint16_t commandset);
char *DecodeCommandSet5(uint16_t commandset);
char *DecodeDataSetMgmt(uint16_t datasetmgmt);
char *DecodeDeviceFormFactor(uint16_t formfactor);
char *DecodeSATAFeatures(uint16_t features);
char *DecodeMajorVersion(uint16_t capabilities);
char *DecodeSATACapabilities(uint16_t capabilities);
char *DecodeSATACapabilities2(uint16_t transport);
char *DecodeSCTCommandTransport(uint16_t transport);
char *DecodeSecurityStatus(uint16_t status);
char *DecodeSpecificConfiguration(uint16_t configuration);
char *DecodeTrustedComputing(uint16_t trutedcomputing);
#endif //DISCIMAGECHEF_DEVICE_REPORT_IDENTIFY_DECODE_H

View File

@@ -1,141 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : inquiry_decode.c
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Contains decoders for SCSI INQUIRY structure.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#include <stdint.h>
#include <string.h>
#include "inquiry_decode.h"
char *DecodeTPGSValues(uint8_t capabilities)
{
switch(capabilities)
{
case 0:
return "NotSupported";
case 1:
return "OnlyImplicit";
case 2:
return "OnlyExplicit";
case 3:
return "Both";
default:
return NULL;
}
}
char *DecodePeripheralDeviceType(uint8_t type)
{
switch(type)
{
case 0x00:
return "DirectAccess";
case 0x01:
return "SequentialAccess";
case 0x02:
return "PrinterDevice";
case 0x03:
return "ProcessorDevice";
case 0x04:
return "WriteOnceDevice";
case 0x05:
return "MultiMediaDevice";
case 0x06:
return "ScannerDevice";
case 0x07:
return "OpticalDevice";
case 0x08:
return "MediumChangerDevice";
case 0x09:
return "CommsDevice";
case 0x0A:
return "PrePressDevice1";
case 0x0B:
return "PrePressDevice2";
case 0x0C:
return "ArrayControllerDevice";
case 0x0D:
return "EnclosureServiceDevice";
case 0x0E:
return "SimplifiedDevice";
case 0x0F:
return "OCRWDevice";
case 0x10:
return "BridgingExpander";
case 0x11:
return "ObjectDevice";
case 0x12:
return "ADCDevice";
case 0x13:
return "SCSISecurityManagerDevice";
case 0x14:
return "SCSIZonedBlockDevice";
case 0x1E:
return "WellKnownDevice";
case 0x1F:
return "UnknownDevice";
default:
return NULL;
}
}
char *DecodePeripheralQualifier(uint8_t qualifier)
{
switch(qualifier)
{
case 0:
return "Supported";
case 1:
return "Unconnected";
case 2:
return "Reserved";
case 3:
return "Unsupported";
default:
return NULL;
}
}
char *DecodeSPIClocking(uint8_t qualifier)
{
switch(qualifier)
{
case 0:
return "ST";
case 1:
return "DT";
case 2:
return "Reserved";
case 3:
return "StandDT";
default:
return NULL;
}
}

View File

@@ -1,44 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : inquiry_decode.h
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Contains definitions for SCSI INQUIRY structure.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#ifndef DISCIMAGECHEF_DEVICE_REPORT_INQUIRY_DECODE_H
#define DISCIMAGECHEF_DEVICE_REPORT_INQUIRY_DECODE_H
char *DecodeTPGSValues(uint8_t capabilities);
char *DecodePeripheralDeviceType(uint8_t capabilities);
char *DecodePeripheralQualifier(uint8_t capabilities);
char *DecodeSPIClocking(uint8_t capabilities);
#endif //DISCIMAGECHEF_DEVICE_REPORT_INQUIRY_DECODE_H

View File

@@ -1,186 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : main.c
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
For Linux, opens a device and generates a report, without needing a .NET
environment, for systems that don't have it.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <malloc.h>
#include <libxml/xmlwriter.h>
#include "main.h"
#include "scsi.h"
#include "ata.h"
#include "atapi.h"
#include "atapi_report.h"
#include "scsi_report.h"
#include "ata_report.h"
int main(int argc, void *argv[])
{
int fd, rc;
unsigned char *scsi_sense = NULL;
unsigned char *scsi_inq_data = NULL;
unsigned char *ata_ident = NULL;
unsigned char *atapi_ident = NULL;
AtaErrorRegistersCHS *ata_error_chs;
int scsi_error, ata_error;
unsigned char *manufacturer;
unsigned char *product;
unsigned char *revision;
int deviceType = DEVICE_TYPE_UNKNOWN;
char *xmlFilename = malloc(NAME_MAX + 1);
xmlTextWriterPtr xmlWriter;
const char *ataName = "ATA";
printf("The Disc Image Chef Device Reporter for Linux %s\n", DIC_VERSION);
printf("%s\n", DIC_COPYRIGHT);
if(argc != 2)
{
printf("Usage:\n");
printf("%s <device_path>\n", argv[0]);
return 1;
}
fd = open(argv[1], O_RDONLY | O_NONBLOCK);
if(fd < 0)
{
printf("Error opening device: %s\n", strerror(errno));
return 2;
}
// TODO: Support MMC, USB, FireWire, PCMCIA
scsi_error = Inquiry(fd, &scsi_inq_data, &scsi_sense);
if(scsi_error)
scsi_inq_data = NULL;
if(scsi_inq_data != NULL)
{
manufacturer = malloc(9);
manufacturer[8] = 0;
product = malloc(17);
product[16] = 0;
revision = malloc(5);
revision[4] = 0;
strncpy(manufacturer, scsi_inq_data + 8, 8);
strncpy(product, scsi_inq_data + 16, 16);
strncpy(revision, scsi_inq_data + 32, 4);
deviceType = DEVICE_TYPE_SCSI;
ata_error = IdentifyPacket(fd, &atapi_ident, &ata_error_chs);
if(!ata_error)
deviceType = DEVICE_TYPE_ATAPI;
}
if(scsi_inq_data == NULL || !strncmp((const char *)manufacturer, ataName, 3))
{
ata_error = Identify(fd, &ata_ident, &ata_error_chs);
if(!ata_error)
{
deviceType = DEVICE_TYPE_ATA;
revision = AtaToCString(ata_ident + (23 * 2), 8);
product = AtaToCString(ata_ident + (27 * 2), 40);
}
}
printf("Device type: %s\n", DeviceType[deviceType]);
printf("Manufacturer: %s\n", manufacturer);
printf("Product: %s\n", product);
printf("Revision: %s\n", revision);
if(deviceType != DEVICE_TYPE_ATA && deviceType != DEVICE_TYPE_ATAPI && deviceType != DEVICE_TYPE_SCSI)
{
printf("Unsupported device type %s.", DeviceType[deviceType]);
return 3;
}
sprintf(xmlFilename, "%s_%s_%s.xml", manufacturer, product, revision);
xmlWriter = xmlNewTextWriterFilename(xmlFilename, 0);
if(xmlWriter == NULL)
{
printf("Could not create XML report file.\n");
return 4;
}
rc = xmlTextWriterStartDocument(xmlWriter, NULL, XML_ENCODING, NULL);
if(rc < 0)
{
printf("Could not create XML report file.\n");
return 4;
}
rc = xmlTextWriterStartElement(xmlWriter, BAD_CAST DIC_REPORT_ROOT);
if(rc < 0)
{
printf("Could not create XML report file.\n");
return 4;
}
char *xmlComment = malloc(255);
sprintf(xmlComment, "Report created with DiscImageChef.Device.Report v%s", DIC_VERSION);
rc = xmlTextWriterWriteComment(xmlWriter, xmlComment);
if(rc < 0)
{
printf("Could not create XML report file.\n");
return 4;
}
if(deviceType == DEVICE_TYPE_ATAPI)
AtapiReport(fd, xmlWriter);
if(deviceType == DEVICE_TYPE_ATAPI || deviceType == DEVICE_TYPE_SCSI)
ScsiReport(fd, xmlWriter);
if(deviceType == DEVICE_TYPE_ATA)
AtaReport(fd, xmlWriter);
rc = xmlTextWriterEndDocument(xmlWriter);
if(rc < 0)
{
printf("Could not close XML report file.\n");
return 4;
}
close(fd);
return 0;
}

View File

@@ -1,56 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : main.h
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Contains global definitions.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#ifndef DISCIMAGECHEF_DEVICE_REPORT_MAIN_H
#define DISCIMAGECHEF_DEVICE_REPORT_MAIN_H
#define DIC_VERSION "4.5.99.1693"
#define DIC_COPYRIGHT "Copyright © 2011-2019 Natalia Portillo"
#define XML_ENCODING "UTF-8"
#define DIC_REPORT_ROOT "DicDeviceReport"
typedef enum
{
DEVICE_TYPE_UNKNOWN,
DEVICE_TYPE_SCSI,
DEVICE_TYPE_ATA,
DEVICE_TYPE_ATAPI,
DEVICE_TYPE_USB,
DEVICE_TYPE_FIREWIRE,
DEVICE_TYPE_PCMCIA,
DEVICE_TYPE_MMC,
DEVICE_TYPE_SD
} DeviceTypes;
const char *DeviceType[] = {"Unknown", "SCSI", "ATA", "ATAPI", "USB", "FireWire", "PCMCIA", "MultiMediaCard",
"SecureDigital"};
#endif //DISCIMAGECHEF_DEVICE_REPORT_MAIN_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,51 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : mmc_report.h
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Contains definitions used in SCSI MultiMedia device reports.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#ifndef DISCIMAGECHEF_DEVICE_REPORT_MMC_REPORT_H
#define DISCIMAGECHEF_DEVICE_REPORT_MMC_REPORT_H
void MmcReport(int fd, xmlTextWriterPtr xmlWriter, unsigned char *cdromMode);
typedef struct
{
int present;
size_t len;
unsigned char *data;
} FeatureDescriptors;
typedef struct
{
uint32_t DataLength;
uint16_t CurrentProfile;
FeatureDescriptors Descriptors[65536];
} SeparatedFeatures;
#endif //DISCIMAGECHEF_DEVICE_REPORT_MMC_REPORT_H

View File

@@ -1,978 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : scsi.c
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Contains SCSI commands.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#include <unitypes.h>
#include <malloc.h>
#include <scsi/sg.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <string.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)
return -1;
*senseBuffer = malloc(32);
memset(*senseBuffer, 0, 32);
sg_io_hdr_t io_hdr;
memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
io_hdr.interface_id = 'S';
io_hdr.cmd_len = cdb_len;
io_hdr.mx_sb_len = 32;
io_hdr.dxfer_direction = direction;
io_hdr.dxfer_len = buffer_len;
io_hdr.dxferp = buffer;
io_hdr.cmdp = cdb;
io_hdr.sbp = *senseBuffer;
io_hdr.timeout = 10000;
int error = ioctl(fd, SG_IO, &io_hdr);
if(error < 0)
error = errno;
else if(io_hdr.status != 0)
error = io_hdr.status;
else if(io_hdr.host_status != 0)
error = io_hdr.host_status;
else if(io_hdr.info != 0)
error = io_hdr.info & SG_INFO_OK_MASK;
return error;
}
int Inquiry(int fd, unsigned char **buffer, unsigned char **senseBuffer)
{
unsigned char cmd_len = 6;
*buffer = malloc(36);
memset(*buffer, 0, 36);
char cdb[] = {SCSI_INQUIRY, 0, 0, 0, 36, 0};
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, 36, senseBuffer, SG_DXFER_FROM_DEV);
if(error)
return error;
unsigned char pagesLength = *(*buffer + 4) + 5;
free(*buffer);
*buffer = malloc(pagesLength);
memset(*buffer, 0, pagesLength);
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;
}
int ReadCapacity(int fd, unsigned char **buffer, unsigned char **senseBuffer, int RelAddr, uint32_t address, int PMI)
{
unsigned char cmd_len = 10;
unsigned int buffer_len = 8;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
unsigned char cdb[] = {SCSI_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0};
if(PMI)
{
cdb[8] = 0x01;
if(RelAddr)
cdb[1] = 0x01;
cdb[2] = (uint8_t)((address & 0xFF000000) >> 24);
cdb[3] = (uint8_t)((address & 0xFF0000) >> 16);
cdb[4] = (uint8_t)((address & 0xFF00) >> 8);
cdb[5] = (uint8_t)(address & 0xFF);
}
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int ReadCapacity16(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint64_t address, int PMI)
{
unsigned char cmd_len = 16;
unsigned int buffer_len = 32;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
unsigned char cdb[] = {SCSI_SERVICE_ACTION_IN, SCSI_READ_CAPACITY_16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
if(PMI)
{
cdb[14] = 0x01;
cdb[2] = (uint8_t)((address & 0xFF00000000000000ULL) >> 56);
cdb[3] = (uint8_t)((address & 0xFF000000000000ULL) >> 48);
cdb[4] = (uint8_t)((address & 0xFF0000000000ULL) >> 40);
cdb[5] = (uint8_t)((address & 0xFF00000000ULL) >> 32);
cdb[6] = (uint8_t)((address & 0xFF000000ULL) >> 24);
cdb[7] = (uint8_t)((address & 0xFF0000ULL) >> 16);
cdb[8] = (uint8_t)((address & 0xFF00ULL) >> 8);
cdb[9] = (uint8_t)(address & 0xFFULL);
}
cdb[10] = (uint8_t)((buffer_len & 0xFF000000) >> 24);
cdb[11] = (uint8_t)((buffer_len & 0xFF0000) >> 16);
cdb[12] = (uint8_t)((buffer_len & 0xFF00) >> 8);
cdb[13] = (uint8_t)(buffer_len & 0xFF);
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int Read6(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t blockSize,
uint8_t transferLength)
{
unsigned char cmd_len = 6;
unsigned int buflen = transferLength == 0 ? 256 * blockSize : transferLength * blockSize;
*buffer = malloc(buflen);
memset(*buffer, 0, buflen);
unsigned char cdb[] = {SCSI_READ, 0, 0, 0, 0, 0};
cdb[1] = (uint8_t)((lba & 0x1F0000) >> 16);
cdb[2] = (uint8_t)((lba & 0xFF00) >> 8);
cdb[3] = (uint8_t)(lba & 0xFF);
cdb[4] = transferLength;
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buflen, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int Read10(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint8_t rdprotect, int dpo, int fua, int fuaNv,
int relAddr, uint32_t lba, uint32_t blockSize, uint8_t groupNumber, uint16_t transferLength)
{
unsigned char cmd_len = 10;
unsigned int buflen = transferLength * blockSize;
*buffer = malloc(buflen);
memset(*buffer, 0, buflen);
unsigned char cdb[] = {SCSI_READ_10, 0, 0, 0, 0, 0, 0, 0, 0, 0};
cdb[1] = (uint8_t)((rdprotect & 0x07) << 5);
if(dpo)
cdb[1] += 0x10;
if(fua)
cdb[1] += 0x08;
if(fuaNv)
cdb[1] += 0x02;
if(relAddr)
cdb[1] += 0x01;
cdb[2] = (uint8_t)((lba & 0xFF000000) >> 24);
cdb[3] = (uint8_t)((lba & 0xFF0000) >> 16);
cdb[4] = (uint8_t)((lba & 0xFF00) >> 8);
cdb[5] = (uint8_t)(lba & 0xFF);
cdb[6] = (uint8_t)(groupNumber & 0x1F);
cdb[7] = (uint8_t)((transferLength & 0xFF00) >> 8);
cdb[8] = (uint8_t)(transferLength & 0xFF);
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buflen, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int Read12(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint8_t rdprotect, int dpo, int fua, int fuaNv,
int relAddr, uint32_t lba, uint32_t blockSize, uint8_t groupNumber, uint32_t transferLength, int streaming)
{
unsigned char cmd_len = 12;
unsigned int buflen = transferLength * blockSize;
*buffer = malloc(buflen);
memset(*buffer, 0, buflen);
unsigned char cdb[] = {SCSI_READ_12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
cdb[1] = (uint8_t)((rdprotect & 0x07) << 5);
if(dpo)
cdb[1] += 0x10;
if(fua)
cdb[1] += 0x08;
if(fuaNv)
cdb[1] += 0x02;
if(relAddr)
cdb[1] += 0x01;
cdb[2] = (uint8_t)((lba & 0xFF000000) >> 24);
cdb[3] = (uint8_t)((lba & 0xFF0000) >> 16);
cdb[4] = (uint8_t)((lba & 0xFF00) >> 8);
cdb[5] = (uint8_t)(lba & 0xFF);
cdb[6] = (uint8_t)((transferLength & 0xFF000000) >> 24);
cdb[7] = (uint8_t)((transferLength & 0xFF0000) >> 16);
cdb[8] = (uint8_t)((transferLength & 0xFF00) >> 8);
cdb[9] = (uint8_t)(transferLength & 0xFF);
cdb[10] = (uint8_t)(groupNumber & 0x1F);
if(streaming)
cdb[10] += 0x80;
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buflen, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int Read16(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint8_t rdprotect, int dpo, int fua, int fuaNv,
uint64_t lba, uint32_t blockSize, uint8_t groupNumber, uint32_t transferLength, int streaming)
{
unsigned char cmd_len = 16;
unsigned int buflen = transferLength * blockSize;
*buffer = malloc(buflen);
memset(*buffer, 0, buflen);
unsigned char cdb[] = {SCSI_READ_16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
cdb[1] = (uint8_t)((rdprotect & 0x07) << 5);
if(dpo)
cdb[1] += 0x10;
if(fua)
cdb[1] += 0x08;
if(fuaNv)
cdb[1] += 0x02;
cdb[2] = (uint8_t)((lba & 0xFF00000000000000ULL) >> 56);
cdb[3] = (uint8_t)((lba & 0xFF000000000000ULL) >> 48);
cdb[4] = (uint8_t)((lba & 0xFF0000000000ULL) >> 40);
cdb[5] = (uint8_t)((lba & 0xFF00000000ULL) >> 32);
cdb[6] = (uint8_t)((lba & 0xFF000000ULL) >> 24);
cdb[7] = (uint8_t)((lba & 0xFF0000ULL) >> 16);
cdb[8] = (uint8_t)((lba & 0xFF00ULL) >> 8);
cdb[9] = (uint8_t)(lba & 0xFFULL);
cdb[10] = (uint8_t)((transferLength & 0xFF000000) >> 24);
cdb[11] = (uint8_t)((transferLength & 0xFF0000) >> 16);
cdb[12] = (uint8_t)((transferLength & 0xFF00) >> 8);
cdb[13] = (uint8_t)(transferLength & 0xFF);
cdb[14] = (uint8_t)(groupNumber & 0x1F);
if(streaming)
cdb[14] += 0x80;
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buflen, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int ReadLong10(int fd, unsigned char **buffer, unsigned char **senseBuffer, int correct, int relAddr, uint32_t lba,
uint16_t transferBytes)
{
unsigned char cmd_len = 10;
*buffer = malloc(transferBytes);
memset(*buffer, 0, transferBytes);
unsigned char cdb[] = {SCSI_READ_LONG, 0, 0, 0, 0, 0, 0, 0, 0, 0};
if(correct)
cdb[1] += 0x02;
if(relAddr)
cdb[1] += 0x01;
cdb[2] = (uint8_t)((lba & 0xFF000000) >> 24);
cdb[3] = (uint8_t)((lba & 0xFF0000) >> 16);
cdb[4] = (uint8_t)((lba & 0xFF00) >> 8);
cdb[5] = (uint8_t)(lba & 0xFF);
cdb[7] = (uint8_t)((transferBytes & 0xFF00) >> 8);
cdb[8] = (uint8_t)(transferBytes & 0xFF);
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, transferBytes, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int ReadLong16(int fd, unsigned char **buffer, unsigned char **senseBuffer, int correct, uint64_t lba,
uint32_t transferBytes)
{
unsigned char cmd_len = 16;
*buffer = malloc(transferBytes);
memset(*buffer, 0, transferBytes);
unsigned char cdb[] = {SCSI_SERVICE_ACTION_IN, SCSI_READ_LONG_16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
cdb[2] = (uint8_t)((lba & 0xFF00000000000000ULL) >> 56);
cdb[3] = (uint8_t)((lba & 0xFF000000000000ULL) >> 48);
cdb[4] = (uint8_t)((lba & 0xFF0000000000ULL) >> 40);
cdb[5] = (uint8_t)((lba & 0xFF00000000ULL) >> 32);
cdb[6] = (uint8_t)((lba & 0xFF000000ULL) >> 24);
cdb[7] = (uint8_t)((lba & 0xFF0000ULL) >> 16);
cdb[8] = (uint8_t)((lba & 0xFF00ULL) >> 8);
cdb[9] = (uint8_t)(lba & 0xFFULL);
cdb[12] = (uint8_t)((transferBytes & 0xFF00) >> 8);
cdb[13] = (uint8_t)(transferBytes & 0xFF);
if(correct)
cdb[14] += 0x01;
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, transferBytes, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int Seek6(int fd, unsigned char **senseBuffer, uint32_t lba)
{
unsigned char cmd_len = 6;
char cdb[] = {SCSI_SEEK, 0, 0, 0, 0, 0};
unsigned char *buffer = malloc(0);
cdb[1] = (uint8_t)((lba & 0x1F0000) >> 16);
cdb[2] = (uint8_t)((lba & 0xFF00) >> 8);
cdb[3] = (uint8_t)(lba & 0xFF);
int error = SendScsiCommand(fd, &cdb, cmd_len, buffer, 0, senseBuffer, SG_DXFER_NONE);
return error;
}
int Seek10(int fd, unsigned char **senseBuffer, uint32_t lba)
{
unsigned char cmd_len = 10;
char cdb[] = {SCSI_SEEK_10, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char *buffer = malloc(0);
cdb[2] = (uint8_t)((lba & 0xFF000000) >> 24);
cdb[3] = (uint8_t)((lba & 0xFF0000) >> 16);
cdb[4] = (uint8_t)((lba & 0xFF00) >> 8);
cdb[5] = (uint8_t)(lba & 0xFF);
int error = SendScsiCommand(fd, &cdb, cmd_len, buffer, 0, senseBuffer, SG_DXFER_NONE);
return error;
}
int TestUnitReady(int fd, unsigned char **senseBuffer)
{
unsigned char cmd_len = 6;
char cdb[] = {SCSI_TEST_UNIT_READY, 0, 0, 0, 0, 0};
unsigned char *buffer = malloc(0);
int error = SendScsiCommand(fd, &cdb, cmd_len, buffer, 0, senseBuffer, SG_DXFER_NONE);
return error;
}
int GetConfiguration(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint16_t startingFeatureNumber,
uint8_t RT)
{
unsigned char cmd_len = 10;
uint16_t buffer_len = 8;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
char cdb[] = {MMC_GET_CONFIGURATION, 0, 0, 0, 0, 0, 0, 0, 0, 0};
cdb[1] = (uint8_t)(RT & 0x03);
cdb[2] = (uint8_t)((startingFeatureNumber & 0xFF00) >> 8);
cdb[3] = (uint8_t)(startingFeatureNumber & 0xFF);
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 = (uint16_t)(*(*buffer + 2) << 8) + *(*buffer + 3) + 2;
cdb[7] = (uint8_t)((buffer_len & 0xFF00) >> 8);
cdb[8] = (uint8_t)(buffer_len & 0xFF);
free(*buffer);
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int ReadTocPmaAtip(int fd, unsigned char **buffer, unsigned char **senseBuffer, int MSF, uint8_t format,
uint8_t trackSessionNumber)
{
unsigned char cmd_len = 10;
uint16_t buffer_len = 1024;
char cdb[] = {MMC_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 0, 0};
if((format & 0xF) == 5)
buffer_len = 32768;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
if(MSF)
cdb[1] = 0x02;
cdb[2] = (uint8_t)(format & 0x0F);
cdb[6] = trackSessionNumber;
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 = (uint16_t)(*(*buffer + 0) << 8) + *(*buffer + 1) + 2;
cdb[7] = (uint8_t)((buffer_len & 0xFF00) >> 8);
cdb[8] = (uint8_t)(buffer_len & 0xFF);
free(*buffer);
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int ReadDiscStructure(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint8_t mediaType, uint32_t address,
uint8_t layerNumber, uint8_t format, uint8_t AGID)
{
unsigned char cmd_len = 12;
uint16_t buffer_len = 8;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
char cdb[] = {MMC_READ_DISC_STRUCTURE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
cdb[1] = (uint8_t)((uint8_t)mediaType & 0x0F);
cdb[2] = (uint8_t)((address & 0xFF000000) >> 24);
cdb[3] = (uint8_t)((address & 0xFF0000) >> 16);
cdb[4] = (uint8_t)((address & 0xFF00) >> 8);
cdb[5] = (uint8_t)(address & 0xFF);
cdb[6] = layerNumber;
cdb[7] = (uint8_t)format;
cdb[8] = (uint8_t)((buffer_len & 0xFF00) >> 8);
cdb[9] = (uint8_t)(buffer_len & 0xFF);
cdb[10] = (uint8_t)((AGID & 0x03) << 6);
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
if(error)
return error;
buffer_len = (uint16_t)(*(*buffer + 0) << 8) + *(*buffer + 1) + 2;
cdb[8] = (uint8_t)((buffer_len & 0xFF00) >> 8);
cdb[9] = (uint8_t)(buffer_len & 0xFF);
free(*buffer);
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int ReadCd(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t blockSize,
uint32_t transferLength, uint8_t expectedSectorType, int DAP, int relAddr, int sync, uint8_t headerCodes,
int userData, int edcEcc, uint8_t C2Error, uint8_t subchannel)
{
unsigned char cmd_len = 12;
uint32_t buffer_len = transferLength * blockSize;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
char cdb[] = {MMC_READ_CD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
cdb[1] = (uint8_t)((uint8_t)expectedSectorType << 2);
if(DAP)
cdb[1] += 0x02;
if(relAddr)
cdb[1] += 0x01;
cdb[2] = (uint8_t)((lba & 0xFF000000) >> 24);
cdb[3] = (uint8_t)((lba & 0xFF0000) >> 16);
cdb[4] = (uint8_t)((lba & 0xFF00) >> 8);
cdb[5] = (uint8_t)(lba & 0xFF);
cdb[6] = (uint8_t)((transferLength & 0xFF0000) >> 16);
cdb[7] = (uint8_t)((transferLength & 0xFF00) >> 8);
cdb[8] = (uint8_t)(transferLength & 0xFF);
cdb[9] = (uint8_t)((uint8_t)C2Error << 1);
cdb[9] += (uint8_t)((uint8_t)headerCodes << 5);
if(sync)
cdb[9] += 0x80;
if(userData)
cdb[9] += 0x10;
if(edcEcc)
cdb[9] += 0x08;
cdb[10] = (uint8_t)subchannel;
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int ReadCdMsf(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t startMsf, uint32_t endMsf,
uint32_t blockSize, uint8_t expectedSectorType, int DAP, int sync, uint8_t headerCodes, int userData,
int edcEcc, uint8_t C2Error, uint8_t subchannel)
{
unsigned char cmd_len = 12;
char cdb[] = {MMC_READ_CD_MSF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
cdb[1] = (uint8_t)((uint8_t)expectedSectorType << 2);
if(DAP)
cdb[1] += 0x02;
cdb[3] = (uint8_t)((startMsf & 0xFF0000) >> 16);
cdb[4] = (uint8_t)((startMsf & 0xFF00) >> 8);
cdb[5] = (uint8_t)(startMsf & 0xFF);
cdb[6] = (uint8_t)((endMsf & 0xFF0000) >> 16);
cdb[7] = (uint8_t)((endMsf & 0xFF00) >> 8);
cdb[8] = (uint8_t)(endMsf & 0xFF);
cdb[9] = (uint8_t)((uint8_t)C2Error << 1);
cdb[9] += (uint8_t)((uint8_t)headerCodes << 5);
if(sync)
cdb[9] += 0x80;
if(userData)
cdb[9] += 0x10;
if(edcEcc)
cdb[9] += 0x08;
cdb[10] = (uint8_t)subchannel;
uint32_t transferLength = (uint32_t)((cdb[6] - cdb[3]) * 60 * 75 + (cdb[7] - cdb[4]) * 75 + (cdb[8] - cdb[5]));
uint32_t buffer_len = transferLength * blockSize;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int PlextorReadCdDa(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t blockSize,
uint32_t transferLength, uint8_t subchannel)
{
unsigned char cmd_len = 12;
uint32_t buffer_len = transferLength * blockSize;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
char cdb[] = {PIONEER_READ_CDDA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
cdb[2] = (uint8_t)((lba & 0xFF000000) >> 24);
cdb[3] = (uint8_t)((lba & 0xFF0000) >> 16);
cdb[4] = (uint8_t)((lba & 0xFF00) >> 8);
cdb[5] = (uint8_t)(lba & 0xFF);
cdb[6] = (uint8_t)((transferLength & 0xFF000000) >> 24);
cdb[7] = (uint8_t)((transferLength & 0xFF0000) >> 16);
cdb[8] = (uint8_t)((transferLength & 0xFF00) >> 8);
cdb[9] = (uint8_t)(transferLength & 0xFF);
cdb[10] = (uint8_t)subchannel;
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int
PlextorReadRawDvd(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t transferLength)
{
unsigned char cmd_len = 10;
uint32_t buffer_len = transferLength * 2064;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
char cdb[] = {SCSI_READ_BUFFER, 0, 0, 0, 0, 0, 0, 0, 0, 0};
cdb[1] = 0x02;
cdb[3] = (uint8_t)((lba & 0xFF0000) >> 16);
cdb[4] = (uint8_t)((lba & 0xFF00) >> 8);
cdb[5] = (uint8_t)(lba & 0xFF);
cdb[3] = (uint8_t)((buffer_len & 0xFF0000) >> 16);
cdb[4] = (uint8_t)((buffer_len & 0xFF00) >> 8);
cdb[5] = (uint8_t)(buffer_len & 0xFF);
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int PioneerReadCdDa(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t blockSize,
uint32_t transferLength, uint8_t subchannel)
{
unsigned char cmd_len = 12;
uint32_t buffer_len = transferLength * blockSize;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
char cdb[] = {PIONEER_READ_CDDA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
cdb[2] = (uint8_t)((lba & 0xFF000000) >> 24);
cdb[3] = (uint8_t)((lba & 0xFF0000) >> 16);
cdb[4] = (uint8_t)((lba & 0xFF00) >> 8);
cdb[5] = (uint8_t)(lba & 0xFF);
cdb[7] = (uint8_t)((transferLength & 0xFF0000) >> 16);
cdb[8] = (uint8_t)((transferLength & 0xFF00) >> 8);
cdb[9] = (uint8_t)(transferLength & 0xFF);
cdb[10] = (uint8_t)subchannel;
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int PioneerReadCdDaMsf(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t startMsf, uint32_t endMsf,
uint32_t blockSize, uint8_t subchannel)
{
unsigned char cmd_len = 12;
char cdb[] = {PIONEER_READ_CDDA_MSF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
cdb[3] = (uint8_t)((startMsf & 0xFF0000) >> 16);
cdb[4] = (uint8_t)((startMsf & 0xFF00) >> 8);
cdb[5] = (uint8_t)(startMsf & 0xFF);
cdb[7] = (uint8_t)((endMsf & 0xFF0000) >> 16);
cdb[8] = (uint8_t)((endMsf & 0xFF00) >> 8);
cdb[9] = (uint8_t)(endMsf & 0xFF);
cdb[10] = (uint8_t)subchannel;
uint32_t transferLength = (uint)((cdb[7] - cdb[3]) * 60 * 75 + (cdb[8] - cdb[4]) * 75 + (cdb[9] - cdb[5]));
uint32_t buffer_len = transferLength * blockSize;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int NecReadCdDa(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t transferLength)
{
unsigned char cmd_len = 12;
uint32_t buffer_len = transferLength * 2352;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
char cdb[] = {NEC_READ_CDDA, 0, 0, 0, 0, 0, 0, 0, 0, 0};
cdb[2] = (uint8_t)((lba & 0xFF000000) >> 24);
cdb[3] = (uint8_t)((lba & 0xFF0000) >> 16);
cdb[4] = (uint8_t)((lba & 0xFF00) >> 8);
cdb[5] = (uint8_t)(lba & 0xFF);
cdb[7] = (uint8_t)((transferLength & 0xFF00) >> 8);
cdb[8] = (uint8_t)(transferLength & 0xFF);
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
return error;
}
int HlDtStReadRawDvd(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t transferLength)
{
unsigned char cmd_len = 12;
uint32_t buffer_len = transferLength * 2064;
*buffer = malloc(buffer_len);
memset(*buffer, 0, buffer_len);
char cdb[] = {HLDTST_VENDOR, 0x48, 0x49, 0x54, 0x01, 0, 0, 0, 0, 0, 0, 0};
cdb[6] = (uint8_t)((lba & 0xFF000000) >> 24);
cdb[7] = (uint8_t)((lba & 0xFF0000) >> 16);
cdb[8] = (uint8_t)((lba & 0xFF00) >> 8);
cdb[9] = (uint8_t)(lba & 0xFF);
cdb[10] = (uint8_t)((buffer_len & 0xFF00) >> 8);
cdb[11] = (uint8_t)(buffer_len & 0xFF);
int error = SendScsiCommand(fd, &cdb, cmd_len, *buffer, buffer_len, senseBuffer, SG_DXFER_FROM_DEV);
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

@@ -1,623 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : scsi.h
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Contains SCSI definitions.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#ifndef DISCIMAGECHEF_DEVICE_REPORT_SCSI_H
#define DISCIMAGECHEF_DEVICE_REPORT_SCSI_H
int SendScsiCommand(int fd, void *cdb, unsigned char cdb_len, unsigned char *buffer, unsigned int buffer_len,
unsigned char **senseBuffer, int direction);
int Inquiry(int fd, unsigned char **buffer, unsigned char **senseBuffer);
int PreventMediumRemoval(int fd, unsigned char **senseBuffer);
int AllowMediumRemoval(int fd, unsigned char **senseBuffer);
int PreventAllowMediumRemoval(int fd, unsigned char **senseBuffer, int persistent, int prevent);
int LoadTray(int fd, unsigned char **senseBuffer);
int EjectTray(int fd, unsigned char **senseBuffer);
int StartUnit(int fd, unsigned char **senseBuffer);
int StopUnit(int fd, unsigned char **senseBuffer);
int StartStopUnit(int fd, unsigned char **senseBuffer, int immediate, uint8_t formatLayer, uint8_t powerConditions,
int changeFormatLayer, int loadEject, int start);
int SpcPreventMediumRemoval(int fd, unsigned char **senseBuffer);
int SpcAllowMediumRemoval(int fd, unsigned char **senseBuffer);
int SpcPreventAllowMediumRemoval(int fd, unsigned char **senseBuffer, uint8_t preventMode);
int Load(int fd, unsigned char **senseBuffer);
int Unload(int fd, unsigned char **senseBuffer);
int LoadUnload(int fd, unsigned char **senseBuffer, int immediate, int load, int retense, int endOfTape, int hold);
int
ModeSense6(int fd, unsigned char **buffer, unsigned char **senseBuffer, int DBD, uint8_t pageControl, uint8_t pageCode,
uint8_t subPageCode);
int ModeSense10(int fd, unsigned char **buffer, unsigned char **senseBuffer, int LLBAA, int DBD, uint8_t pageContorl,
uint8_t pageCode, uint8_t subPageCode);
int ReadCapacity(int fd, unsigned char **buffer, unsigned char **senseBuffer, int RelAddr, uint32_t address, int PMI);
int ReadCapacity16(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint64_t address, int PMI);
int Read6(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t blockSize,
uint8_t transferLength);
int Read10(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint8_t rdprotect, int dpo, int fua, int fuaNv,
int relAddr, uint32_t lba, uint32_t blockSize, uint8_t groupNumber, uint16_t transferLength);
int Read12(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint8_t rdprotect, int dpo, int fua, int fuaNv,
int relAddr, uint32_t lba, uint32_t blockSize, uint8_t groupNumber, uint32_t transferLength, int streaming);
int Read16(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint8_t rdprotect, int dpo, int fua, int fuaNv,
uint64_t lba, uint32_t blockSize, uint8_t groupNumber, uint32_t transferLength, int streaming);
int ReadLong10(int fd, unsigned char **buffer, unsigned char **senseBuffer, int correct, int relAddr, uint32_t lba,
uint16_t transferBytes);
int ReadLong16(int fd, unsigned char **buffer, unsigned char **senseBuffer, int correct, uint64_t lba,
uint32_t transferBytes);
int Seek6(int fd, unsigned char **senseBuffer, uint32_t lba);
int Seek10(int fd, unsigned char **senseBuffer, uint32_t lba);
int TestUnitReady(int fd, unsigned char **senseBuffer);
int GetConfiguration(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint16_t startingFeatureNumber,
uint8_t RT);
int ReadTocPmaAtip(int fd, unsigned char **buffer, unsigned char **senseBuffer, int MSF, uint8_t format,
uint8_t trackSessionNumber);
int ReadDiscStructure(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint8_t mediaType, uint32_t address,
uint8_t layerNumber, uint8_t format, uint8_t AGID);
int ReadCd(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t blockSize,
uint32_t transferLength, uint8_t expectedSectorType, int DAP, int relAddr, int sync, uint8_t headerCodes,
int userData, int edcEcc, uint8_t C2Error, uint8_t subchannel);
int ReadCdMsf(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t startMsf, uint32_t endMsf,
uint32_t blockSize, uint8_t expectedSectorType, int DAP, int sync, uint8_t headerCodes, int userData,
int edcEcc, uint8_t C2Error, uint8_t subchannel);
int PlextorReadCdDa(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t blockSize,
uint32_t transferLength, uint8_t subchannel);
int
PlextorReadRawDvd(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t transferLength);
int PioneerReadCdDa(int fd, unsigned char **buffer, unsigned char **senseBuffer, uint32_t lba, uint32_t blockSize,
uint32_t transferLength, uint8_t subchannel);
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,
SCSI_START_STOP_UNIT = 0x1B,
SCSI_LOAD_UNLOAD = SCSI_START_STOP_UNIT,
SCSI_MODE_SENSE = 0x1A,
SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL = 0x1E,
SCSI_READ_CAPACITY = 0x25,
SCSI_READ_10 = 0x28,
SCSI_READ_LONG = 0x3E,
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,
NEC_READ_CDDA = 0xD4,
PIONEER_READ_CDDA = 0xD8,
PIONEER_READ_CDDA_MSF = 0xD9,
HLDTST_VENDOR = 0xE7,
} ScsiCommands;
typedef enum
{
MODE_PAGE_CURRENT = 0x00, MODE_PAGE_CHANGEABLE = 0x40, MODE_PAGE_DEFAULT = 0x80, MODE_PAGE_SAVED = 0xC0
} ScsiModeSensePageControl;
typedef enum
{
SCSI_READ_CAPACITY_16 = 0x10, SCSI_READ_LONG_16 = 0x11,
} ScsiServiceActionIn;
typedef enum
{
DISC_STRUCTURE_DVD = 0x00, DISC_STRUCTURE_BD = 0x01,
} MmcDiscStructureMediaType;
// TODO: Stylize this
typedef enum
{
// Generic Format Codes
/// <summary>
/// AACS Volume Identifier
/// </summary>
DISC_STRUCTURE_AACSVolId = 0x80, /// <summary>
/// AACS Pre-recorded Media Serial Number
/// </summary>
DISC_STRUCTURE_AACSMediaSerial = 0x81, /// <summary>
/// AACS Media Identifier
/// </summary>
DISC_STRUCTURE_AACSMediaId = 0x82, /// <summary>
/// AACS Lead-in Media Key Block
/// </summary>
DISC_STRUCTURE_AACSMKB = 0x83, /// <summary>
/// AACS Data Keys
/// </summary>
DISC_STRUCTURE_AACSDataKeys = 0x84, /// <summary>
/// AACS LBA extents
/// </summary>
DISC_STRUCTURE_AACSLBAExtents = 0x85, /// <summary>
/// CPRM Media Key Block specified by AACS
/// </summary>
DISC_STRUCTURE_AACSMKBCPRM = 0x86, /// <summary>
/// Recognized format layers
/// </summary>
DISC_STRUCTURE_RecognizedFormatLayers = 0x90, /// <summary>
/// Write protection status
/// </summary>
DISC_STRUCTURE_WriteProtectionStatus = 0xC0, /// <summary>
/// READ/SEND DISC STRUCTURE capability list
/// </summary>
DISC_STRUCTURE_CapabilityList = 0xFF,
// DVD Disc Structures
/// <summary>
/// DVD Lead-in Physical Information
/// </summary>
DISC_STRUCTURE_PhysicalInformation = 0x00, /// <summary>
/// DVD Lead-in Copyright Information
/// </summary>
DISC_STRUCTURE_CopyrightInformation = 0x01, /// <summary>
/// CSS/CPPM Disc key
/// </summary>
DISC_STRUCTURE_DiscKey = 0x02, /// <summary>
/// DVD Burst Cutting Area
/// </summary>
DISC_STRUCTURE_BurstCuttingArea = 0x03, /// <summary>
/// DVD Lead-in Disc Manufacturing Information
/// </summary>
DISC_STRUCTURE_DiscManufacturingInformation = 0x04, /// <summary>
/// DVD Copyright Information from specified sector
/// </summary>
DISC_STRUCTURE_SectorCopyrightInformation = 0x05, /// <summary>
/// CSS/CPPM Media Identifier
/// </summary>
DISC_STRUCTURE_MediaIdentifier = 0x06, /// <summary>
/// CSS/CPPM Media Key Block
/// </summary>
DISC_STRUCTURE_MediaKeyBlock = 0x07, /// <summary>
/// DDS from DVD-RAM
/// </summary>
DISC_STRUCTURE_DVDRAM_DDS = 0x08, /// <summary>
/// DVD-RAM Medium Status
/// </summary>
DISC_STRUCTURE_DVDRAM_MediumStatus = 0x09, /// <summary>
/// DVD-RAM Spare Area Information
/// </summary>
DISC_STRUCTURE_DVDRAM_SpareAreaInformation = 0x0A, /// <summary>
/// DVD-RAM Recording Type Information
/// </summary>
DISC_STRUCTURE_DVDRAM_RecordingType = 0x0B, /// <summary>
/// DVD-R/-RW RMD in last Border-out
/// </summary>
DISC_STRUCTURE_LastBorderOutRMD = 0x0C, /// <summary>
/// Specified RMD from last recorded Border-out
/// </summary>
DISC_STRUCTURE_SpecifiedRMD = 0x0D, /// <summary>
/// DVD-R/-RW Lead-in pre-recorded information
/// </summary>
DISC_STRUCTURE_PreRecordedInfo = 0x0E, /// <summary>
/// DVD-R/-RW Media Identifier
/// </summary>
DISC_STRUCTURE_DVDR_MediaIdentifier = 0x0F, /// <summary>
/// DVD-R/-RW Physical Format Information
/// </summary>
DISC_STRUCTURE_DVDR_PhysicalInformation = 0x10, /// <summary>
/// ADIP
/// </summary>
DISC_STRUCTURE_ADIP = 0x11, /// <summary>
/// HD DVD Lead-in Copyright Protection Information
/// </summary>
DISC_STRUCTURE_HDDVD_CopyrightInformation = 0x12, /// <summary>
/// AACS Lead-in Copyright Data Section
/// </summary>
DISC_STRUCTURE_DVD_AACS = 0x15, /// <summary>
/// HD DVD-R Medium Status
/// </summary>
DISC_STRUCTURE_HDDVDR_MediumStatus = 0x19, /// <summary>
/// HD DVD-R Last recorded RMD in the latest RMZ
/// </summary>
DISC_STRUCTURE_HDDVDR_LastRMD = 0x1A, /// <summary>
/// DVD+/-R DL and DVD-Download DL layer capacity
/// </summary>
DISC_STRUCTURE_DVDR_LayerCapacity = 0x20, /// <summary>
/// DVD-R DL Middle Zone start address
/// </summary>
DISC_STRUCTURE_MiddleZoneStart = 0x21, /// <summary>
/// DVD-R DL Jump Interval Size
/// </summary>
DISC_STRUCTURE_JumpIntervalSize = 0x22, /// <summary>
/// DVD-R DL Start LBA of the manual layer jump
/// </summary>
DISC_STRUCTURE_ManualLayerJumpStartLBA = 0x23, /// <summary>
/// DVD-R DL Remapping information of the specified Anchor Point
/// </summary>
DISC_STRUCTURE_RemapAnchorPoint = 0x24, /// <summary>
/// Disc Control Block
/// </summary>
DISC_STRUCTURE_DCB = 0x30,
// BD Disc Structures
/// <summary>
/// Blu-ray Disc Information
/// </summary>
DISC_STRUCTURE_DiscInformation = 0x00, /// <summary>
/// Blu-ray Burst Cutting Area
/// </summary>
DISC_STRUCTURE_BD_BurstCuttingArea = 0x03, /// <summary>
/// Blu-ray DDS
/// </summary>
DISC_STRUCTURE_BD_DDS = 0x08, /// <summary>
/// Blu-ray Cartridge Status
/// </summary>
DISC_STRUCTURE_CartridgeStatus = 0x09, /// <summary>
/// Blu-ray Spare Area Information
/// </summary>
DISC_STRUCTURE_BD_SpareAreaInformation = 0x0A, /// <summary>
/// Unmodified DFL
/// </summary>
DISC_STRUCTURE_RawDFL = 0x12, /// <summary>
/// Physical Access Control
/// </summary>
DISC_STRUCTURE_PAC = 0x30
} MmcDiscStructureFormat;
typedef enum
{
MMC_SECTOR_ALL = 0,
MMC_SECTOR_CDDA = 1,
MMC_SECTOR_MODE1 = 2,
MMC_SECTOR_MODE2 = 3,
MMC_SECTOR_MODE2F1 = 4,
MMC_SECTOR_MODE2F2 = 5
} MmcSectorTypes;
typedef enum
{
MMC_HEADER_NONE = 0, MMC_HEADER_ONLY = 1, MMC_SUBHEADER_ONLY = 2, MMC_HEADER_ALL = 3
} MmcHeaderCodes;
typedef enum
{
MMC_ERROR_NONE = 0, MMC_ERROR_C2 = 1, MMC_ERROR_C2_AND_BLOCK = 2
} MmcErrorField;
typedef enum
{
MMC_SUBCHANNEL_NONE = 0, MMC_SUBCHANNEL_RAW = 1, MMC_SUBCHANNEL_Q16 = 2, MMC_SUBCHANNEL_RW = 4
} MmcSubchannel;
typedef enum
{
PIONEER_SUBCHANNEL_NONE = 0, PIONEER_SUBCHANNEL_Q16 = 1, PIONEER_SUBCHANNEL_ALL = 2, PIONEER_SUBCHANNEL_ONLY = 3
} PioneerSubchannel;
typedef enum
{
PLEXTOR_SUBCHANNEL_NONE = 0,
PLEXTOR_SUBCHANNEL_Q16 = 1,
PLEXTOR_SUBCHANNEL_PACK = 2,
PLEXTOR_SUBCHANNEL_ALL = 3,
PLEXTOR_SUBCHANNEL_RAW_C2 = 8
} PlextorSubchannel;
// SCSI INQUIRY command response
#pragma pack(push, 1)
typedef struct
{
/// <summary>
/// Peripheral device type
/// Byte 0, bits 4 to 0
/// </summary>
uint8_t PeripheralDeviceType : 5;
/// <summary>
/// Peripheral qualifier
/// Byte 0, bits 7 to 5
/// </summary>
uint8_t PeripheralQualifier : 3;
/// <summary>
/// SCSI-1 vendor-specific qualification codes
/// Byte 1, bits 6 to 0
/// </summary>
uint8_t DeviceTypeModifier : 7;
/// <summary>
/// Removable device
/// Byte 1, bit 7
/// </summary>
uint8_t RMB : 1;
/// <summary>
/// ANSI SCSI Standard Version
/// Byte 2, bits 2 to 0, mask = 0x07
/// </summary>
uint8_t ANSIVersion : 3;
/// <summary>
/// ECMA SCSI Standard Version
/// Byte 2, bits 5 to 3, mask = 0x38, >> 3
/// </summary>
uint8_t ECMAVersion : 3;
/// <summary>
/// ISO/IEC SCSI Standard Version
/// Byte 2, bits 7 to 6, mask = 0xC0, >> 6
/// </summary>
uint8_t ISOVersion : 2;
/// <summary>
/// Responde data format
/// Byte 3, bit 3 to 0
/// </summary>
uint8_t ResponseDataFormat : 4;
/// <summary>
/// Supports LUN hierarchical addressing
/// Byte 3, bit 4
/// </summary>
uint8_t HiSup : 1;
/// <summary>
/// Supports setting Normal ACA
/// Byte 3, bit 5
/// </summary>
uint8_t NormACA : 1;
/// <summary>
/// Device supports TERMINATE TASK command
/// Byte 3, bit 6
/// </summary>
uint8_t TrmTsk : 1;
/// <summary>
/// Asynchronous Event Reporting Capability supported
/// Byte 3, bit 7
/// </summary>
uint8_t AERC : 1;
/// <summary>
/// Lenght of total INQUIRY response minus 4
/// Byte 4
/// </summary>
uint8_t AdditionalLength;
/// <summary>
/// Supports protection information
/// Byte 5, bit 0
/// </summary>
uint8_t Protect : 1;
/// <summary>
/// Reserved
/// Byte 5, bits 2 to 1
/// </summary>
uint8_t Reserved2 : 2;
/// <summary>
/// Supports third-party copy commands
/// Byte 5, bit 3
/// </summary>
uint8_t ThreePC : 1;
/// <summary>
/// Supports asymetrical logical unit access
/// Byte 5, bits 5 to 4
/// </summary>
uint8_t TPGS : 2;
/// <summary>
/// Device contains an Access Control Coordinator
/// Byte 5, bit 6
/// </summary>
uint8_t ACC : 1;
/// <summary>
/// Device contains an embedded storage array controller
/// Byte 5, bit 7
/// </summary>
uint8_t SCCS : 1;
/// <summary>
/// Supports 16-bit wide SCSI addresses
/// Byte 6, bit 0
/// </summary>
uint8_t Addr16 : 1;
/// <summary>
/// Supports 32-bit wide SCSI addresses
/// Byte 6, bit 1
/// </summary>
uint8_t Addr32 : 1;
/// <summary>
/// Device supports request and acknowledge handshakes
/// Byte 6, bit 2
/// </summary>
uint8_t ACKREQQ : 1;
/// <summary>
/// Device contains or is attached to a medium changer
/// Byte 6, bit 3
/// </summary>
uint8_t MChngr : 1;
/// <summary>
/// Multi-port device
/// Byte 6, bit 4
/// </summary>
uint8_t MultiP : 1;
/// <summary>
/// Vendor-specific
/// Byte 6, bit 5
/// </summary>
uint8_t VS1 : 1;
/// <summary>
/// Device contains an embedded enclosure services component
/// Byte 6, bit 6
/// </summary>
uint8_t EncServ : 1;
/// <summary>
/// Supports basic queueing
/// Byte 6, bit 7
/// </summary>
uint8_t BQue : 1;
/// <summary>
/// Indicates that the devices responds to RESET with soft reset
/// Byte 7, bit 0
/// </summary>
uint8_t SftRe : 1;
/// <summary>
/// Supports TCQ queue
/// Byte 7, bit 1
/// </summary>
uint8_t CmdQue : 1;
/// <summary>
/// Supports CONTINUE TASK and TARGET TRANSFER DISABLE commands
/// Byte 7, bit 2
/// </summary>
uint8_t TranDis : 1;
/// <summary>
/// Supports linked commands
/// Byte 7, bit 3
/// </summary>
uint8_t Linked : 1;
/// <summary>
/// Supports synchronous data transfer
/// Byte 7, bit 4
/// </summary>
uint8_t Sync : 1;
/// <summary>
/// Supports 16-bit wide data transfers
/// Byte 7, bit 5
/// </summary>
uint8_t WBus16 : 1;
/// <summary>
/// Supports 32-bit wide data transfers
/// Byte 7, bit 6
/// </summary>
uint8_t WBus32 : 1;
/// <summary>
/// Device supports relative addressing
/// Byte 7, bit 7
/// </summary>
uint8_t RelAddr : 1;
/// <summary>
/// Vendor identification
/// Bytes 8 to 15
/// </summary>
uint8_t VendorIdentification[8];
/// <summary>
/// Product identification
/// Bytes 16 to 31
/// </summary>
uint8_t ProductIdentification[16];
/// <summary>
/// Product revision level
/// Bytes 32 to 35
/// </summary>
uint8_t ProductRevisionLevel[4];
/// <summary>
/// Vendor-specific data
/// Bytes 36 to 55
/// </summary>
uint8_t VendorSpecific[20];
/// <summary>
/// Supports information unit transfers
/// Byte 56, bit 0
/// </summary>
uint8_t IUS : 1;
/// <summary>
/// Device supports Quick Arbitration and Selection
/// Byte 56, bit 1
/// </summary>
uint8_t QAS : 1;
/// <summary>
/// Supported SPI clocking
/// Byte 56, bits 3 to 2
/// </summary>
uint8_t Clocking : 2;
/// <summary>
/// Byte 56, bits 7 to 4
/// </summary>
uint8_t Reserved3 : 4;
/// <summary>
/// Reserved
/// Byte 57
/// </summary>
uint8_t Reserved4;
/// <summary>
/// Array of version descriptors
/// Bytes 58 to 73
/// </summary>
uint16_t VersionDescriptors[8];
/// <summary>
/// Reserved
/// Bytes 74 to 95
/// </summary>
uint8_t Reserved5[22];
/// <summary>
/// Reserved
/// Bytes 96 to end
/// </summary>
uint8_t VendorSpecific2;
} ScsiInquiry;
#pragma pack(pop)
#endif //DISCIMAGECHEF_DEVICE_REPORT_SCSI_H

View File

@@ -1,304 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : scsi_mode.c
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Contains decoders for SCSI MODE PAGEs.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#include <malloc.h>
#include <string.h>
#include <endian.h>
#include <stdint.h>
#include "scsi_mode.h"
ModeHeader *DecodeModeHeader10(unsigned char *modeResponse, uint8_t deviceType)
{
uint16_t blockDescLength = (uint16_t)((modeResponse[6] << 8) + modeResponse[7]);
int i;
ModeHeader *header = malloc(sizeof(ModeHeader));
memset(header, 0, sizeof(ModeHeader));
header->MediumType = modeResponse[2];
int longLBA = (modeResponse[4] & 0x01) == 0x01;
if(blockDescLength > 0)
{
if(longLBA)
{
header->descriptorsLength = blockDescLength / 16;
for(i = 0; i < header->descriptorsLength; i++)
{
header->BlockDescriptors[i].Density = 0x00;
header->BlockDescriptors[i].Blocks = be64toh((uint64_t)(*modeResponse + 0 + i * 16 + 8));
header->BlockDescriptors[i].BlockLength += (uint32_t)(modeResponse[15 + i * 16 + 8] << 24);
header->BlockDescriptors[i].BlockLength += (uint32_t)(modeResponse[14 + i * 16 + 8] << 16);
header->BlockDescriptors[i].BlockLength += (uint32_t)(modeResponse[13 + i * 16 + 8] << 8);
header->BlockDescriptors[i].BlockLength += modeResponse[12 + i * 16 + 8];
}
}
else
{
header->descriptorsLength = blockDescLength / 8;
for(i = 0; i < header->descriptorsLength; i++)
{
if(deviceType != 0x00)
{
header->BlockDescriptors[i].Density = modeResponse[0 + i * 8 + 8];
}
else
{
header->BlockDescriptors[i].Density = 0x00;
header->BlockDescriptors[i].Blocks += (uint64_t)(modeResponse[0 + i * 8 + 8] << 24);
}
header->BlockDescriptors[i].Blocks += (uint64_t)(modeResponse[1 + i * 8 + 8] << 16);
header->BlockDescriptors[i].Blocks += (uint64_t)(modeResponse[2 + i * 8 + 8] << 8);
header->BlockDescriptors[i].Blocks += modeResponse[3 + i * 8 + 8];
header->BlockDescriptors[i].BlockLength += (uint32_t)(modeResponse[5 + i * 8 + 8] << 16);
header->BlockDescriptors[i].BlockLength += (uint32_t)(modeResponse[6 + i * 8 + 8] << 8);
header->BlockDescriptors[i].BlockLength += modeResponse[7 + i * 8 + 8];
}
}
}
if(deviceType == 0x00 || deviceType == 0x05)
{
header->WriteProtected = ((modeResponse[3] & 0x80) == 0x80);
header->DPOFUA = ((modeResponse[3] & 0x10) == 0x10);
}
if(deviceType == 0x01)
{
header->WriteProtected = ((modeResponse[3] & 0x80) == 0x80);
header->Speed = (uint8_t)(modeResponse[3] & 0x0F);
header->BufferedMode = (uint8_t)((modeResponse[3] & 0x70) >> 4);
}
if(deviceType == 0x02)
header->BufferedMode = (uint8_t)((modeResponse[3] & 0x70) >> 4);
if(deviceType == 0x07)
{
header->WriteProtected = ((modeResponse[3] & 0x80) == 0x80);
header->EBC = ((modeResponse[3] & 0x01) == 0x01);
header->DPOFUA = ((modeResponse[3] & 0x10) == 0x10);
}
header->decoded = 1;
return header;
}
DecodedMode *DecodeMode10(unsigned char *modeResponse, uint8_t deviceType)
{
DecodedMode *decodedMode = malloc(sizeof(DecodedMode));
ModeHeader *hdrPtr = DecodeModeHeader10(modeResponse, deviceType);
memcpy(&(decodedMode->Header), hdrPtr, sizeof(ModeHeader));
free(hdrPtr);
if(!decodedMode->Header.decoded)
return decodedMode;
decodedMode->decoded = 1;
int longlba = (modeResponse[4] & 0x01) == 0x01;
int offset;
if(longlba)
offset = 8 + decodedMode->Header.descriptorsLength * 16;
else
offset = 8 + decodedMode->Header.descriptorsLength * 8;
int length = (modeResponse[0] << 8);
length += modeResponse[1];
length += 2;
while(offset < length)
{
int isSubpage = (modeResponse[offset] & 0x40) == 0x40;
uint8_t pageNo = (uint8_t)(modeResponse[offset] & 0x3F);
int subpage;
if(pageNo == 0)
{
decodedMode->pageSizes[0][0] = (size_t)(length - offset);
decodedMode->Pages[0][0] = malloc(decodedMode->pageSizes[0][0]);
memset(decodedMode->Pages[0][0], 0, decodedMode->pageSizes[0][0]);
memcpy(decodedMode->Pages[0][0], modeResponse + offset, decodedMode->pageSizes[0][0]);
offset += decodedMode->pageSizes[0][0];
}
else
{
if(isSubpage)
{
if(offset + 3 >= length)
break;
pageNo = (uint8_t)(modeResponse[offset] & 0x3F);
subpage = modeResponse[offset + 1];
decodedMode->pageSizes[pageNo][subpage] = (size_t)((modeResponse[offset + 2] << 8) +
modeResponse[offset + 3] + 4);
decodedMode->Pages[pageNo][subpage] = malloc(decodedMode->pageSizes[pageNo][subpage]);
memset(decodedMode->Pages[pageNo][subpage], 0, decodedMode->pageSizes[pageNo][subpage]);
memcpy(decodedMode->Pages[pageNo][subpage], modeResponse + offset,
decodedMode->pageSizes[pageNo][subpage]);
offset += decodedMode->pageSizes[pageNo][subpage];
}
else
{
if(offset + 1 >= length)
break;
pageNo = (uint8_t)(modeResponse[offset] & 0x3F);
decodedMode->pageSizes[pageNo][0] = (size_t)(modeResponse[offset + 1] + 2);
decodedMode->Pages[pageNo][0] = malloc(decodedMode->pageSizes[pageNo][0]);
memset(decodedMode->Pages[pageNo][0], 0, decodedMode->pageSizes[pageNo][0]);
memcpy(decodedMode->Pages[pageNo][0], modeResponse + offset, decodedMode->pageSizes[pageNo][0]);
offset += decodedMode->pageSizes[pageNo][0];
}
}
}
return decodedMode;
}
ModeHeader *DecodeModeHeader6(unsigned char *modeResponse, uint8_t deviceType)
{
int i;
ModeHeader *header = malloc(sizeof(ModeHeader));
memset(header, 0, sizeof(ModeHeader));
if(modeResponse[3])
{
header->descriptorsLength = modeResponse[3] / 8;
for(i = 0; i < header->descriptorsLength; i++)
{
header->BlockDescriptors[i].Density = modeResponse[0 + i * 8 + 4];
header->BlockDescriptors[i].Blocks += (uint64_t)(modeResponse[1 + i * 8 + 4] << 16);
header->BlockDescriptors[i].Blocks += (uint64_t)(modeResponse[2 + i * 8 + 4] << 8);
header->BlockDescriptors[i].Blocks += modeResponse[3 + i * 8 + 4];
header->BlockDescriptors[i].BlockLength += (uint32_t)(modeResponse[5 + i * 8 + 4] << 16);
header->BlockDescriptors[i].BlockLength += (uint32_t)(modeResponse[6 + i * 8 + 4] << 8);
header->BlockDescriptors[i].BlockLength += modeResponse[7 + i * 8 + 4];
}
}
if(deviceType == 0x00 || deviceType == 0x05)
{
header->WriteProtected = ((modeResponse[2] & 0x80) == 0x80);
header->DPOFUA = ((modeResponse[2] & 0x10) == 0x10);
}
if(deviceType == 0x01)
{
header->WriteProtected = ((modeResponse[2] & 0x80) == 0x80);
header->Speed = (uint8_t)(modeResponse[2] & 0x0F);
header->BufferedMode = (uint8_t)((modeResponse[2] & 0x70) >> 4);
}
if(deviceType == 0x02)
header->BufferedMode = (uint8_t)((modeResponse[2] & 0x70) >> 4);
if(deviceType == 0x07)
{
header->WriteProtected = ((modeResponse[2] & 0x80) == 0x80);
header->EBC = ((modeResponse[2] & 0x01) == 0x01);
header->DPOFUA = ((modeResponse[2] & 0x10) == 0x10);
}
header->decoded = 1;
return header;
}
DecodedMode *DecodeMode6(unsigned char *modeResponse, uint8_t deviceType)
{
DecodedMode *decodedMode = malloc(sizeof(DecodedMode));
ModeHeader *hdrPtr = DecodeModeHeader6(modeResponse, deviceType);
memcpy(&(decodedMode->Header), hdrPtr, sizeof(ModeHeader));
free(hdrPtr);
if(!decodedMode->Header.decoded)
return decodedMode;
decodedMode->decoded = 1;
int offset = 4 + decodedMode->Header.descriptorsLength * 8;
int length = modeResponse[0] + 1;
while(offset < length)
{
int isSubpage = (modeResponse[offset] & 0x40) == 0x40;
uint8_t pageNo = (uint8_t)(modeResponse[offset] & 0x3F);
int subpage;
if(pageNo == 0)
{
decodedMode->pageSizes[0][0] = (size_t)(length - offset);
decodedMode->Pages[0][0] = malloc(decodedMode->pageSizes[0][0]);
memset(decodedMode->Pages[0][0], 0, decodedMode->pageSizes[0][0]);
memcpy(decodedMode->Pages[0][0], modeResponse + offset, decodedMode->pageSizes[0][0]);
offset += decodedMode->pageSizes[0][0];
}
else
{
if(isSubpage)
{
if(offset + 3 >= length)
break;
pageNo = (uint8_t)(modeResponse[offset] & 0x3F);
subpage = modeResponse[offset + 1];
decodedMode->pageSizes[pageNo][subpage] = (size_t)((modeResponse[offset + 2] << 8) +
modeResponse[offset + 3] + 4);
decodedMode->Pages[pageNo][subpage] = malloc(decodedMode->pageSizes[pageNo][subpage]);
memset(decodedMode->Pages[pageNo][subpage], 0, decodedMode->pageSizes[pageNo][subpage]);
memcpy(decodedMode->Pages[pageNo][subpage], modeResponse + offset,
decodedMode->pageSizes[pageNo][subpage]);
offset += decodedMode->pageSizes[pageNo][subpage];
}
else
{
if(offset + 1 >= length)
break;
pageNo = (uint8_t)(modeResponse[offset] & 0x3F);
decodedMode->pageSizes[pageNo][0] = (size_t)(modeResponse[offset + 1] + 2);
decodedMode->Pages[pageNo][0] = malloc(decodedMode->pageSizes[pageNo][0]);
memset(decodedMode->Pages[pageNo][0], 0, decodedMode->pageSizes[pageNo][0]);
memcpy(decodedMode->Pages[pageNo][0], modeResponse + offset, decodedMode->pageSizes[pageNo][0]);
offset += decodedMode->pageSizes[pageNo][0];
}
}
}
return decodedMode;
}

View File

@@ -1,72 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : scsi_mode.h
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Contains definitions for SCSI MODE PAGEs.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#ifndef DISCIMAGECHEF_DEVICE_REPORT_SCSI_MODE_H
#define DISCIMAGECHEF_DEVICE_REPORT_SCSI_MODE_H
typedef struct
{
uint8_t Density;
uint64_t Blocks;
uint32_t BlockLength;
} BlockDescriptor;
typedef struct
{
uint8_t MediumType;
int WriteProtected;
BlockDescriptor BlockDescriptors[4096];
int descriptorsLength;
uint8_t Speed;
uint8_t BufferedMode;
int EBC;
int DPOFUA;
int decoded;
} ModeHeader;
typedef struct
{
ModeHeader Header;
unsigned char *Pages[256][256];
size_t pageSizes[256][256];
int decoded;
} DecodedMode;
ModeHeader *DecodeModeHeader6(unsigned char *modeResponse, uint8_t deviceType);
ModeHeader *DecodeModeHeader10(unsigned char *modeResponse, uint8_t deviceType);
DecodedMode *DecodeMode6(unsigned char *modeResponse, uint8_t deviceType);
DecodedMode *DecodeMode10(unsigned char *modeResponse, uint8_t deviceType);
#endif //DISCIMAGECHEF_DEVICE_REPORT_SCSI_MODE_H

View File

@@ -1,803 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : scsi_report.c
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Creates report for SCSI devices.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#include <malloc.h>
#include <string.h>
#include <libxml/xmlwriter.h>
#include <unistd.h>
#include "scsi_report.h"
#include "scsi.h"
#include "inquiry_decode.h"
#include "scsi_mode.h"
#include "mmc_report.h"
#include "ssc_report.h"
void ScsiReport(int fd, xmlTextWriterPtr xmlWriter)
{
unsigned char *sense = NULL;
unsigned char *buffer = NULL;
int error;
int page_len;
int removable = FALSE;
char user_response = ' ';
unsigned char *tmpString;
const int testSize512[] = {514,
// Long sector sizes for SuperDisk
536, 558,
// Long sector sizes for 512-byte magneto-opticals
600, 610, 630};
const int testSize1024[] = {
// Long sector sizes for floppies
1026,
// Long sector sizes for 1024-byte magneto-opticals
1200};
const int testSize2048[] = {2380};
const int testSize4096[] = {4760};
const int testSize8192[] = {9424};
printf("Querying SCSI INQUIRY...\n");
error = Inquiry(fd, &buffer, &sense);
if(error)
{
fprintf(stderr, "Error {0} requesting INQUIRY", error);
return;
}
xmlTextWriterStartElement(xmlWriter, BAD_CAST DIC_SCSI_REPORT_ELEMENT); // <SCSI>
page_len = *(buffer + 4) + 5;
ScsiInquiry *inquiry = malloc(sizeof(ScsiInquiry));
memset(inquiry, 0, sizeof(ScsiInquiry));
memcpy(inquiry, buffer, page_len > sizeof(ScsiInquiry) ? sizeof(ScsiInquiry) : page_len);
if(inquiry->RMB)
{
do
{
printf("Is the media removable from the reading/writing elements (flash memories ARE NOT removable)? (Y/N): ");
scanf("%c", &user_response);
printf("\n");
}while(user_response != 'Y' && user_response != 'y' && user_response != 'N' && user_response != 'n');
removable = (user_response == 'Y' || user_response == 'y');
}
xmlTextWriterStartElement(xmlWriter, BAD_CAST DIC_SCSI_INQUIRY_ELEMENT); // <Inquiry>
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "AccessControlCoordinator", "%s",
inquiry->ACC ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ACKRequests", "%s", inquiry->ACKREQQ ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Address16", "%s", inquiry->Addr16 ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Address32", "%s", inquiry->Addr32 ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "AERCSupported", "%s", inquiry->AERC ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ANSIVersion", "%d", inquiry->ANSIVersion);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "AsymmetricalLUNAccess", "%s", DecodeTPGSValues(inquiry->TPGS));
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BasicQueueing", "%s", inquiry->BQue ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "DeviceTypeModifier", "%d", inquiry->DeviceTypeModifier);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ECMAVersion", "%d", inquiry->ECMAVersion);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "EnclosureServices", "%s", inquiry->EncServ ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "HierarchicalLUN", "%s", inquiry->HiSup ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ISOVersion", "%d", inquiry->ISOVersion);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "IUS", "%s", inquiry->IUS ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LinkedCommands", "%s", inquiry->Linked ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MediumChanger", "%s", inquiry->MChngr ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "MultiPortDevice", "%s", inquiry->MultiP ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "NormalACA", "%s", inquiry->NormACA ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PeripheralDeviceType", "%s",
DecodePeripheralDeviceType(inquiry->PeripheralDeviceType));
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "PeripheralQualifier", "%s",
DecodePeripheralQualifier(inquiry->PeripheralQualifier));
tmpString = malloc(17);
memset(tmpString, 0, 17);
memcpy(tmpString, inquiry->ProductIdentification, 16);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ProductIdentification", "%s", tmpString);
free(tmpString);
tmpString = malloc(5);
memset(tmpString, 0, 5);
memcpy(tmpString, inquiry->ProductRevisionLevel, 4);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ProductRevisionLevel", "%s", tmpString);
free(tmpString);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Protection", "%s", inquiry->Protect ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "QAS", "%s", inquiry->QAS ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "RelativeAddressing", "%s",
inquiry->RelAddr ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Removable", "%s", inquiry->RMB ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ResponseDataFormat", "%d", inquiry->ResponseDataFormat);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SoftReset", "%s", inquiry->SftRe ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SPIClocking", "%s", DecodeSPIClocking(inquiry->Clocking));
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "StorageArrayController", "%s",
inquiry->SCCS ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SyncTransfer", "%s", inquiry->Sync ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "TaggedCommandQueue", "%s", inquiry->CmdQue ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "TerminateTaskSupported", "%s",
inquiry->TrmTsk ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "ThirdPartyCopy", "%s", inquiry->ThreePC ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "TranferDisable", "%s", inquiry->TranDis ? "true" : "false");
tmpString = malloc(9);
memset(tmpString, 0, 9);
memcpy(tmpString, inquiry->VendorIdentification, 8);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "VendorIdentification", "%8s", tmpString);
free(tmpString);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WideBus16", "%s", inquiry->WBus16 ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WideBus32", "%s", inquiry->WBus32 ? "true" : "false");
xmlTextWriterStartElement(xmlWriter, BAD_CAST "Data");
xmlTextWriterWriteBase64(xmlWriter, buffer, 0, page_len);
xmlTextWriterEndElement(xmlWriter);
xmlTextWriterEndElement(xmlWriter); // </Inquiry>
// TODO: EVPDs
if(removable)
{
if(inquiry->PeripheralDeviceType == 0x05) // MultiMediaDevice
{
AllowMediumRemoval(fd, &sense);
EjectTray(fd, &sense);
}
else if(inquiry->PeripheralDeviceType == 0x05) // SequentialAccess
{
SpcAllowMediumRemoval(fd, &sense);
printf("Asking drive to unload tape (can take a few minutes)...\n");
Unload(fd, &sense);
}
printf("Please remove any media from the device and press any key when it is out.\n");
scanf("%c");
}
int supportsMode6 = FALSE;
int supportsMode10 = FALSE;
int supportsModeSubpages = FALSE;
unsigned char *mode6Response = NULL;
unsigned char *mode10Response = NULL;
printf("Querying all mode pages and subpages using SCSI MODE SENSE (10)...\n");
error = ModeSense10(fd, &mode10Response, &sense, FALSE, TRUE, MODE_PAGE_DEFAULT, 0x3F, 0xFF);
if(error)
{
printf("Querying all mode pages using SCSI MODE SENSE (10)...\n");
error = ModeSense10(fd, &mode10Response, &sense, FALSE, TRUE, MODE_PAGE_DEFAULT, 0x3F, 0x00);
if(!error)
supportsMode10 = TRUE;
}
else
{
supportsMode10 = TRUE;
supportsModeSubpages = TRUE;
}
printf("Querying all mode pages and subpages using SCSI MODE SENSE (6)...\n");
error = ModeSense6(fd, &mode6Response, &sense, FALSE, MODE_PAGE_DEFAULT, 0x3F, 0xFF);
if(error)
{
printf("Querying all mode pages using SCSI MODE SENSE (6)...\n");
error = ModeSense6(fd, &mode6Response, &sense, FALSE, MODE_PAGE_DEFAULT, 0x3F, 0x00);
if(error)
{
printf("Querying SCSI MODE SENSE (6)...\n");
error = ModeSense6(fd, &mode6Response, &sense, FALSE, MODE_PAGE_DEFAULT, 0x00, 0x00);
if(!error)
supportsMode6 = TRUE;
}
else
supportsMode6 = TRUE;
}
else
{
supportsMode6 = TRUE;
supportsModeSubpages = TRUE;
}
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsModeSense6", "%s", supportsMode6 ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsModeSense10", "%s", supportsMode10 ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsModeSubpages", "%s",
supportsModeSubpages ? "true" : "false");
if(supportsMode6)
{
xmlTextWriterStartElement(xmlWriter, BAD_CAST "ModeSense6Data");
xmlTextWriterWriteBase64(xmlWriter, mode6Response, 0, *(mode6Response + 0) + 1);
xmlTextWriterEndElement(xmlWriter);
}
if(supportsMode10)
{
xmlTextWriterStartElement(xmlWriter, BAD_CAST "ModeSense10Data");
xmlTextWriterWriteBase64(xmlWriter, mode10Response, 0,
(*(mode10Response + 0) << 8) + *(mode10Response + 1) + 2);
xmlTextWriterEndElement(xmlWriter);
}
DecodedMode *decMode = NULL;
unsigned char *cdromMode = NULL;
if(supportsMode10)
decMode = DecodeMode10(mode10Response, inquiry->PeripheralDeviceType);
else if(supportsMode6)
decMode = DecodeMode6(mode6Response, inquiry->PeripheralDeviceType);
if(decMode->decoded)
{
int page, subpage;
xmlTextWriterStartElement(xmlWriter, BAD_CAST "ModeSense"); // <ModeSense>
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BlankCheckEnabled", "%s",
decMode->Header.EBC ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "DPOandFUA", "%s",
decMode->Header.DPOFUA ? "true" : "false");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "WriteProtected", "%s",
decMode->Header.WriteProtected ? "true" : "false");
if(decMode->Header.BufferedMode > 0)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BlankCheckEnabled", "%d",
decMode->Header.BufferedMode);
if(decMode->Header.Speed > 0)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Speed", "%d", decMode->Header.Speed);
for(page = 0; page < 256; page++)
{
for(subpage = 0; subpage < 256; subpage++)
{
if(decMode->pageSizes[page][subpage] > 0 && decMode->Pages[page][subpage] != NULL)
{
xmlTextWriterStartElement(xmlWriter, BAD_CAST "modePageType");
xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST "page", "%d", page);
xmlTextWriterWriteFormatAttribute(xmlWriter, BAD_CAST "subpage", "%d", subpage);
xmlTextWriterWriteBase64(xmlWriter, decMode->Pages[page][subpage], 0,
decMode->pageSizes[page][subpage]);
xmlTextWriterEndElement(xmlWriter);
if(page == 0x2A && subpage == 0x00)
{
cdromMode = decMode->Pages[0x2A][0x00];
}
}
}
}
xmlTextWriterEndElement(xmlWriter); // </ModeSense>
}
if(inquiry->PeripheralDeviceType == 0x05) // MultiMediaDevice
{
MmcReport(fd, xmlWriter, cdromMode);
}
else if(inquiry->PeripheralDeviceType == 0x01) // SequentialAccess
{
SscReport(fd, xmlWriter);
}
else
{
if(removable)
{
user_response = ' ';
int anyMedia = FALSE;
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 "RemovableMedias"); // <RemovableMedias>
xmlTextWriterStartElement(xmlWriter, BAD_CAST "testedMediaType"); // <testedMediaType>
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)
{
uint64_t blocks = 0;
uint32_t blockSize = 0;
printf("Querying SCSI READ CAPACITY...\n");
error = ReadCapacity(fd, &buffer, &sense, FALSE, 0, FALSE);
if(!error)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadCapacity", "%s", "true");
blocks =
(uint64_t)(buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + (buffer[3]) +
1;
blockSize = (uint32_t)((buffer[4] << 24) + (buffer[5] << 16) + (buffer[6] << 8) +
(buffer[7]));
}
printf("Querying SCSI READ CAPACITY (16)...\n");
error = ReadCapacity16(fd, &buffer, &sense, FALSE, 0);
if(!error)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadCapacity16", "%s", "true");
blocks = (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + (buffer[3]);
blocks <<= 32;
blocks += (buffer[4] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7]);
blocks++;
blockSize = (uint32_t)((buffer[8] << 24) + (buffer[9] << 16) + (buffer[10] << 8) +
(buffer[11]));
}
if(blocks != 0)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Blocks", "%llu", blocks);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BlockSize", "%lu", blockSize);
}
if(decMode != NULL)
decMode->decoded = 0;
printf("Querying SCSI MODE SENSE (10)...\n");
error = ModeSense10(fd, &mode10Response, &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, mode10Response, 0,
(*(mode10Response + 0) << 8) + *(mode10Response + 1) + 2);
xmlTextWriterEndElement(xmlWriter);
decMode = DecodeMode10(mode10Response, inquiry->PeripheralDeviceType);
}
printf("Querying SCSI MODE SENSE (6)...\n");
error = ModeSense6(fd, &mode6Response, &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, mode6Response, 0, *(mode6Response + 0) + 1);
xmlTextWriterEndElement(xmlWriter);
if(!decMode->decoded)
decMode = DecodeMode6(mode6Response, inquiry->PeripheralDeviceType);
}
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("Trying SCSI READ (6)...\n");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead", "%s",
!Read6(fd, &buffer, &sense, 0, blockSize, 1) ? "true"
: "false");
printf("Trying SCSI READ (10)...\n");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead10", "%s",
!Read10(fd, &buffer, &sense, 0, FALSE, TRUE, FALSE, FALSE, 0,
blockSize, 0, 1) ? "true" : "false");
printf("Trying SCSI READ (12)...\n");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead12", "%s",
!Read12(fd, &buffer, &sense, 0, FALSE, TRUE, FALSE, FALSE, 0,
blockSize, 0, 1, FALSE) ? "true" : "false");
printf("Trying SCSI READ (16)...\n");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead16", "%s",
!Read16(fd, &buffer, &sense, 0, FALSE, TRUE, FALSE, 0,
blockSize, 0, 1, FALSE) ? "true" : "false");
uint32_t longBlockSize = blockSize;
int supportsReadLong10 = FALSE;
printf("Trying SCSI READ LONG (10)...\n");
ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, 0xFFFF);
if((sense[0] == 0x70 || sense[0] == 0x71) && (sense[2] & 0x0F) == 0x05 && sense[12] == 0x24 &&
sense[13] == 0x00)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLong", "%s", "true");
supportsReadLong10 = TRUE;
if(sense[0] & 0x80 && sense[2] & 0x20)
{
uint32_t information = (sense[3] << 24) + (sense[4] << 16) + (sense[5] << 8) + sense[6];
longBlockSize = 0xFFFF - (information & 0xFFFF);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LongBlockSize", "%d",
longBlockSize);
}
}
printf("Trying SCSI READ LONG (16)...\n");
ReadLong16(fd, &buffer, &sense, FALSE, 0, 0xFFFF);
if((sense[0] == 0x70 || sense[0] == 0x71) && (sense[2] & 0x0F) == 0x05 && sense[12] == 0x24 &&
sense[13] == 0x00)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLong16", "%s", "true");
int i;
if(supportsReadLong10 && blockSize == longBlockSize)
{
if(blockSize == 512)
{
for(i = 0; i < sizeof(testSize512) / sizeof(int); i++)
{
error = ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, testSize512[i]);
if(!error)
{
longBlockSize = testSize512[i];
break;
}
}
}
else if(blockSize == 1024)
{
for(i = 0; i < sizeof(testSize1024) / sizeof(int); i++)
{
error = ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, testSize1024[i]);
if(!error)
{
longBlockSize = testSize1024[i];
break;
}
}
}
else if(blockSize == 2048)
{
for(i = 0; i < sizeof(testSize2048) / sizeof(int); i++)
{
error = ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, testSize2048[i]);
if(!error)
{
longBlockSize = testSize2048[i];
break;
}
}
}
else if(blockSize == 4096)
{
for(i = 0; i < sizeof(testSize4096) / sizeof(int); i++)
{
error = ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, testSize4096[i]);
if(!error)
{
longBlockSize = testSize4096[i];
break;
}
}
}
else if(blockSize == 8192)
{
for(i = 0; i < sizeof(testSize8192) / sizeof(int); i++)
{
error = ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, testSize8192[i]);
if(!error)
{
longBlockSize = testSize8192[i];
break;
}
}
}
}
if(supportsReadLong10 && blockSize == longBlockSize)
{
user_response = ' ';
do
{
printf("Drive supports SCSI READ LONG but I cannot find the correct size. Do you want me to try? (This can take hours) (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')
{
for(i = blockSize; i <= 65536; i++)
{
printf("\rTrying to READ LONG with a size of %d bytes", i);
error = ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, i);
if(!error)
{
longBlockSize = i;
break;
}
}
printf("\n");
}
user_response = ' ';
}
if(supportsReadLong10 && blockSize != longBlockSize)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LongBlockSize", "%d", longBlockSize);
}
xmlTextWriterEndElement(xmlWriter); // </testedMediaType>
if(!anyMedia)
anyMedia = TRUE;
}
}
if(anyMedia)
xmlTextWriterEndElement(xmlWriter); // </RemovableMedias>
}
else
{
uint64_t blocks = 0;
uint32_t blockSize = 0;
xmlTextWriterStartElement(xmlWriter, BAD_CAST "ReadCapabilities"); // <ReadCapabilities>
printf("Querying SCSI READ CAPACITY...\n");
error = ReadCapacity(fd, &buffer, &sense, FALSE, 0, FALSE);
if(!error)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadCapacity", "%s", "true");
blocks = (uint64_t)(buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + (buffer[3]) + 1;
blockSize = (uint32_t)((buffer[4] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7]));
}
printf("Querying SCSI READ CAPACITY (16)...\n");
error = ReadCapacity16(fd, &buffer, &sense, FALSE, 0);
if(!error)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadCapacity16", "%s", "true");
blocks = (buffer[0] << 24) + (buffer[1] << 16) + (buffer[2] << 8) + (buffer[3]);
blocks <<= 32;
blocks += (buffer[4] << 24) + (buffer[5] << 16) + (buffer[6] << 8) + (buffer[7]);
blocks++;
blockSize = (uint32_t)((buffer[8] << 24) + (buffer[9] << 16) + (buffer[10] << 8) + (buffer[11]));
}
if(blocks != 0)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "Blocks", "%llu", blocks);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "BlockSize", "%lu", blockSize);
}
if(supportsMode10)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsModeSense10", "%s", "true");
xmlTextWriterStartElement(xmlWriter, BAD_CAST "ModeSense10Data");
xmlTextWriterWriteBase64(xmlWriter, mode10Response, 0,
(*(mode10Response + 0) << 8) + *(mode10Response + 1) + 2);
xmlTextWriterEndElement(xmlWriter);
}
if(supportsMode6)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsModeSense6", "%s", "true");
xmlTextWriterStartElement(xmlWriter, BAD_CAST "ModeSense6Data");
xmlTextWriterWriteBase64(xmlWriter, mode6Response, 0, *(mode6Response + 0) + 1);
xmlTextWriterEndElement(xmlWriter);
}
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("Trying SCSI READ (6)...\n");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead", "%s",
!Read6(fd, &buffer, &sense, 0, blockSize, 1) ? "true" : "false");
printf("Trying SCSI READ (10)...\n");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead10", "%s",
!Read10(fd, &buffer, &sense, 0, FALSE, TRUE, FALSE, FALSE, 0, blockSize, 0,
1) ? "true" : "false");
printf("Trying SCSI READ (12)...\n");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead12", "%s",
!Read12(fd, &buffer, &sense, 0, FALSE, TRUE, FALSE, FALSE, 0, blockSize, 0,
1, FALSE) ? "true" : "false");
printf("Trying SCSI READ (16)...\n");
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsRead16", "%s",
!Read16(fd, &buffer, &sense, 0, FALSE, TRUE, FALSE, 0, blockSize, 0, 1,
FALSE) ? "true" : "false");
uint32_t longBlockSize = blockSize;
int supportsReadLong10 = FALSE;
printf("Trying SCSI READ LONG (10)...\n");
ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, 0xFFFF);
if((sense[0] == 0x70 || sense[0] == 0x71) && (sense[2] & 0x0F) == 0x05 && sense[12] == 0x24 &&
sense[13] == 0x00)
{
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLong", "%s", "true");
supportsReadLong10 = TRUE;
if(sense[0] & 0x80 && sense[2] & 0x20)
{
uint32_t information = (sense[3] << 24) + (sense[4] << 16) + (sense[5] << 8) + sense[6];
longBlockSize = 0xFFFF - (information & 0xFFFF);
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LongBlockSize", "%d", longBlockSize);
}
}
printf("Trying SCSI READ LONG (16)...\n");
ReadLong16(fd, &buffer, &sense, FALSE, 0, 0xFFFF);
if((sense[0] == 0x70 || sense[0] == 0x71) && (sense[2] & 0x0F) == 0x05 && sense[12] == 0x24 &&
sense[13] == 0x00)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "SupportsReadLong16", "%s", "true");
int i;
if(supportsReadLong10 && blockSize == longBlockSize)
{
if(blockSize == 512)
{
for(i = 0; i < sizeof(testSize512) / sizeof(int); i++)
{
error = ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, testSize512[i]);
if(!error)
{
longBlockSize = testSize512[i];
break;
}
}
}
else if(blockSize == 1024)
{
for(i = 0; i < sizeof(testSize1024) / sizeof(int); i++)
{
error = ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, testSize1024[i]);
if(!error)
{
longBlockSize = testSize1024[i];
break;
}
}
}
else if(blockSize == 2048)
{
for(i = 0; i < sizeof(testSize2048) / sizeof(int); i++)
{
error = ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, testSize2048[i]);
if(!error)
{
longBlockSize = testSize2048[i];
break;
}
}
}
else if(blockSize == 4096)
{
for(i = 0; i < sizeof(testSize4096) / sizeof(int); i++)
{
error = ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, testSize4096[i]);
if(!error)
{
longBlockSize = testSize4096[i];
break;
}
}
}
else if(blockSize == 8192)
{
for(i = 0; i < sizeof(testSize8192) / sizeof(int); i++)
{
error = ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, testSize8192[i]);
if(!error)
{
longBlockSize = testSize8192[i];
break;
}
}
}
}
if(supportsReadLong10 && blockSize == longBlockSize)
{
user_response = ' ';
do
{
printf("Drive supports SCSI READ LONG but I cannot find the correct size. Do you want me to try? (This can take hours) (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')
{
for(i = blockSize; i <= 65536; i++)
{
printf("\rTrying to READ LONG with a size of %d bytes", i);
error = ReadLong10(fd, &buffer, &sense, FALSE, FALSE, 0, i);
if(!error)
{
longBlockSize = i;
break;
}
}
printf("\n");
}
}
if(supportsReadLong10 && blockSize != longBlockSize)
xmlTextWriterWriteFormatElement(xmlWriter, BAD_CAST "LongBlockSize", "%d", longBlockSize);
xmlTextWriterEndElement(xmlWriter); // </ReadCapabilities>
}
}
xmlTextWriterEndElement(xmlWriter); // </SCSI>
}

View File

@@ -1,40 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : scsi_report.h
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Contains definitions used in SCSI reports.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#ifndef DISCIMAGECHEF_DEVICE_REPORT_SCSI_REPORT_H
#define DISCIMAGECHEF_DEVICE_REPORT_SCSI_REPORT_H
#define DIC_SCSI_REPORT_ELEMENT "SCSI"
#define DIC_SCSI_INQUIRY_ELEMENT "Inquiry"
void ScsiReport(int fd, xmlTextWriterPtr xmlWriter);
#endif //DISCIMAGECHEF_DEVICE_REPORT_SCSI_REPORT_H

View File

@@ -1,375 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : ssc_report.c
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Creates report for SCSI Streaming devices.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#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 == NULL || !decMode->decoded)
decMode = DecodeMode6(buffer, 0x01);
}
if(decMode != NULL && 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

@@ -1,87 +0,0 @@
/***************************************************************************
The Disc Image Chef
----------------------------------------------------------------------------
Filename : ssc_report.h
Author(s) : Natalia Portillo
Component : DiscImageChef.Device.Report
--[ Description ] ----------------------------------------------------------
Contains definitions used in SCSI Streaming device reports.
--[ License ] --------------------------------------------------------------
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
----------------------------------------------------------------------------
Copyright © 2011-2019 Natalia Portillo
****************************************************************************/
#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