File indexing completed on 2025-03-16 04:29:56
0001 /* 0002 SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 /** 0006 This file contains all the MMC command implementations of the K3b device class 0007 to make the code more readable. 0008 **/ 0009 0010 0011 #include "k3bdevice.h" 0012 #include "k3bscsicommand.h" 0013 #include "k3bdeviceglobals.h" 0014 #include "QDebug" 0015 0016 #include <string.h> 0017 0018 0019 bool K3b::Device::Device::testUnitReady() const 0020 { 0021 ScsiCommand cmd( this ); 0022 cmd.enableErrorMessages( false ); 0023 cmd[0] = MMC_TEST_UNIT_READY; 0024 cmd[5] = 0; // Necessary to set the proper command length 0025 return( cmd.transport() == 0 ); 0026 } 0027 0028 0029 bool K3b::Device::Device::getFeature( UByteArray& data, unsigned int feature ) const 0030 { 0031 unsigned char header[2048]; 0032 ::memset( header, 0, 2048 ); 0033 0034 ScsiCommand cmd( this ); 0035 cmd[0] = MMC_GET_CONFIGURATION; 0036 cmd[1] = 2; // read only specified feature 0037 cmd[2] = feature>>8; 0038 cmd[3] = feature; 0039 cmd[8] = 8; // we only read the data length first 0040 cmd[9] = 0; // Necessary to set the proper command length 0041 0042 // we only read the data length first 0043 unsigned int dataLen = 8; 0044 if( !cmd.transport( TR_DIR_READ, header, 8 ) ) 0045 dataLen = from4Byte( header ) + 4; 0046 else 0047 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << ": GET CONFIGURATION length det failed."; 0048 0049 // 0050 // Some buggy firmwares do not return the size of the available data 0051 // but the returned data or something invalid altogether. 0052 // So we simply use the maximum possible value to be on the safe side 0053 // with these buggy drives. 0054 // We cannot use this as default since many firmwares fail with a too high data length. 0055 // 0056 if( (dataLen-8) % 8 || dataLen <= 8 ) 0057 dataLen = 0xFFFF; 0058 0059 // again with real length 0060 data.resize( dataLen ); 0061 ::memset( data.data(), 0, data.size() ); 0062 0063 cmd[7] = data.size() >> 8; 0064 cmd[8] = data.size(); 0065 if( cmd.transport( TR_DIR_READ, data.data(), data.size() ) == 0 ) { 0066 data.resize( qMin( data.size(), (int)from4Byte( data.data() ) + 4 ) ); 0067 return true; 0068 } 0069 else { 0070 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << ": GET CONFIGURATION with real length " 0071 << data.size() << " failed." << Qt::endl; 0072 data.clear(); 0073 return false; 0074 } 0075 } 0076 0077 0078 int K3b::Device::Device::featureCurrent( unsigned int feature ) const 0079 { 0080 UByteArray data; 0081 if( getFeature( data, feature ) ) { 0082 int ret = -1; 0083 if( data.size() >= 11 ) 0084 ret = ( data[8+2]&1 ? 1 : 0 ); // check the current flag 0085 0086 return ret; 0087 } 0088 else 0089 return -1; 0090 } 0091 0092 0093 bool K3b::Device::Device::readIsrc( unsigned int track, QByteArray& isrc ) const 0094 { 0095 UByteArray data; 0096 0097 if( readSubChannel( data, 0x3, track ) ) { 0098 bool isrcValid = false; 0099 0100 if( data.size() >= 8+18 ) { 0101 isrcValid = (data[8+4]>>7 & 0x1); 0102 0103 if( isrcValid ) { 0104 isrc = QByteArray( reinterpret_cast<char*>(data[8+5]), 13 ); 0105 0106 // TODO: check the range of the chars 0107 0108 } 0109 } 0110 0111 return isrcValid; 0112 } 0113 else 0114 return false; 0115 } 0116 0117 0118 bool K3b::Device::Device::readMcn( QByteArray& mcn ) const 0119 { 0120 UByteArray data; 0121 0122 if( readSubChannel( data, 0x2, 0 ) ) { 0123 bool mcnValid = false; 0124 0125 if( data.size() >= 8+18 ) { 0126 mcnValid = (data[8+4]>>7 & 0x1); 0127 0128 if( mcnValid ) 0129 mcn = QByteArray( reinterpret_cast<char*>(data[8+5]), 14 ); 0130 } 0131 0132 return mcnValid; 0133 } 0134 else 0135 return false; 0136 } 0137 0138 0139 bool K3b::Device::Device::getPerformance( UByteArray& data, 0140 unsigned int type, 0141 unsigned int dataType, 0142 unsigned int lba ) const 0143 { 0144 unsigned int descLen = 0; 0145 switch( type ) { 0146 case 0x0: 0147 descLen = 16; 0148 break; 0149 case 0x1: 0150 descLen = 8; 0151 break; 0152 case 0x2: 0153 descLen = 2048; 0154 break; 0155 case 0x3: 0156 descLen = 16; 0157 break; 0158 case 0x4: 0159 descLen = 8; 0160 break; 0161 case 0x5: 0162 descLen = 8; // FIXME: ?? 0163 break; 0164 } 0165 0166 unsigned int dataLen = descLen + 8; 0167 UByteArray header( dataLen ); 0168 ::memset( header.data(), 0, dataLen ); 0169 0170 ScsiCommand cmd( this ); 0171 cmd[0] = MMC_GET_PERFORMANCE; 0172 cmd[1] = dataType; 0173 cmd[2] = lba >> 24; 0174 cmd[3] = lba >> 16; 0175 cmd[4] = lba >> 8; 0176 cmd[5] = lba; 0177 cmd[9] = 1; // first we read one descriptor 0178 cmd[10] = type; 0179 cmd[11] = 0; // Necessary to set the proper command length 0180 if( cmd.transport( TR_DIR_READ, header.data(), dataLen ) ) { 0181 qDebug() << "(K3b::Device::Device) " << blockDeviceName() 0182 << ": GET PERFORMANCE length det failed." << Qt::endl; 0183 return false; 0184 } 0185 0186 dataLen = from4Byte( header.data() ) + 4; 0187 0188 // At least one Panasonic drive returns gigantic changing numbers for the data length 0189 // which makes K3b crash below when *data cannot be allocated. That's why we cut the 0190 // length here. 0191 // FIXME: 2048 is a proper upper boundary for the write speed but not for all 0192 // return types. "Defect Status Data" for example might return way more data. 0193 // FIXME: Since we only use getPerformance for writing speeds and without a proper length 0194 // those do not make sense it is better to fail here anyway. 0195 if( descLen == 0 || (dataLen-8) % descLen || dataLen <= 8 || dataLen > 2048 ) { 0196 qDebug() << "(K3b::Device::Device) " << blockDeviceName() 0197 << ": GET PERFORMANCE reports bogus dataLen: " << dataLen << Qt::endl; 0198 return false; 0199 } 0200 0201 data.resize( dataLen ); 0202 ::memset( data.data(), 0, data.size() ); 0203 0204 unsigned int numDesc = (dataLen-8)/descLen; 0205 0206 cmd[8] = numDesc>>8; 0207 cmd[9] = numDesc; 0208 if( cmd.transport( TR_DIR_READ, data.data(), data.size() ) == 0 ) { 0209 data.resize( qMin( data.size(), (int)from4Byte( data.data() ) + 4 ) ); 0210 0211 if( data.size() > 8 ) { 0212 return true; 0213 } 0214 else { 0215 qDebug() << "(K3b::Device::Device) " << blockDeviceName() 0216 << ": GET PERFORMANCE reports invalid data size:" << data.size() << Qt::endl; 0217 data.clear(); 0218 return false; 0219 } 0220 } 0221 else { 0222 qDebug() << "(K3b::Device::Device) " << blockDeviceName() 0223 << ": GET PERFORMANCE with real length " 0224 << data.size() << " failed." << Qt::endl; 0225 data.clear(); 0226 return false; 0227 } 0228 } 0229 0230 0231 bool K3b::Device::Device::setSpeed( unsigned int readingSpeed, 0232 unsigned int writingSpeed, 0233 bool cav ) const 0234 { 0235 ScsiCommand cmd( this ); 0236 cmd[0] = MMC_SET_SPEED; 0237 cmd[1] = ( cav ? 0x1 : 0x0 ); 0238 cmd[2] = readingSpeed >> 8; 0239 cmd[3] = readingSpeed; 0240 cmd[4] = writingSpeed >> 8; 0241 cmd[5] = writingSpeed; 0242 cmd[11] = 0; // Necessary to set the proper command length 0243 return ( cmd.transport( TR_DIR_WRITE ) == 0 ); 0244 } 0245 0246 0247 bool K3b::Device::Device::seek( unsigned long lba ) const 0248 { 0249 ScsiCommand cmd( this ); 0250 cmd[0] = MMC_SEEK_10; 0251 cmd[2] = lba>>24; 0252 cmd[3] = lba>>16; 0253 cmd[4] = lba>>8; 0254 cmd[5] = lba; 0255 cmd[9] = 0; // Necessary to set the proper command length 0256 return !cmd.transport(); 0257 } 0258 0259 0260 bool K3b::Device::Device::readTrackInformation( UByteArray& data, int type, int value ) const 0261 { 0262 unsigned char header[2048]; 0263 ::memset( header, 0, 2048 ); 0264 0265 ScsiCommand cmd( this ); 0266 cmd[0] = MMC_READ_TRACK_INFORMATION; 0267 cmd[9] = 0; // Necessary to set the proper command length 0268 0269 switch( type ) { 0270 case 0: 0271 case 1: 0272 case 2: 0273 cmd[1] = type & 0x3; 0274 cmd[2] = value>>24; 0275 cmd[3] = value>>16; 0276 cmd[4] = value>>8; 0277 cmd[5] = value; 0278 break; 0279 default: 0280 qDebug() << "(K3b::Device::readTrackInformation) wrong type parameter: " << type; 0281 return false; 0282 } 0283 0284 // first we read the header 0285 unsigned int dataLen = 4; 0286 cmd[8] = 4; 0287 if( cmd.transport( TR_DIR_READ, header, 4 ) == 0 ) 0288 dataLen = from2Byte( header ) + 2; 0289 else 0290 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << ": READ TRACK INFORMATION length det failed."; 0291 0292 // 0293 // Some buggy firmwares do not return the size of the available data 0294 // but the returned data. 0295 // So we try to determine the correct size based on the medium type 0296 // DVD+R: 40 (MMC4) 0297 // DVD-DL: 48 (MMC5) 0298 // CD: 36 (MMC2) 0299 // 0300 if( dataLen <= 6 ) { 0301 int m = mediaType(); 0302 if( m & (MEDIA_DVD_R_DL|MEDIA_DVD_R_DL_SEQ|MEDIA_DVD_R_DL_JUMP) ) 0303 dataLen = 48; 0304 else if( m & (MEDIA_DVD_PLUS_R|MEDIA_DVD_PLUS_R_DL) ) 0305 dataLen = 40; 0306 else 0307 dataLen = 36; 0308 } 0309 0310 // again with real length 0311 data.resize( dataLen ); 0312 ::memset( data.data(), 0, data.size() ); 0313 0314 cmd[7] = data.size() >> 8; 0315 cmd[8] = data.size(); 0316 if( cmd.transport( TR_DIR_READ, data.data(), data.size() ) == 0 ) { 0317 data.resize( qMin( data.size(), from2Byte( data.data() ) + 2 ) ); 0318 return true; 0319 } 0320 else { 0321 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << ": READ TRACK INFORMATION with real length " 0322 << data.size() << " failed." << Qt::endl; 0323 data.clear(); 0324 return false; 0325 } 0326 } 0327 0328 0329 0330 bool K3b::Device::Device::read10( unsigned char* data, 0331 unsigned int dataLen, 0332 unsigned long startAdress, 0333 unsigned int length, 0334 bool fua ) const 0335 { 0336 ::memset( data, 0, dataLen ); 0337 0338 ScsiCommand cmd( this ); 0339 cmd[0] = MMC_READ_10; 0340 cmd[1] = ( fua ? 0x8 : 0x0 ); 0341 cmd[2] = startAdress>>24; 0342 cmd[3] = startAdress>>16; 0343 cmd[4] = startAdress>>8; 0344 cmd[5] = startAdress; 0345 cmd[7] = length>>8; 0346 cmd[8] = length; 0347 cmd[9] = 0; // Necessary to set the proper command length 0348 0349 if( cmd.transport( TR_DIR_READ, data, dataLen ) ) { 0350 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << ": READ 10 failed!"; 0351 return false; 0352 } 0353 else 0354 return true; 0355 } 0356 0357 0358 bool K3b::Device::Device::read12( unsigned char* data, 0359 unsigned int dataLen, 0360 unsigned long startAdress, 0361 unsigned long length, 0362 bool streaming, 0363 bool fua ) const 0364 { 0365 ::memset( data, 0, dataLen ); 0366 0367 ScsiCommand cmd( this ); 0368 cmd[0] = MMC_READ_12; 0369 cmd[1] = ( fua ? 0x8 : 0x0 ); 0370 cmd[2] = startAdress>>24; 0371 cmd[3] = startAdress>>16; 0372 cmd[4] = startAdress>>8; 0373 cmd[5] = startAdress; 0374 cmd[6] = length>>24; 0375 cmd[7] = length>>16; 0376 cmd[8] = length>>8; 0377 cmd[9] = length; 0378 cmd[10] = (streaming ? 0x80 : 0 ); 0379 cmd[11] = 0; // Necessary to set the proper command length 0380 0381 if( cmd.transport( TR_DIR_READ, data, dataLen ) ) { 0382 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << ": READ 12 failed!"; 0383 return false; 0384 } 0385 else 0386 return true; 0387 } 0388 0389 0390 bool K3b::Device::Device::readCd( unsigned char* data, 0391 unsigned int dataLen, 0392 int sectorType, 0393 bool dap, 0394 unsigned long startAdress, 0395 unsigned long length, 0396 bool sync, 0397 bool header, 0398 bool subHeader, 0399 bool userData, 0400 bool edcEcc, 0401 int c2, 0402 int subChannel ) const 0403 { 0404 ::memset( data, 0, dataLen ); 0405 0406 ScsiCommand cmd( this ); 0407 cmd[0] = MMC_READ_CD; 0408 cmd[1] = (sectorType<<2 & 0x1c) | ( dap ? 0x2 : 0x0 ); 0409 cmd[2] = startAdress>>24; 0410 cmd[3] = startAdress>>16; 0411 cmd[4] = startAdress>>8; 0412 cmd[5] = startAdress; 0413 cmd[6] = length>>16; 0414 cmd[7] = length>>8; 0415 cmd[8] = length; 0416 cmd[9] = ( ( sync ? 0x80 : 0x0 ) | 0417 ( subHeader ? 0x40 : 0x0 ) | 0418 ( header ? 0x20 : 0x0 ) | 0419 ( userData ? 0x10 : 0x0 ) | 0420 ( edcEcc ? 0x8 : 0x0 ) | 0421 ( c2<<1 & 0x6 ) ); 0422 cmd[10] = subChannel & 0x7; 0423 cmd[11] = 0; // Necessary to set the proper command length 0424 0425 if( cmd.transport( TR_DIR_READ, data, dataLen ) ) { 0426 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << ": READ CD failed!"; 0427 return false; 0428 } 0429 else { 0430 return true; 0431 } 0432 } 0433 0434 0435 bool K3b::Device::Device::readCdMsf( unsigned char* data, 0436 unsigned int dataLen, 0437 int sectorType, 0438 bool dap, 0439 const K3b::Msf& startAdress, 0440 const K3b::Msf& endAdress, 0441 bool sync, 0442 bool header, 0443 bool subHeader, 0444 bool userData, 0445 bool edcEcc, 0446 int c2, 0447 int subChannel ) const 0448 { 0449 ::memset( data, 0, dataLen ); 0450 0451 ScsiCommand cmd( this ); 0452 cmd[0] = MMC_READ_CD_MSF; 0453 cmd[1] = (sectorType<<2 & 0x1c) | ( dap ? 0x2 : 0x0 ); 0454 cmd[3] = (startAdress+150).minutes(); 0455 cmd[4] = (startAdress+150).seconds(); 0456 cmd[5] = (startAdress+150).frames(); 0457 cmd[6] = (endAdress+150).minutes(); 0458 cmd[7] = (endAdress+150).seconds(); 0459 cmd[8] = (endAdress+150).frames(); 0460 cmd[9] = ( ( sync ? 0x80 : 0x0 ) | 0461 ( subHeader ? 0x40 : 0x0 ) | 0462 ( header ? 0x20 : 0x0 ) | 0463 ( userData ? 0x10 : 0x0 ) | 0464 ( edcEcc ? 0x8 : 0x0 ) | 0465 ( c2<<1 & 0x6 ) ); 0466 cmd[10] = subChannel & 0x7; 0467 cmd[11] = 0; // Necessary to set the proper command length 0468 0469 if( cmd.transport( TR_DIR_READ, data, dataLen ) ) { 0470 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << ": READ CD MSF failed!"; 0471 return false; 0472 } 0473 else 0474 return true; 0475 } 0476 0477 0478 bool K3b::Device::Device::readSubChannel( UByteArray& data, 0479 unsigned int subchannelParam, 0480 unsigned int trackNumber ) const 0481 { 0482 unsigned char header[2048]; 0483 ::memset( header, 0, 2048 ); 0484 0485 ScsiCommand cmd( this ); 0486 cmd[0] = MMC_READ_SUB_CHANNEL; 0487 cmd[2] = 0x40; // SUBQ 0488 cmd[3] = subchannelParam; 0489 cmd[6] = trackNumber; // only used when subchannelParam == 03h (ISRC) 0490 cmd[8] = 4; 0491 cmd[9] = 0; // Necessary to set the proper command length 0492 0493 // first we read the header 0494 unsigned int dataLen = 4; 0495 if( cmd.transport( TR_DIR_READ, header, 4 ) == 0 ) 0496 dataLen = from2Byte( &header[2] ) + 4; 0497 else 0498 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << ": READ SUB-CHANNEL length det failed."; 0499 0500 // 0501 // Some buggy firmwares do not return the size of the available data 0502 // but the returned data. So we simply use the maximum possible value to be on the safe side 0503 // with these buggy drives. 0504 // We cannot use this as default since many firmwares fail with a too high data length. 0505 // 0506 if( dataLen <= 4 ) 0507 dataLen = 0xFFFF; 0508 0509 // again with real length 0510 data.resize( dataLen ); 0511 ::memset( data.data(), 0, data.size() ); 0512 0513 cmd[7] = data.size() >> 8; 0514 cmd[8] = data.size(); 0515 if( cmd.transport( TR_DIR_READ, data.data(), data.size() ) == 0 ) { 0516 data.resize( qMin( data.size(), from2Byte( &data[2] ) + 4 ) ); 0517 return true; 0518 } 0519 else { 0520 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << ": READ SUB-CHANNEL with real length " 0521 << data.size() << " failed." << Qt::endl; 0522 data.clear(); 0523 return false; 0524 } 0525 } 0526 0527 0528 bool K3b::Device::Device::readTocPmaAtip( UByteArray& data, int format, bool time, int track ) const 0529 { 0530 unsigned int descLen = 0; 0531 0532 switch( format ) { 0533 case 0x0: 0534 descLen = 8; 0535 break; 0536 case 0x1: 0537 descLen = 8; 0538 break; 0539 case 0x2: 0540 descLen = 11; 0541 break; 0542 case 0x3: 0543 descLen = 11; 0544 break; 0545 case 0x4: 0546 descLen = 4; // MMC2: 24 and MMC4: 28, so we use the highest common factor 0547 break; 0548 case 0x5: 0549 descLen = 18; 0550 break; 0551 } 0552 0553 unsigned char header[2048]; 0554 ::memset( header, 0, 2048 ); 0555 0556 ScsiCommand cmd( this ); 0557 cmd[0] = MMC_READ_TOC_PMA_ATIP; 0558 cmd[1] = ( time ? 0x2 : 0x0 ); 0559 cmd[2] = format & 0x0F; 0560 cmd[6] = track; 0561 cmd[8] = 4; 0562 cmd[9] = 0; // Necessary to set the proper command length 0563 0564 // we only read the header 0565 unsigned int dataLen = 4; 0566 if( cmd.transport( TR_DIR_READ, header, 4 ) == 0 ) 0567 dataLen = from2Byte( header ) + 2; 0568 else 0569 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << ": READ TOC/PMA/ATIP length det failed."; 0570 0571 // 0572 // Some buggy firmwares return an invalid size here 0573 // So we simply use the maximum possible value to be on the safe side 0574 // with these buggy drives. 0575 // We cannot use this as default since many firmwares fail with a too high data length. 0576 // 0577 if( descLen != 0 && ((dataLen-4) % descLen || dataLen < 4+descLen) ) { 0578 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << ": READ TOC/PMA/ATIP invalid length returned: " << dataLen; 0579 dataLen = 0xFFFF; 0580 } 0581 0582 // 0583 // Not all drives like uneven numbers 0584 // 0585 if( dataLen%2 ) 0586 ++dataLen; 0587 0588 // again with real length 0589 data.resize( dataLen ); 0590 ::memset( data.data(), 0, data.size() ); 0591 0592 cmd[7] = data.size() >> 8; 0593 cmd[8] = data.size(); 0594 if( cmd.transport( TR_DIR_READ, data.data(), data.size() ) == 0 ) { 0595 dataLen = qMin( dataLen, from2Byte( data.data() ) + 2u ); 0596 if( descLen == 0 || (dataLen-4) % descLen || dataLen < 4+descLen ) { 0597 // useless length 0598 data.clear(); 0599 return false; 0600 } 0601 else { 0602 data.resize( dataLen ); 0603 return true; 0604 } 0605 } 0606 else { 0607 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << ": READ TOC/PMA/ATIP format " 0608 << format << " with real length " 0609 << data.size() << " failed." << Qt::endl; 0610 data.clear(); 0611 return false; 0612 } 0613 } 0614 0615 0616 bool K3b::Device::Device::mechanismStatus( UByteArray& data ) const 0617 { 0618 unsigned char header[2048]; 0619 ::memset( header, 0, 2048 ); 0620 0621 ScsiCommand cmd( this ); 0622 cmd[0] = MMC_MECHANISM_STATUS; 0623 cmd[9] = 8; 0624 cmd[11] = 0; // Necessary to set the proper command length 0625 0626 // first we read the header 0627 unsigned int dataLen = 8; 0628 if( cmd.transport( TR_DIR_READ, header, 8 ) == 0 ) 0629 dataLen = from4Byte( &header[6] ) + 8; 0630 else 0631 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << ": MECHANISM STATUS length det failed."; 0632 0633 // 0634 // Some buggy firmwares do not return the size of the available data 0635 // but the returned data or something invalid altogether. 0636 // So we simply use the maximum possible value to be on the safe side 0637 // with these buggy drives. 0638 // We cannot use this as default since many firmwares fail with a too high data length. 0639 // 0640 if( (dataLen-8) % 4 || dataLen <= 8 ) 0641 dataLen = 0xFFFF; 0642 0643 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << ": MECHANISM STATUS " 0644 << (int)header[5] << " slots." << Qt::endl; 0645 0646 // again with real length 0647 data.resize( dataLen ); 0648 ::memset( data.data(), 0, data.size() ); 0649 0650 cmd[8] = data.size() >> 8; 0651 cmd[9] = data.size(); 0652 if( cmd.transport( TR_DIR_READ, data.data(), data.size() ) == 0 ) { 0653 data.resize( qMin( data.size(), (int)from4Byte( &data[6] ) + 8 ) ); 0654 return true; 0655 } 0656 else { 0657 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << ": MECHANISM STATUS with real length " 0658 << data.size() << " failed." << Qt::endl; 0659 data.clear(); 0660 return false; 0661 } 0662 } 0663 0664 0665 0666 bool K3b::Device::Device::modeSense(UByteArray& pageData, int page) const 0667 { 0668 unsigned char header[2048]; 0669 ::memset(header, 0, sizeof(header)); 0670 0671 ScsiCommand cmd(this); 0672 cmd[0] = MMC_MODE_SENSE; 0673 cmd[1] = 0x8; // Disable Block Descriptors 0674 cmd[2] = page & 0x3F; 0675 cmd[8] = 8; 0676 cmd[9] = 0; // Necessary to set the proper command length 0677 0678 // first we determine the data length 0679 int replyLen = 8; 0680 if (cmd.transport(TR_DIR_READ, header, 8) == 0) 0681 replyLen = from2Byte(header) + 2; 0682 else { 0683 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << 0684 ": MODE SENSE length det failed."; 0685 } 0686 // FIXME: rumor or misnomer? 0687 // Some buggy firmwares do not return the size of the available data 0688 // but the returned data. So we simply use the maximum possible value to be 0689 // on the safe side with these buggy drives. 0690 // We cannot use this as default since many firmwares fail with a too high 0691 // data length. 0692 if (replyLen == 8) 0693 replyLen = 0xFFFF; 0694 0695 // again with real length 0696 pageData.resize(replyLen); 0697 ::memset(pageData.data(), 0, pageData.size()); 0698 0699 cmd[7] = pageData.size() >> 8; 0700 cmd[8] = pageData.size(); 0701 if (cmd.transport(TR_DIR_READ, pageData.data(), pageData.size()) == 0 ) { 0702 pageData.resize(qMin(pageData.size(), from2Byte(pageData.data()) + 2)); 0703 return true; 0704 } else { 0705 pageData.clear(); 0706 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << 0707 ": MODE SENSE with real length " << replyLen << " failed." << Qt::endl; 0708 return false; 0709 } 0710 } 0711 0712 0713 bool K3b::Device::Device::modeSelect( UByteArray& pageData, bool pf, bool sp ) const 0714 { 0715 pageData[0] = 0; 0716 pageData[1] = 0; 0717 pageData[4] = 0; 0718 pageData[5] = 0; 0719 0720 // we do not support Block Descriptors here 0721 pageData[6] = 0; 0722 pageData[7] = 0; 0723 0724 // PS bit reserved 0725 pageData[8] &= 0x3F; 0726 0727 ScsiCommand cmd( this ); 0728 cmd[0] = MMC_MODE_SELECT; 0729 cmd[1] = ( sp ? 1 : 0 ) | ( pf ? 0x10 : 0 ); 0730 cmd[7] = pageData.size()>>8; 0731 cmd[8] = pageData.size(); 0732 cmd[9] = 0; 0733 return( cmd.transport( TR_DIR_WRITE, pageData.data(), pageData.size() ) == 0 ); 0734 } 0735 0736 0737 // does only make sense for complete media 0738 bool K3b::Device::Device::readCapacity( K3b::Msf& r ) const 0739 { 0740 ScsiCommand cmd( this ); 0741 cmd[0] = MMC_READ_CAPACITY; 0742 cmd[9] = 0; // Necessary to set the proper command length 0743 unsigned char buf[8]; 0744 ::memset( buf, 0, 8 ); 0745 if( cmd.transport( TR_DIR_READ, buf, 8 ) == 0 ) { 0746 r = from4Byte( buf ); 0747 return true; 0748 } 0749 else 0750 return false; 0751 } 0752 0753 0754 bool K3b::Device::Device::readFormatCapacity( int wantedFormat, K3b::Msf& r, 0755 K3b::Msf* currentMax, int* currentMaxFormat ) const 0756 { 0757 bool success = false; 0758 0759 // the maximal length as stated in MMC4 0760 static const unsigned int maxLen = 4 + (8*32); 0761 0762 unsigned char buffer[maxLen]; 0763 ::memset( buffer, 0, maxLen ); 0764 0765 ScsiCommand cmd( this ); 0766 cmd[0] = MMC_READ_FORMAT_CAPACITIES; 0767 cmd[7] = maxLen >> 8; 0768 cmd[8] = maxLen & 0xFF; 0769 cmd[9] = 0; // Necessary to set the proper command length 0770 if( cmd.transport( TR_DIR_READ, buffer, maxLen ) == 0 ) { 0771 0772 unsigned int realLength = buffer[3] + 4; 0773 0774 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << " READ FORMAT CAPACITY: Current/Max " 0775 << (int)(buffer[8]&0x3) << " " << from4Byte( &buffer[4] ) << Qt::endl; 0776 0777 if( currentMax ) 0778 *currentMax = from4Byte( &buffer[4] ); 0779 if( currentMaxFormat ) 0780 *currentMaxFormat = (int)(buffer[8]&0x3); 0781 0782 // 0783 // Descriptor Type: 0784 // 0 - reserved 0785 // 1 - unformatted :) 0786 // 2 - formatted. Here we get the used capacity (lead-in to last lead-out/border-out) 0787 // 3 - No media present 0788 // 0789 for( unsigned int i = 12; i < realLength-4; i+=8 ) { 0790 int format = (int)((buffer[i+4]>>2)&0x3f); 0791 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << " READ FORMAT CAPACITY: " 0792 << format << " " << from4Byte( &buffer[i] ) 0793 << " " << (int)( (buffer[i+5] << 16 & 0xFF0000) | 0794 (buffer[i+6] << 8 & 0xFF00) | 0795 (buffer[i+7] & 0xFF) ) << Qt::endl; 0796 0797 if( format == wantedFormat ) { 0798 // found the descriptor 0799 r = qMax( (int)from4Byte( &buffer[i] ), r.lba() ); 0800 success = true; 0801 } 0802 } 0803 } 0804 0805 return success; 0806 } 0807 0808 0809 bool K3b::Device::Device::readDiscInformation( UByteArray& data ) const 0810 { 0811 unsigned char header[2]; 0812 ::memset( header, 0, 2 ); 0813 0814 ScsiCommand cmd( this ); 0815 cmd[0] = MMC_READ_DISC_INFORMATION; 0816 cmd[8] = 2; 0817 cmd[9] = 0; // Necessary to set the proper command length 0818 0819 unsigned int dataLen = 0; 0820 if( cmd.transport( TR_DIR_READ, header, 2 ) == 0 ) 0821 dataLen = from2Byte( header ) + 2u; 0822 else 0823 qDebug() << "(K3b::Device::Device) " << blockDeviceName() 0824 << ": READ DISC INFORMATION length det failed" << Qt::endl; 0825 0826 if( dataLen < 32 ) { 0827 qDebug() << "(K3b::Device::Device) " << blockDeviceName() 0828 << ": Device reports bogus disc information length of " << dataLen << Qt::endl; 0829 dataLen = 32; 0830 } 0831 0832 data.resize( dataLen ); 0833 ::memset( data.data(), 0, data.size() ); 0834 0835 cmd[7] = data.size() >> 8; 0836 cmd[8] = data.size(); 0837 if( cmd.transport( TR_DIR_READ, data.data(), data.size() ) == 0 ) { 0838 data.resize( qMin( data.size(), from2Byte( data.data() ) + 2 ) ); 0839 return true; 0840 } 0841 else { 0842 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << ": READ DISC INFORMATION with real length " 0843 << dataLen << " failed." << Qt::endl; 0844 data.clear(); 0845 return false; 0846 } 0847 } 0848 0849 0850 bool K3b::Device::Device::readDvdStructure( UByteArray& data, 0851 unsigned int format, 0852 unsigned int layer, 0853 unsigned long address, 0854 unsigned int agid ) const 0855 { 0856 return readDiscStructure( data, 0x0, format, layer, address, agid ); 0857 } 0858 0859 0860 bool K3b::Device::Device::readDiscStructure( UByteArray& data, 0861 unsigned int mediaType, 0862 unsigned int format, 0863 unsigned int layer, 0864 unsigned long address, 0865 unsigned int agid ) const 0866 { 0867 unsigned char header[4]; 0868 ::memset( header, 0, 4 ); 0869 0870 ScsiCommand cmd( this ); 0871 cmd[0] = MMC_READ_DVD_STRUCTURE; 0872 cmd[1] = mediaType & 0xF; 0873 cmd[2] = address>>24; 0874 cmd[3] = address>>16; 0875 cmd[4] = address>>8; 0876 cmd[5] = address; 0877 cmd[6] = layer; 0878 cmd[7] = format; 0879 cmd[10] = (agid<<6); 0880 cmd[11] = 0; // Necessary to set the proper command length 0881 0882 cmd[9] = 4; 0883 if( cmd.transport( TR_DIR_READ, header, 4 ) == 0 ) { 0884 // again with real length 0885 unsigned int dataLen = from2Byte( header ) + 2; 0886 0887 data.resize( dataLen ); 0888 ::memset( data.data(), 0, data.size() ); 0889 0890 cmd[8] = data.size() >> 8; 0891 cmd[9] = data.size(); 0892 if( cmd.transport( TR_DIR_READ, data.data(), data.size() ) == 0 ) { 0893 data.resize( qMin( data.size(), from2Byte( data.data() ) + 2 ) ); 0894 return true; 0895 } 0896 else { 0897 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << ": READ DVD STRUCTURE with real length failed."; 0898 data.clear(); 0899 return false; 0900 } 0901 } 0902 else { 0903 qDebug() << "(K3b::Device::Device) " << blockDeviceName() << ": READ DVD STRUCTURE length det failed"; 0904 return false; 0905 } 0906 } 0907 0908 0909 int K3b::Device::Device::readBufferCapacity( long long& bufferLength, long long& bufferAvail ) const 0910 { 0911 unsigned char data[12]; 0912 ::memset( data, 0, 12 ); 0913 0914 ScsiCommand cmd( this ); 0915 cmd[0] = MMC_READ_BUFFER_CAPACITY; 0916 cmd[8] = 12; 0917 cmd[9] = 0; // Necessary to set the proper command length 0918 int r = cmd.transport( TR_DIR_READ, data, 12 ); 0919 if( r ) 0920 return r; 0921 0922 unsigned int dataLength = from2Byte( data ); 0923 0924 if( dataLength >= 10 ) { 0925 bufferLength = from4Byte( &data[4] ); 0926 bufferAvail = from4Byte( &data[8] ); 0927 } 0928 else { 0929 bufferAvail = bufferLength = 0; 0930 } 0931 0932 return 0; 0933 }