Re: [linux-minidisc] another way to send SCSI commands
Am Samstag, den 04.12.2010, 00:10 +0100 schrieb Michael Karcher:
> > 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.
The attached patch makes sending an INQUIRY command to the attached
Hi-MD walkman work. I did not test it with a CD drive yet (I might have
broken that, although I doubt it), as the current design has the problem
that it only works on drive with inserted media (as you specify the
device using /dev/rdiskN, and this device does not exist if no medium is
installed...) and the CD drive of the only Mac I have (remote) access to
is currently empty. I will add later a function that allows
specification of the IOKit device ID for attachment.
Regards,
Michael Karcher
--- transport.hxx.orig 2010-12-03 02:43:34.000000000 +0100
+++ transport.hxx 2010-12-05 01:50:29.000000000 +0100
@@ -1478,7 +1478,7 @@
io_object_t scsiob=IO_OBJECT_NULL,parent;
CFMutableDictionaryRef match,bsddev;
CFNumberRef num;
- int i;
+ int i,res;
if (ref) sb = *ref;
else if (stat(file,&sb)) return 0;
@@ -1511,32 +1511,51 @@
if ((scsiob = IOServiceGetMatchingService(kIOMasterPortDefault,match))
== IO_OBJECT_NULL) return !(errno=ENXIO);
- // traverse up to "SCSITaskAuthoringDevice"
+ // Find a plugin of type MMCDeviceUserClientType or
+ // SCSITaskDeviceUserClientType by traversing the tree upwards.
kern_return_t kret;
+ int found = 0;
+ CFStringRef mmctype = CFUUIDCreateString(kCFAllocatorDefault,
+ kIOMMCDeviceUserClientTypeID);
+ CFStringRef tasktype = CFUUIDCreateString(kCFAllocatorDefault,
+ kIOSCSITaskDeviceUserClientTypeID);
while ((kret=IORegistryEntryGetParentEntry(scsiob,kIOServicePlane,
- &parent)) == kIOReturnSuccess)
- { CFStringRef uclient;
- const char *s;
- int cmp;
+ &parent)) == kIOReturnSuccess && !found)
+ { CFDictionaryRef plugins;
IOObjectRelease(scsiob);
scsiob = parent;
- uclient = (CFStringRef)IORegistryEntryCreateCFProperty(scsiob,
- CFSTR(kIOPropertySCSITaskDeviceCategory),
+ plugins = (CFDictionaryRef)IORegistryEntryCreateCFProperty(scsiob,
+ CFSTR(kIOCFPlugInTypesKey),
kCFAllocatorDefault,0);
- if (uclient)
- { s = CFStringGetCStringPtr(uclient,kCFStringEncodingMacRoman);
- cmp = strcmp(s,kIOPropertySCSITaskAuthoringDevice);
- CFRelease(uclient);
- if (cmp==0) break;
+ if (plugins)
+ { if (CFDictionaryContainsKey(plugins,mmctype))
+ { res = attachViaMMC(scsiob);
+ found = 1;
+ }
+ if (CFDictionaryContainsKey(plugins,tasktype))
+ { res = attachViaSCSITask(scsiob);
+ found = 1;
+ }
+ CFRelease(plugins);
}
}
- if (kret!=kIOReturnSuccess)
+ CFRelease(tasktype);
+ CFRelease(mmctype);
+ if (!found)
{ if (scsiob!=IO_OBJECT_NULL) IOObjectRelease(scsiob);
return !(errno=ENXIO);
}
+ if (res)
+ { filename=strdup(file);
+ this->scsiob = scsiob;
+ }
+ return res;
+ }
- SInt32 score=0;
+private:
+ int attachViaMMC(io_object_t scsiob)
+ { SInt32 score=0;
if (IOCreatePlugInInterfaceForService(scsiob,
kIOMMCDeviceUserClientTypeID,
kIOCFPlugInInterfaceID,
@@ -1573,10 +1592,43 @@
return !(errno=EBUSY);
}
- filename=strdup(file);
+ return 1;
+ }
+
+ int attachViaSCSITask(io_object_t scsiob)
+ { SInt32 score=0;
+ if (IOCreatePlugInInterfaceForService(scsiob,
+ kIOSCSITaskDeviceUserClientTypeID,
+ kIOCFPlugInInterfaceID,
+ &plugin,&score) != kIOReturnSuccess)
+ { IOObjectRelease(scsiob);
+ return !(errno=ENXIO);
+ }
+ if ((*plugin)->QueryInterface(plugin,
+ CFUUIDGetUUIDBytes(kIOSCSITaskDeviceInterfaceID),
+ (void**)&taskif) != S_OK)
+ { IODestroyPlugInInterface(plugin), plugin=NULL;
+ IOObjectRelease(scsiob);
+ return !(errno=ENXIO);
+ }
+
+ //
+ // Note that in order to ObtainExclusiveAccess no corresponding
+ // /dev/[r]diskN may remain open by that time. For reference,
+ // acquiring exclusive access temporarily removes BSD block
+ // storage device from I/O registry as well as corresponding
+ // /dev entries.
+ //
+ if ((*taskif)->ObtainExclusiveAccess(taskif) != kIOReturnSuccess)
+ { (*taskif)->Release(taskif), taskif=NULL;
+ IODestroyPlugInInterface(plugin), plugin=NULL;
+ IOObjectRelease(scsiob), scsiob=IO_OBJECT_NULL;
+ return !(errno=EBUSY);
+ }
return 1;
}
+public:
unsigned char &operator[] (size_t i)
{ if (i==0)
{ memset (cdb,0,sizeof(cdb));