Bug 139985

Summary: k3b shows incorrect list of writing speeds for DVD on FreeBSD
Product: [Applications] k3b Reporter: Andriy Gapon <avg>
Component: Data ProjectAssignee: Sebastian Trueg <trueg>
Status: RESOLVED FIXED    
Severity: normal CC: tilman
Priority: NOR    
Version: unspecified   
Target Milestone: ---   
Platform: FreeBSD Ports   
OS: FreeBSD   
Latest Commit: Version Fixed In:

Description Andriy Gapon 2007-01-12 19:30:52 UTC
Version:           0.12.17 (using KDE KDE 3.5.5)
Installed from:    FreeBSD Ports
OS:                FreeBSD

k3b incorrectly determines writing speeds for DVDs on FreeBSD:
k3b: (K3bDevice::openDevice) open device /dev/pass0 succeeded.
k3b: (K3bDevice::ScsiCommand) transport command ac, length: 12
k3b: (K3bDevice::openDevice) open device /dev/pass0 succeeded.
k3b: (K3bDevice::ScsiCommand) transport command ac, length: 10
k3b: (K3bDevice::Device) /dev/cd0:  Number of supported write speeds via
GET PERFORMANCE: 7
k3b: (K3bDevice::Device) /dev/cd0 : 13854 KB/s
k3b: (K3bDevice::Device) /dev/cd0 Invalid DVD speed: 0 KB/s
k3b: (K3bDevice::Device) /dev/cd0 Invalid DVD speed: 0 KB/s
k3b: (K3bDevice::Device) /dev/cd0 Invalid DVD speed: 0 KB/s
k3b: (K3bDevice::Device) /dev/cd0 Invalid DVD speed: 0 KB/s
k3b: (K3bDevice::Device) /dev/cd0 Invalid DVD speed: 0 KB/s
k3b: (K3bDevice::Device) /dev/cd0 Invalid DVD speed: 0 KB/s

As you can see, the second 0xAC (GET PERFORMANCE) was sent as 10 byte command, but it should have been a 12 byte command. This behavior is a result of two things:

1. (real problem) libk3bdevice/k3bscsicommand_bsd.cpp:
unsigned char& K3bDevice::ScsiCommand::operator[]( size_t i )
{ 
  d->ccb.csio.cdb_len = i+1;
  return d->ccb.csio.cdb_io.cdb_bytes[i];
}

2. (trigger) libk3bdevice/k3bdevice_mmc.cpp:
K3bDevice::Device::getPerformance() first sends 0xAC command to query number of write speeds and then send the second command to get actual number. When sending the second command existing cmd object is reused and 2 command bytes are changed:

    int numDesc = (dataLen-8)/16;

    cmd[8] = numDesc>>8;
    cmd[9] = numDesc;

Because of the behavior of operator[] shown above, cdb_len of OS CAM command is set to 10.

Possible fixes:
1. the easiest: in K3bDevice::Device::getPerformance() set eleventh byte for both cmd executions.
2. the safest: change BSD implementation of K3bDevice::ScsiCommand::operator[] so that cdb_len can only be increased, e.g.:
    if (i+1 > d->ccb.csio.cdb_len)
        d->ccb.csio.cdb_len = i+1;
This way it would be safe to write things like:
cmd[1] = XX;
cmd[0] = YY;
Currently this wouldn't work as expected on FreeBSD.
Comment 1 Sebastian Trueg 2007-01-13 11:41:52 UTC
SVN commit 622839 by trueg:

Properly update the command length on BSD.

BUG: 139985


 M  +2 -1      k3bscsicommand_bsd.cpp  


--- trunk/extragear/multimedia/k3b/libk3bdevice/k3bscsicommand_bsd.cpp #622838:622839
@@ -56,7 +56,8 @@
 
 unsigned char& K3bDevice::ScsiCommand::operator[]( size_t i )
 {
-  d->ccb.csio.cdb_len = i+1;
+  if( d->ccb.csio.cdb_len < i+1 )
+    d->ccb.csio.cdb_len = i+1;
   return d->ccb.csio.cdb_io.cdb_bytes[i];
 }