Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 140 additions & 0 deletions examples/read_cd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#!/usr/bin/env python3

# SPDX-FileCopyrightText: 2021 The python-scsi Authors
#
# SPDX-License-Identifier: LGPL-2.1-or-later

# coding: utf-8

import sys

#from pyscsi.pyscsi import scsi_enum_readcd as READCD
from pyscsi.pyscsi.scsi import SCSI
from pyscsi.pyscsi.scsi_sense import SCSICheckCondition
from pyscsi.utils import init_device


def usage():
print('Usage: read_cd.py <device>')


def main():
i = 1
lba = 0
tl = 1
est = 0
dap = 0
mcsb = 0x02
c2ei = 0
scsb = 0
while i < len(sys.argv):
if sys.argv[i] == '--help':
return usage()
if sys.argv[i] == '-lba':
del sys.argv[i]
if sys.argv[i][:2] == '0x':
lba = int(sys.argv[i], 16)
else:
lba = int(sys.argv[i], 10)
del sys.argv[i]
continue
if sys.argv[i] == '-tl':
del sys.argv[i]
if sys.argv[i][:2] == '0x':
tl = int(sys.argv[i], 16)
else:
tl = int(sys.argv[i], 10)
del sys.argv[i]
continue
if sys.argv[i] == '-est':
del sys.argv[i]
est = int(sys.argv[i], 16)
del sys.argv[i]
continue
if sys.argv[i] == '-dap':
del sys.argv[i]
dap = int(sys.argv[i])
del sys.argv[i]
continue
if sys.argv[i] == '-mcsb':
del sys.argv[i]
mcsb = int(sys.argv[i], 16)
del sys.argv[i]
continue
if sys.argv[i] == '-c2ei':
del sys.argv[i]
c2ei = int(sys.argv[i], 16)
del sys.argv[i]
continue
if sys.argv[i] == '-scsb':
del sys.argv[i]
scsb = int(sys.argv[i], 16)
del sys.argv[i]
continue
i += 1

if len(sys.argv) < 2:
return usage()

device = init_device(sys.argv[1])

with SCSI(device) as s:

try:
s.testunitready()

cmd = s.readcd(lba, tl, est=est, dap=dap, mcsb=mcsb, c2ei=c2ei, scsb=scsb)
di = cmd.datain
for i in range(tl):
print('LBA 0x%08x' % (lba + i), '/', lba + i)
if mcsb & 0x10:
print('SYNC', di[:12].hex())
di = di[12:]
if mcsb & 0x04:
print('SECTOR HEADER', di[:4].hex())
di = di[4:]
if mcsb & 0x08:
if est != 4 and est != 5:
raise RuntimeError('Subheader data can only be requested from Mode 2 Form 1/2 sectors')

print('SECTOR SUB-HEADER', di[:8].hex())
di = di[8:]
if mcsb & 0x02:
ds = 0
if est == 2: # Mode 1
ds = 2048
if est == 3: # Mode 2 formless
ds = 2336
if est == 4: # Mode 2 form 1
ds = 2048
if est == 5: # Mode 2 form 2
ds = 2324
if ds == 0:
raise NotImplementedError('USER DATA requested but we can not determine the size of the data area')

print('USER DATA', di[:ds].hex())
di = di[ds:]
if mcsb & 0x01:
raise NotImplementedError('EDC&ECC')

if c2ei == 1: # C2 Errors Codes
print('C2 ERROR CODES', di[:294].hex())
di = di[294:]
if c2ei == 2: # C2 Errors Codes
print('C2 ERROR CODES', di[:296].hex())
di = di[296:]
if scsb == 2: # Formatted Q sub-channel data
print('SUB-CHANNEL', di[:16].hex())
di = di[16:]
if scsb == 4: # Corrected and de-interleaved R-W sub-channel data
print('SUB-CHANNEL', di[:96].hex())
di = di[96:]

except SCSICheckCondition as ex:
# if you want a print out of the sense data dict uncomment the next line
#ex.show_data = True
print(ex)


if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions pyscsi/pyscsi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
'scsi_cdb_read16',
'scsi_cdb_readcapacity16',
'scsi_cdb_readcapacity10',
'scsi_cdb_readcd',
'scsi_cdb_readelementstatus',
'scsi_cdb_report_luns',
'scsi_cdb_report_priority',
Expand Down
26 changes: 26 additions & 0 deletions pyscsi/pyscsi/scsi.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from pyscsi.pyscsi.scsi_cdb_read16 import Read16
from pyscsi.pyscsi.scsi_cdb_readcapacity10 import ReadCapacity10
from pyscsi.pyscsi.scsi_cdb_readcapacity16 import ReadCapacity16
from pyscsi.pyscsi.scsi_cdb_readcd import ReadCd
from pyscsi.pyscsi.scsi_cdb_readelementstatus import ReadElementStatus
from pyscsi.pyscsi.scsi_cdb_report_luns import ReportLuns
from pyscsi.pyscsi.scsi_cdb_report_priority import ReportPriority
Expand Down Expand Up @@ -477,6 +478,31 @@ def readcapacity16(self,
cmd.unmarshall()
return cmd

def readcd(self,
lba,
tl,
**kwargs):
"""
Returns a ReadCd Instance

:param lba: Logical Block Address
:param tl: Transfer Length
:param kwargs: a dict with key/value pairs
est=0: Expected Sector Type
dap=0: Digital Audio Play
mcsb=0: Main Channel Selection Bits
c2e1=0: C2 Error Information
scsb=0: Sub-Channel Selection Bits
:return: a ReadCd instance
"""
opcode = self.device.opcodes.READ_CD
cmd = ReadCd(opcode,
lba,
tl,
**kwargs)
self.execute(cmd)
return cmd

def readelementstatus(self,
start,
num,
Expand Down
66 changes: 66 additions & 0 deletions pyscsi/pyscsi/scsi_cdb_readcd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# coding: utf-8

# Copyright (C) 2021 by Ronnie Sahlberg<[email protected]>
# SPDX-FileCopyrightText: 2014 The python-scsi Authors
#
# SPDX-License-Identifier: LGPL-2.1-or-later

from pyscsi.pyscsi.scsi_command import SCSICommand
from pyscsi.utils.converter import decode_bits, encode_dict

#
# SCSI ReadCd command and definitions
#


class ReadCd(SCSICommand):
"""
A class to hold information from a ReadCd command to a scsi device
"""
_cdb_bits = {'opcode': [0xff, 0],
'est': [0x1c, 1],
'dap': [0x02, 1],
'lba': [0xffffffff, 2],
'tl': [0xffff, 6],
'mcsb': [0xf8, 9],
'c2ei': [0x06, 9],
'scsb': [0x07, 10],
}

def __init__(self,
opcode,
lba,
tl,
est=0,
dap=0,
mcsb=0,
c2ei=0,
scsb=0):
"""
initialize a new instance

:param opcode: a OpCode instance
:param lba: Logical Block Address
:param tl: transfer length
:param est=0: Expected Sector Type
:param dap=0: Digital Audio Play
:param mcsb=0: Main Channel Selection Bits
:param c2e1=0: C2 Error Information
:param scsb=0: Sub-Channel Selection Bits
"""

# dont bother to compute the exact allocation length needed, just use
# 3kb per lba
SCSICommand.__init__(self,
opcode,
0,
tl * 3072)

self.cdb = self.build_cdb(opcode=self.opcode.value,
lba=lba,
tl=tl,
est=est,
dap=dap,
mcsb=mcsb,
c2ei=c2ei,
scsb=scsb)