File indexing completed on 2025-03-23 04:28:12
0001 /* 0002 k3bscsicommand_win32.cpp 0003 SPDX-FileCopyrightText: 2007 Jeremy C. Andrus <jeremy@jeremya.com> 0004 SPDX-FileCopyrightText: 2009 Ralf Habacker <ralf.habacker@freenet.de> 0005 SPDX-FileCopyrightText: 1998-2007 Sebastian Trueg <trueg@k3b.org> 0006 0007 Parts of this file are inspired (and copied) from various source 0008 files in the cdrdao project (C) J. Schilling, Andreas Mueller 0009 and many others. 0010 0011 SPDX-License-Identifier: GPL-2.0-or-later 0012 */ 0013 0014 #include "k3bscsicommand.h" 0015 #include "k3bdevice.h" 0016 0017 #include <windows.h> 0018 #include <stdio.h> 0019 #include <fcntl.h> 0020 #include <errno.h> 0021 #include <string.h> 0022 #include <assert.h> 0023 0024 #include "winspti.h" 0025 0026 0027 class K3b::Device::ScsiCommand::Private 0028 { 0029 public: 0030 SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER m_cmd; 0031 0032 SCSI_SENSE_DATA m_senseData; 0033 }; 0034 0035 0036 void K3b::Device::ScsiCommand::clear() 0037 { 0038 ::memset( &d->m_cmd, 0, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER) ); 0039 } 0040 0041 0042 unsigned char& K3b::Device::ScsiCommand::operator[]( size_t i ) 0043 { 0044 if( d->m_cmd.spt.CdbLength < i+1 ) 0045 d->m_cmd.spt.CdbLength = i+1; 0046 return d->m_cmd.spt.Cdb[i]; 0047 } 0048 0049 0050 int K3b::Device::ScsiCommand::transport( TransportDirection dir, 0051 void* data, 0052 size_t len ) 0053 { 0054 bool needToClose = false; 0055 ULONG returned = 0; 0056 BOOL status = TRUE; 0057 0058 // closing device every time breaks scsi operation, disabled for now 0059 //needToClose = !m_device->isOpen(); 0060 m_device->open( dir == TR_DIR_WRITE ); 0061 0062 if( !m_device->isOpen() ) { 0063 qDebug() << "(K3bScsiCommand::transport) could not perform Win32 IOCTL on invalid handle value" << Qt::endl; 0064 return -1; 0065 } 0066 0067 if ( dir == TR_DIR_READ ) 0068 d->m_cmd.spt.DataIn = SCSI_IOCTL_DATA_IN; 0069 else if ( dir == TR_DIR_WRITE ) 0070 d->m_cmd.spt.DataIn = SCSI_IOCTL_DATA_OUT; 0071 else 0072 d->m_cmd.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED; 0073 0074 d->m_cmd.spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT); 0075 d->m_cmd.spt.SenseInfoLength = SENSE_LEN_SPTI; 0076 d->m_cmd.spt.DataTransferLength = len; 0077 d->m_cmd.spt.TimeOutValue = 2; 0078 d->m_cmd.spt.DataBuffer = len ? data : NULL; 0079 d->m_cmd.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf); 0080 0081 status = DeviceIoControl( m_device->handle(), 0082 IOCTL_SCSI_PASS_THROUGH_DIRECT, 0083 &(d->m_cmd), sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), 0084 &(d->m_cmd), sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), 0085 &returned, NULL); 0086 0087 if( needToClose ) 0088 m_device->close(); 0089 0090 // get the sense data on error 0091 if ( !status ) { 0092 qDebug() << "(K3bScsiCommand::transport) ioctl failed: " << GetLastError() << ", returned=" << returned << Qt::endl; 0093 ::memcpy( &(d->m_senseData), d->m_cmd.ucSenseBuf, SENSE_LEN_SPTI ); 0094 0095 debugError( d->m_cmd.spt.Cdb[0], 0096 d->m_senseData.SD_Error, 0097 d->m_senseData.SD_SenseKey, 0098 d->m_senseData.SD_ASC, 0099 d->m_senseData.SD_ASCQ ); 0100 0101 int errCode = 0102 (d->m_senseData.SD_Error << 24) & 0xF000 | 0103 (d->m_senseData.SD_SenseKey << 16) & 0x0F00 | 0104 (d->m_senseData.SD_ASC << 8) & 0x00F0 | 0105 (d->m_senseData.SD_ASCQ) & 0x000F; 0106 0107 return ( errCode != 0 ? errCode : 1 ); 0108 } 0109 qDebug() 0110 << "len:" << d->m_cmd.spt.CdbLength 0111 << "cmd:" << commandString(d->m_cmd.spt.Cdb[0]) 0112 << d->m_cmd.spt.Cdb[0] 0113 << d->m_cmd.spt.Cdb[1] 0114 << d->m_cmd.spt.Cdb[2] 0115 << d->m_cmd.spt.Cdb[3] 0116 << d->m_cmd.spt.Cdb[4] 0117 << d->m_cmd.spt.Cdb[5] 0118 << d->m_cmd.spt.Cdb[6] 0119 << d->m_cmd.spt.Cdb[7] 0120 << d->m_cmd.spt.Cdb[8] 0121 << d->m_cmd.spt.Cdb[9] 0122 << "datalen=" << d->m_cmd.spt.DataTransferLength 0123 << "returned=" << returned 0124 ; 0125 0126 return 0; 0127 }