Am Freitag, den 03.12.2010, 23:04 +0100 schrieb Adrian Glaubitz: > we start doing any work on implementing it that way. It would be very > nice to be able to link dynamically to the tools on Linux, to keep the code > as clean and lean as possible. The whole implementation is currently inside a header file, so you can't avoid to to have it linked into your program. > As for MacOS X, I can give it a try on my Macbook and also on the > Mac Mini, I think that it shouldn't be so much of a big deal to > compile and run it. Unfortunately, I don't have any MiniDisc hardware > lying around in Norway to test, but I think I could use some USB > sticks or harddisks or even CDROM. Fortunately, the tools are > also easily installable through Macports [1]. Forget about USB sticks - I wasted enough time on that today. On Mac OS, you just can not send raw SCSI commands to USB sticks, even not with libscg. Mac OS prevents raw SCSI access to devices Mac OS has a driver for except under special circumstances. To send raw SCSI commands, you need to obtain a SCSITaskDeviceInterface for the device in question. If the device has no Mac OS driver at all, like e.g. SCSI tape drives, MacOS makes it possible to get this interface directly, by aquiring a "plugin" of the type SCSITaskDeviceUserClient and asking that for the SCSITaskDeviceInterface. The availability of this plugin is explicitly given by the property "SCSITaskDeviceCategory" that has the value "SCSITaskUserClientDevice". For CD writers, the CD authoring application also needs raw SCSI access, although Mac OS (of course) does have a CDROM driver, so the SCSITaskDeviceUserClient plugin is not available. But Mac OS helpfully adds another plug-in instead - it's the MMCDeviceUserClient plug-in. (MMC = Multimedia Commandset) This plug-in can be queried for a MMCDeviceInterface interface which then in turn can deliver a SCSITaskDeviceInterface. The availability of the MMCDeviceUserClient plugin is explicitly stated by the property "SCSITaskDeviceCategory" having the value "SCSITaskAuthoringDevice". Now, as we are lucky, Sony installs a driver for their Hi-MD recorders in Mac OS. The Sony driver re-adds the capability of sending raw SCSI commands to the USB mass storage disk device. It works like in the no-driver case by querying for a SCSITaskDeviceUserClient plug-in on the correct device object. The device class here is the "com_sony_driver_SonyMagicGateNub", which has th "SCSITaskDeviceCategory" property set to "SonyMagicGateUserClientDevice". This Sony-special string is not really what a general-purpose SCSI Library needs, but there is an easy workaround that doesn't need any sony specific stuff to support this kind of devices. Now the neat trick how to detect the Sony way of sending SCSI commands without special-casing it: There is a property called "IOCFPlugInTypes", which is a dictionary, whose keys are the GUIDs of the supported plugins. The Sony driver as well as the generic MacOS driver for non-supported SCSI device classes both list the SCSITaskDeviceUserClient UUID here: kIOSCSITaskDeviceUserClientTypeID = {7D66678E-08A2-11D5-A1B8-0030657D052A} while CD/DVD/BluRay drives list the MMCDeviceUserClient UUID here: kIOMMCDeviceUserClientTypeID = {97ABCF2C-23CC-11D5-A0E8-003065704866} So instead of what dvd+rw-tools does now (searching for SCSITaskDeviceInterface = SCSITaskAuthoringDevice), I suggest to instead search for the UUIDs in the IOCFPlugInTypes dictionary - and support both the indirect interface acquisition through the MMCDeviceInterface as well as the direct aquisition of a SCSITaskDeviceInterface (which will work on non-supported SCSI device classes and the Sony devices). > Thanks a lot for investigating into that. I would very glad if we can > drop libscg in favor of dvd+rw-tools. I did not yet implement the suggested change, but I am quite confident that it will work. I include ioreg dumps for a Hi-MD device and the internal DVD writer of a Mac Mini. Regards, Michael Karcher +-o Hi-MD@fd100000 <class IOUSBDevice, id 0x100001275, registered, matched, active, busy 0 (1357 ms), retain 8> | { | "idVendor" = 1356 | "IOUserClientClass" = "IOUSBDeviceUserClientV2" | "Device Speed" = 2 | "iSerialNumber" = 3 | "Requested Power" = 250 | "Bus Power Available" = 250 | "kHasMSCInterface" = Yes | "IOGeneralInterest" = "IOCommand is not serializable" | "bDeviceClass" = 0 | "USB Product Name" = "Hi-MD" | "bNumConfigurations" = 1 | "USB Serial Number" = "????????????" | "iManufacturer" = 1 | "USB Vendor Name" = "Sony" | "bcdDevice" = 256 | "bDeviceSubClass" = 0 | "IOCFPlugInTypes" = {"9dc7b780-9ec0-11d4-a54f-000a27052861"="IOUSBFamily.kext/Contents/PlugIns/IOUSBLib.bundle"} | "sessionID" = 1242052451452390 | "iProduct" = 2 | "bMaxPacketSize0" = 64 | "locationID" = 18446744073660268544 | "Low Power Displayed" = No | "uid" = "USB:054C0287????????????" | "idProduct" = 647 | "USB Address" = 6 | "bDeviceProtocol" = 0 | "PortNum" = 1 | } | +-o IOUSBCompositeDriver <class IOUSBCompositeDriver, id 0x100001277, !registered, !matched, active, busy 0, retain 4> | { | "IOProviderClass" = "IOUSBDevice" | "bDeviceClass" = 0 | "IOMatchCategory" = "IODefaultMatchCategory" | "IOProbeScore" = 50000 | "bDeviceSubClass" = 0 | "CFBundleIdentifier" = "com.apple.driver.AppleUSBComposite" | "IOClass" = "IOUSBCompositeDriver" | } | +-o IOUSBInterface@0 <class IOUSBInterface, id 0x100001278, registered, matched, active, busy 0 (1148 ms), retain 7> | { | "IOUserClientClass" = "IOUSBInterfaceUserClientV2" | "idProduct" = 647 | "IOCFPlugInTypes" = {"2d9786c6-9ef3-11d4-ad51-000a27052861"="IOUSBFamily.kext/Contents/PlugIns/IOUSBLib.bundle"} | "iInterface" = 0 | "bAlternateSetting" = 0 | "bConfigurationValue" = 1 | "bInterfaceProtocol" = 80 | "bInterfaceNumber" = 0 | "bInterfaceSubClass" = 5 | "idVendor" = 1356 | "bInterfaceClass" = 8 | "locationID" = 18446744073660268544 | "bNumEndpoints" = 2 | "bcdDevice" = 256 | } | +-o IOUSBMassStorageClass <class IOUSBMassStorageClass, id 0x10000127a, registered, matched, active, busy 0 (1053 ms), retain 8> | { | "Write Time Out Duration" = 30000 | "Read Time Out Duration" = 30000 | "IOUnit" = 6 | "Physical Interconnect Location" = "External" | "CFBundleIdentifier" = "com.apple.iokit.IOUSBMassStorageClass" | "IOClass" = "IOUSBMassStorageClass" | "Protocol Characteristics" = {"Physical Interconnect"="USB","Physical Interconnect Location"="External","Read Time Out Duration"=30000,"Write Time Out Duration"=30000} | "IOProbeScore" = 50000 | "IOMatchCategory" = "IODefaultMatchCategory" | "bInterfaceSubClass" = 5 | "Physical Interconnect" = "USB" | "bInterfaceClass" = 8 | "IOProviderClass" = "IOUSBInterface" | "IOPowerManagement" = {"CurrentPowerState"=1,"DevicePowerState"=1,"ChildrenPowerState"=1,"DriverPowerState"=1} | } | +-o IOSCSIPeripheralDeviceNub <class IOSCSIPeripheralDeviceNub, id 0x10000127c, registered, matched, active, busy 0 (946 ms), retain 6> | { | "IOProviderClass" = "IOSCSIProtocolServices" | "Protocol Characteristics" = {"Physical Interconnect"="USB","Physical Interconnect Location"="External","Read Time Out Duration"=30000,"Write Time Out Duration"=30000} | "IOMatchCategory" = "SCSITaskUserClientIniter" | "Product Revision Level" = "1000" | "IOProbeScore" = 0 | "Product Identification" = "Hi-MD WALKMAN" | "CFBundleIdentifier" = "com.apple.iokit.IOSCSIArchitectureModelFamily" | "Vendor Identification" = "SONY" | "IOClass" = "IOSCSIPeripheralDeviceNub" | "Peripheral Device Type" = 0 | } | +-o com_sony_driver_SonyMagicGate <class com_sony_driver_SonyMagicGate, id 0x10000127d, !registered, !matched, active, busy 0 (225 ms), retain 8> | { | "Vendor Identification" = "SONY" | "IOMaximumBlockCountWrite" = 64 | "Product Identification" = "Hi-MD WALKMAN" | "CFBundleIdentifier" = "com.sony.driver.SonyMagicGateDriver" | "IOClass" = "com_sony_driver_SonyMagicGate" | "Peripheral Device Type" = 0 | "IOMaximumByteCountWrite" = 131072 | "IOProbeScore" = 15000 | "IOMatchCategory" = "IODefaultMatchCategory" | "IOPowerManagement" = {"TimeSinceDeviceIdle"=15528947,"DevicePowerState"=0,"TimeSinceActivityTickle"=16129602,"ActivityTickles"=0,"DriverPowerState"=1,"CurrentPowerState"=1,"IdleTimerPeriod"=200000} | "IOMaximumBlockCountRead" = 64 | "IOProviderClass" = "IOSCSIPeripheralDeviceNub" | "IOMaximumByteCountRead" = 131072 | } | +-o com_sony_driver_SonyMagicGateNub <class com_sony_driver_SonyMagicGateNub, id 0x100001281, registered, matched, active, busy 0 (225 ms), retain 6> | { | "IOMaximumSegmentCountRead" = 32 | "IOUserClientClass" = "SCSITaskUserClient" | "IOMatchCategory" = "SCSITaskUserClientIniter" | "Protocol Characteristics" = {"Physical Interconnect"="USB","Physical Interconnect Location"="External","Read Time Out Duration"=30000,"Write Time Out Duration"=30000} | "IOCFPlugInTypes" = {"7D66678E-08A2-11D5-A1B8-0030657D052A"="IOSCSIArchitectureModelFamily.kext/Contents/PlugIns/SCSITaskUserClient.kext/Contents/PlugIns/SCSITaskLib.plugin"} | "SCSITaskDeviceCategory" = "SonyMagicGateUserClientDevice" | "Device Characteristics" = {"Product Revision Level"="1000","Vendor Name"="SONY","Product Name"="Hi-MD WALKMAN"} | "IOMaximumSegmentCountWrite" = 32 | "IOMinimumSegmentAlignmentByteCount" = 4 | "device-type" = "Generic" | "SCSITaskUserClient GUID" = <8025d30592da5522a4690400> | } | +-o IOBlockStorageDriver <class IOBlockStorageDriver, id 0x100001282, registered, matched, active, busy 0 (221 ms), retain 7> | | { | | "IOProviderClass" = "IOBlockStorageDevice" | | "IOMatchCategory" = "IODefaultMatchCategory" | | "IOProbeScore" = 0 | | "Statistics" = {"Errors (Read)"=0,"Total Time (Write)"=80503124126,"Latency Time (Read)"=0,"Latency Time (Write)"=0,"Bytes (Read)"=1271808,"Retries (Read)"=0,"Bytes (Write)"=2301952,"Errors (Write)"=0,"Retries (Write)"=0,"Operations (Read)"=119,"Operations (Write)"=177,"Total Time (Read)"=31003860906} | | "IOPropertyMatch" = {"device-type"="Generic"} | | "IOGeneralInterest" = "IOCommand is not serializable" | | "CFBundleIdentifier" = "com.apple.iokit.IOStorageFamily" | | "IOClass" = "IOBlockStorageDriver" | | } | | | +-o SONY Hi-MD WALKMAN Media <class IOMedia, id 0x100001284, registered, matched, active, busy 0 (218 ms), retain 8> | | { | | "Leaf" = Yes | | "Writable" = Yes | | "BSD Minor" = 3 | | "IOBusyInterest" = "IOCommand is not serializable" | | "IOGeneralInterest" = "IOCommand is not serializable" | | "Preferred Block Size" = 2048 | | "BSD Major" = 14 | | "BSD Name" = "disk1" | | "Size" = 1011759104 | | "Content Hint" = "" | | "IOMediaIcon" = {"CFBundleIdentifier"="com.apple.iokit.IOStorageFamily","IOBundleResourceFile"="Removable.icns"} | | "Removable" = Yes | | "Open" = No | | "BSD Unit" = 1 | | "Whole" = Yes | | "Content" = "" | | "Ejectable" = Yes | | } | | | +-o IOMediaBSDClient <class IOMediaBSDClient, id 0x100001285, registered, matched, active, busy 0 (3 ms), retain 5> | { | "IOResourceMatch" = "IOBSD" | "IOProbeScore" = 30000 | "IOMatchCategory" = "IOMediaBSDClient" | "CFBundleIdentifier" = "com.apple.iokit.IOStorageFamily" | "IOClass" = "IOMediaBSDClient" | "IOProviderClass" = "IOMedia" | } | +-o SCSITaskUserClientIniter <class SCSITaskUserClientIniter, id 0x100001283, !registered, !matched, active, busy 0, retain 4> { "IOProviderClass" = "com_sony_driver_SonyMagicGateNub" "IOMatchCategory" = "SCSITaskUserClientIniter" "IOProviderMergeProperties" = {"IOCFPlugInTypes"={"7D66678E-08A2-11D5-A1B8-0030657D052A"="IOSCSIArchitectureModelFamily.kext/Contents/PlugIns/SCSITaskUserClient.kext/Contents/PlugIns/SCSITaskLib.plugin"},"SCSITaskDeviceCategory"="SonyMagicGateUserClientDevice","IOUserClientClass"="SCSITaskUserClient"} "IOProbeScore" = 0 "CFBundleIdentifier" = "com.apple.iokit.SCSITaskUserClient" "IOPersonalityPublisher" = "com.sony.driver.SonyMagicGateDriver" "IOClass" = "SCSITaskUserClientIniter" } +-o ATADeviceNub@0 <class ATADeviceNub, id 0x1000001fa, registered, matched, active, busy 0 (4370 ms), retain 6> | { | "socket type" = "internal" | "device model" = "MATSHITADVD-R UJ-846 " | "IOUnit" = 0 | "IOMaximumSegmentCountRead" = 256 | "IOMaximumByteCountWrite" = 131072 | "device serial" = " " | "unit number" = 0 | "IOMaximumByteCountRead" = 131072 | "IOMaximumSegmentCountWrite" = 256 | "device revision" = "FM3J " | "ata device type" = "atapi" | } | +-o IOATAPIProtocolTransport <class IOATAPIProtocolTransport, id 0x100000203, registered, matched, active, busy 0 (4314 ms), retain 10> | { | "ata device type" = "atapi" | "Write Time Out Duration" = 15000 | "Read Time Out Duration" = 15000 | "Physical Interconnect Location" = "Internal" | "CFBundleIdentifier" = "com.apple.iokit.IOATAPIProtocolTransport" | "Retry Count" = 1 | "IOClass" = "IOATAPIProtocolTransport" | "Protocol Characteristics" = {"unit number"=0} | "IOProbeScore" = 0 | "IOMatchCategory" = "IODefaultMatchCategory" | "Physical Interconnect" = "ATAPI" | "IOPowerManagement" = {"CurrentPowerState"=1,"DevicePowerState"=1,"ChildrenPowerState"=1,"DriverPowerState"=1} | "IOProviderClass" = "IOATADevice" | } | +-o IOSCSIPeripheralDeviceNub <class IOSCSIPeripheralDeviceNub, id 0x100000210, registered, matched, active, busy 0 (4209 ms), retain 6> | { | "IOProviderClass" = "IOSCSIProtocolServices" | "Protocol Characteristics" = {"unit number"=0,"Physical Interconnect"="ATAPI","Retry Count"=1,"Physical Interconnect Location"="Internal","Read Time Out Duration"=15000,"Write Time Out Duration"=15000} | "IOMatchCategory" = "SCSITaskUserClientIniter" | "Product Revision Level" = "FM3J" | "IOProbeScore" = 0 | "Product Identification" = "DVD-R UJ-846" | "CFBundleIdentifier" = "com.apple.iokit.IOSCSIArchitectureModelFamily" | "Vendor Identification" = "MATSHITA" | "IOClass" = "IOSCSIPeripheralDeviceNub" | "Peripheral Device Type" = 5 | } | +-o IOSCSIPeripheralDeviceType05 <class IOSCSIPeripheralDeviceType05, id 0x100000219, !registered, !matched, active, busy 0 (4090 ms), retain 6> | { | "IOMaximumBlockCountWrite" = 65535 | "CFBundleIdentifier" = "com.apple.iokit.IOSCSIMultimediaCommandsDevice" | "DVD Features" = 503 | "IOClass" = "IOSCSIPeripheralDeviceType05" | "Peripheral Device Type" = 5 | "IOProbeScore" = 5000 | "IOMatchCategory" = "IODefaultMatchCategory" | "CD Features" = 1791 | "IOPowerManagement" = {"TimeSinceDeviceIdle"=31721007,"DevicePowerState"=0,"TimeSinceActivityTickle"=32521010,"ActivityTickles"=0,"DriverPowerState"=1,"CurrentPowerState"=1,"IdleTimerPeriod"=200000} | "IOMaximumBlockCountRead" = 65535 | "IOProviderClass" = "IOSCSIPeripheralDeviceNub" | "BD Features" = 0 | } | +-o IODVDServices <class IODVDServices, id 0x10000021f, registered, matched, active, busy 0 (4090 ms), retain 6> | { | "IOUserClientClass" = "SCSITaskUserClient" | "SCSITaskDeviceCategory" = "SCSITaskAuthoringDevice" | "IOMatchCategory" = "SCSITaskUserClientIniter" | "Protocol Characteristics" = {"unit number"=0,"Physical Interconnect"="ATAPI","Retry Count"=1,"Physical Interconnect Location"="Internal","Read Time Out Duration"=15000,"Write Time Out Duration"=15000} | "IOCFPlugInTypes" = {"97ABCF2C-23CC-11D5-A0E8-003065704866"="IOSCSIArchitectureModelFamily.kext/Contents/PlugIns/SCSITaskUserClient.kext/Contents/PlugIns/SCSITaskLib.plugin"} | "IOGeneralInterest" = "IOCommand is not serializable" | "Device Characteristics" = {"Loading Mechanism"="Slot","BD Features"=0,"Product Name"="DVD-R UJ-846","Product Revision Level"="FM3J","DVD Features"=503,"Async Notification"=No,"Vendor Name"="MATSHITA","Fast Spindown"=No,"Power Off"=No,"Low Power Polling"=Yes,"CD Features"=1791} | "IOMinimumSegmentAlignmentByteCount" = 4 | "device-type" = "DVD" | "SCSITaskUserClient GUID" = <8038680470ad544200000000> | } | +-o IODVDBlockStorageDriver <class IODVDBlockStorageDriver, id 0x100000220, registered, matched, active, busy 0 (4087 ms), retain 6> | { | "IOProviderClass" = "IODVDBlockStorageDevice" | "IOMatchCategory" = "IODefaultMatchCategory" | "IOProbeScore" = 0 | "Statistics" = {"Errors (Read)"=4,"Total Time (Write)"=0,"Latency Time (Read)"=0,"Latency Time (Write)"=0,"Bytes (Read)"=231808,"Retries (Read)"=0,"Bytes (Write)"=0,"Errors (Write)"=0,"Retries (Write)"=0,"Operations (Read)"=116,"Operations (Write)"=0,"Total Time (Read)"=12148222507} | "IOPropertyMatch" = {"device-type"="DVD"} | "IOGeneralInterest" = "IOCommand is not serializable" | "CFBundleIdentifier" = "com.apple.iokit.IODVDStorageFamily" | "IOClass" = "IODVDBlockStorageDriver" | } | +-o SCSITaskUserClientIniter <class SCSITaskUserClientIniter, id 0x100000221, !registered, !matched, active, busy 0, retain 4> { "IOMatchCategory" = "SCSITaskUserClientIniter" "IOProviderMergeProperties" = {"IOCFPlugInTypes"={"97ABCF2C-23CC-11D5-A0E8-003065704866"="IOSCSIArchitectureModelFamily.kext/Contents/PlugIns/SCSITaskUserClient.kext/Contents/PlugIns/SCSITaskLib.plugin"},"SCSITaskDeviceCategory"="SCSITaskAuthoringDevice","IOUserClientClass"="SCSITaskUserClient"} "CFBundleIdentifier" = "com.apple.iokit.SCSITaskUserClient" "IOProbeScore" = 0 "IOClass" = "SCSITaskUserClientIniter" "IOProviderClass" = "IODVDServices" }