예제 #1
0
static IOReturn Feedback360Probe(void *that,CFDictionaryRef propertyTable,io_service_t service,SInt32 *order)
{
    if ((service==0)
     || ((!IOObjectConformsTo(service,"Xbox360ControllerClass"))
     && (!IOObjectConformsTo(service,"Wireless360Controller")))) return kIOReturnBadArgument;
    return S_OK;
}
static CFStringRef BSDNameForBlockStorageDevice( io_registry_entry_t service )
{
    // This should be an IOBlockStorageDevice. It'll have one child, an IOBlockStorageDriver,
    // which will have one child of its own, an IOMedia. We get the BSD name from the IOMedia.

    static CFStringRef kUnknownDiskBSDName = CFSTR("disk[??]");
    kern_return_t kr = KERN_SUCCESS;

    io_registry_entry_t driver = MACH_PORT_NULL;
    kr = IORegistryEntryGetChildEntry( service, kIOServicePlane, &driver );
    if ( driver == MACH_PORT_NULL )
        return ( kUnknownDiskBSDName );

    if ( IOObjectConformsTo(driver, kIOBlockStorageDriverClass) == FALSE )
        return ( kUnknownDiskBSDName );

    io_registry_entry_t media = MACH_PORT_NULL;
    kr = IORegistryEntryGetChildEntry( driver, kIOServicePlane, &media );
    IOObjectRelease( driver );
    if ( media == MACH_PORT_NULL )
        return ( kUnknownDiskBSDName );

    if ( IOObjectConformsTo(media, kIOMediaClass) == FALSE )
        return ( kUnknownDiskBSDName );

    CFStringRef str = IORegistryEntryCreateCFProperty( media, CFSTR("BSD Name"), NULL, 0 );
    if ( str == NULL )
        str = kUnknownDiskBSDName;

    IOObjectRelease( media );
    return ( str );
}
예제 #3
0
/*
 * Given disk2s1, look up "disk2" is IOKit and attempt to determine if
 * it is an optical device.
 */
int is_optical_media(const char *bsdname)
{
	CFMutableDictionaryRef matchingDict;
	int ret = 0;
	io_service_t service, start;
    kern_return_t   kernResult;
    io_iterator_t   iter;

	if ((matchingDict = IOBSDNameMatching(kIOMasterPortDefault, 0, bsdname))  == NULL)
        return(0);

	start = IOServiceGetMatchingService(kIOMasterPortDefault, matchingDict);
	if (IO_OBJECT_NULL == start)
		return (0);

	service = start;

	// Create an iterator across all parents of the service object passed in.
	// since only disk2 would match with ConfirmsTo, and not disk2s1, so
    // we search the parents until we find "Whole", ie, disk2.
	kernResult = IORegistryEntryCreateIterator(service,
                       kIOServicePlane,
                       kIORegistryIterateRecursively | kIORegistryIterateParents,
                       &iter);

	if (KERN_SUCCESS == kernResult) {
        Boolean isWholeMedia = false;
        IOObjectRetain(service);
        do {

			// Lookup "Whole" if we can
			if (IOObjectConformsTo(service, kIOMediaClass)) {
				CFTypeRef wholeMedia;
				wholeMedia = IORegistryEntryCreateCFProperty(service,
													 CFSTR(kIOMediaWholeKey),
                                                     kCFAllocatorDefault,
                                                     0);
				if (wholeMedia) {
					isWholeMedia = CFBooleanGetValue(wholeMedia);
					CFRelease(wholeMedia);
				}
			}

			// If we found "Whole", check the service type.
			if (isWholeMedia &&
				( (IOObjectConformsTo(service, kIOCDMediaClass)) ||
				  (IOObjectConformsTo(service, kIODVDMediaClass)) )) {
				ret = 1; // Is optical, skip
			}

            IOObjectRelease(service);
        } while ((service = IOIteratorNext(iter)) && !isWholeMedia);
        IOObjectRelease(iter);
	}

	IOObjectRelease(start);
	return ret;
}
예제 #4
0
// returns a solid type from an entry and its properties
static Solid::DeviceInterface::Type typeFromEntry(const io_registry_entry_t &entry,
        const QMap<QString, QVariant> &properties)
{
    if (IOObjectConformsTo(entry, "AppleACPICPU")) {
        return Solid::DeviceInterface::Processor;
    }
    if (IOObjectConformsTo(entry, "AppleSmartBattery")) {
        return Solid::DeviceInterface::Battery;
    }

    return Solid::DeviceInterface::Unknown;
}
예제 #5
0
static int darwinIsMountedDisc(char *bsdName, mach_port_t masterPort)
{
    int retval = 0;
    CFMutableDictionaryRef matchingDict;
    kern_return_t rc;
    io_iterator_t iter;
    io_service_t service;

    if ((matchingDict = IOBSDNameMatching(masterPort, 0, bsdName)) == NULL)
        return(0);

    rc = IOServiceGetMatchingServices(masterPort, matchingDict, &iter);
    if ((rc != KERN_SUCCESS) || (!iter))
        return(0);

    service = IOIteratorNext(iter);
    IOObjectRelease(iter);
    if (!service)
        return(0);

    rc = IORegistryEntryCreateIterator(service, kIOServicePlane,
             kIORegistryIterateRecursively | kIORegistryIterateParents, &iter);
    
    if (!iter)
        return(0);

    if (rc != KERN_SUCCESS)
    {
        IOObjectRelease(iter);
        return(0);
    } /* if */

    IOObjectRetain(service);  /* add an extra object reference... */

    do
    {
        if (darwinIsWholeMedia(service))
        {
            if ( (IOObjectConformsTo(service, kIOCDMediaClass)) ||
                 (IOObjectConformsTo(service, kIODVDMediaClass)) )
            {
                retval = 1;
            } /* if */
        } /* if */
        IOObjectRelease(service);
    } while ((service = IOIteratorNext(iter)) && (!retval));
                
    IOObjectRelease(iter);
    IOObjectRelease(service);

    return(retval);
} /* darwinIsMountedDisc */
예제 #6
0
// returns a solid type from an entry and its properties
static Solid::DeviceInterface::Type typeFromEntry(const io_registry_entry_t &entry,
        const QMap<QString, QVariant> &properties)
{
    if (IOObjectConformsTo(entry, kIOEthernetInterfaceClass))
        return Solid::DeviceInterface::NetworkInterface;
    if (IOObjectConformsTo(entry, "AppleACPICPU"))
        return Solid::DeviceInterface::Processor;
    if (IOObjectConformsTo(entry, "IOSerialBSDClient"))
        return Solid::DeviceInterface::SerialInterface;
    if (IOObjectConformsTo(entry, "AppleSmartBattery"))
        return Solid::DeviceInterface::Battery;

    return Solid::DeviceInterface::Unknown;
}
예제 #7
0
uint16_t OSX_ProbeTargetDrive(const char* id3args_drive, char* mcdi_data) {
	uint16_t mcdi_data_len = 0;
	io_object_t	cdobject = MACH_PORT_NULL;
	
	if (strncmp(id3args_drive, "disk", 4) != 0) {
		OSX_ScanForCDDrive();
		exit(0);
	}
	cdobject = IOServiceGetMatchingService(kIOMasterPortDefault, IOBSDNameMatching (kIOMasterPortDefault, 0, id3args_drive) );

	if (cdobject == MACH_PORT_NULL) {
		fprintf(stdout, "No device found at %s; searching for possible drives...\n", id3args_drive);
		OSX_ScanForCDDrive();
		
	} else if (IOObjectConformsTo(cdobject, kIOCDMediaClass) == false) {
		fprintf (stdout, "No cd present in drive at %s\n", id3args_drive );
		IOObjectRelease(cdobject);
		cdobject = MACH_PORT_NULL;
		OSX_ScanForCDDrive();
	} else {
		//we now have a cd object
		OSX_ReadCDTOC(cdobject);
		if (cdTOC != NULL) {
			uint8_t cdType = DetermineCDType(cdTOC);
			if (cdType == CDOBJECT_AUDIOCD) {
				mcdi_data_len = FormMCDIdata(mcdi_data);
			}
		}
	}

	IOObjectRelease(cdobject);
	cdobject = MACH_PORT_NULL;
	return mcdi_data_len;
}
예제 #8
0
static io_service_t GetUsbDevice(io_service_t service) {
  IOReturn status;
  io_iterator_t   iterator = 0;
  io_service_t    device = 0;

  if (!service) {
    return device;
  }

  status = IORegistryEntryCreateIterator(service,
                                         kIOServicePlane,
                                         (kIORegistryIterateParents | kIORegistryIterateRecursively),
                                         &iterator);

  if (status == kIOReturnSuccess) {
    io_service_t currentService;
    while ((currentService = IOIteratorNext(iterator)) && device == 0) {
      io_name_t serviceName;
      status = IORegistryEntryGetNameInPlane(currentService, kIOServicePlane, serviceName);
      if (status == kIOReturnSuccess && IOObjectConformsTo(currentService, kIOUSBDeviceClassName)) {
        device = currentService;
      } else {
        // Release the service object which is no longer needed
        (void) IOObjectRelease(currentService);
      }
    }

    // Release the iterator
    (void) IOObjectRelease(iterator);
  }

  return device;
}
예제 #9
0
파일: iostat.c 프로젝트: PaxGordon/SEDarwin
/*
 * Try to record the named device as interesting.  It
 * must be an IOMedia device.
 */
static int
record_one_device(char *name)
{
    io_iterator_t drivelist;
    io_registry_entry_t drive;
    kern_return_t status;

    /*
     * Find the device.
     */
    status = IOServiceGetMatchingServices(masterPort,
                                          IOBSDNameMatching(masterPort, kNilOptions, name),
                                          &drivelist);
    if (status != KERN_SUCCESS)
        errx(1, "couldn't match '%s'", name);

    /*
     * Get the first match (should only be one)
     */
    if ((drive = IOIteratorNext(drivelist)) == NULL)
        errx(1, "'%s' not found", name);
    if (!IOObjectConformsTo(drive, "IOMedia"))
        errx(1, "'%s' is not a storage device", name);

    /*
     * Record the device.
     */
    if (record_device(drive))
        errx(1, "could not record '%s' for monitoring", name);

    IOObjectRelease(drive);
    IOObjectRelease(drivelist);

    return(0);
}
예제 #10
0
IOKitDevice::IOKitDevice(const io_service_t& hService_)
:
   usBusNumber(0),
	usAddress(0),
	usConfigurationNum(0),
   ulSerialNumber(0),
	ulLocation(0),
   hSavedService(NULL)
{
   UCHAR ucSerialIndex = 0;
   
   szProductDescription[0] = '\0';
   szSerialString[0] = '\0';
	memset(&stDeviceDescriptor, 0, sizeof(stDeviceDescriptor));  //!! Can initialize in stDeviceDescriptor constructor instead
	memset(szSystemPath, 0, sizeof(szSystemPath));

   if(hService_ == 0)
      throw IOKitError::INVALID_PARAM;

   if(!IOObjectConformsTo(hService_, "IOUSBDevice"))
      throw IOKitError::INVALID_PARAM;
      
   IOObjectRetain(hService_);
   hSavedService = hService_;
   
   
   //IOKitError::Enum eReturn;
   
   
   
   //!!eReturn = IOKitDevice::GetNewDescriptor(ppstDeviceInterface, stDeviceDescriptor);
   //if(eReturn != IOKitError::SUCCESS)
   //   throw eReturn;
   
   IOKitDevice::GetDeviceString(hService_, CFSTR("USB Product Name"), (UCHAR*)szProductDescription, sizeof(szProductDescription));  //could also use "Product Name" (with a search) to get from drivers

   usVid = IOKitDevice::GetDeviceNumber(hService_, CFSTR("idVendor"));
   usPid = IOKitDevice::GetDeviceNumber(hService_, CFSTR("idProduct"));
   usConfigurationNum = IOKitDevice::GetDeviceNumber(hService_, CFSTR("bNumConfigurations"));
   ulLocation = IOKitDevice::GetDeviceNumber(hService_, CFSTR("locationID"));
   usAddress = IOKitDevice::GetDeviceNumber(hService_, CFSTR("USB Address"));
   usBusNumber = ulLocation >> 24;
   
   UCHAR bDeviceClass = IOKitDevice::GetDeviceNumber(hService_, CFSTR("bDeviceClass"));
   UCHAR bDeviceSubClass = IOKitDevice::GetDeviceNumber(hService_, CFSTR("bDeviceSubClass"));

   ulSerialNumber = IOKitDevice::GetSerialNumber(hService_, (UCHAR*) szSerialString, sizeof(szSerialString), ucSerialIndex);
   stDeviceDescriptor.iSerialNumber = (UInt8)ucSerialIndex;  //update descriptor with serial string index

   SNPRINTF(szSystemPath, sizeof(szSystemPath), "%03i-%04x-%04x-%02x-%02x", usAddress, usVid, usPid, bDeviceClass, bDeviceSubClass);
      
   //!!eReturn = CheckDeviceSanity();
   //if(eReturn != IOKitError::SUCCESS)
   //   throw eReturn;
	
   return;
}
예제 #11
0
IOReturn IOFireWireSBP2LibLUN::probe( CFDictionaryRef propertyTable,
                                      io_service_t service, SInt32 *order )
{
    // only load against LUN's
    if( !service || !IOObjectConformsTo(service, "IOFireWireSBP2LUN") )
        return kIOReturnBadArgument;

    return kIOReturnSuccess;
}
	IOReturn
	IOCFPlugIn::Probe( CFDictionaryRef propertyTable, io_service_t service, SInt32 *order )
	{	
		// only load against firewire nubs
		if( !service || !IOObjectConformsTo(service, "IOFireWireNub") )
			return kIOReturnBadArgument;
		
		return kIOReturnSuccess;
	}
예제 #13
0
Boolean IsWholeMedia(io_service_t service)
{
  //
  // Determine if the object passed in represents an IOMedia (or subclass) object.
  // If it does, retrieve the "Whole" property.
  // If this is the whole media object, find out if it is a CD, DVD, or something else.
  // If it isn't the whole media object, iterate across its parents in the IORegistry
  // until the whole media object is found.
  //
  // Note that media types other than CD and DVD are not distinguished by class name
  // but are generic IOMedia objects.
  //

  Boolean isWholeMedia = false;
  io_name_t className;
  kern_return_t kernResult;

  if (IOObjectConformsTo(service, kIOMediaClass)) {

    CFTypeRef wholeMedia;

    wholeMedia = IORegistryEntryCreateCFProperty(service, CFSTR(kIOMediaWholeKey), kCFAllocatorDefault, 0);

    if (NULL == wholeMedia) {
      printf("Could not retrieve Whole property\n");
    } else {
      isWholeMedia = CFBooleanGetValue(wholeMedia);
      CFRelease(wholeMedia);
    }
  }

  if (isWholeMedia) {
    if (IOObjectConformsTo(service, kIOCDMediaClass)) {
      printf("is a CD\n");
    } else if (IOObjectConformsTo(service, kIODVDMediaClass)) {
      printf("is a DVD\n");
    } else {
      kernResult = IOObjectGetClass(service, className);
      printf("is of class %s\n", className);
    }
  }

  return isWholeMedia;
}
예제 #14
0
파일: diskio.c 프로젝트: pexip/os-net-snmp
/*
 * Check whether an IORegistryEntry refers to a valid
 * I/O device, and if so, collect the information.
 */
static int
handle_drive(io_registry_entry_t drive, struct drivestats * dstat)
{
    io_registry_entry_t parent;
    CFMutableDictionaryRef     properties;
    CFStringRef         name;
    CFNumberRef         number;
    kern_return_t       status;

    /* get drive's parent */
    status = IORegistryEntryGetParentEntry(drive, kIOServicePlane, &parent);
    if (status != KERN_SUCCESS) {
	snmp_log(LOG_ERR, "diskio: device has no parent\n");
/*	fprintf(stderr, "device has no parent\n"); */
	return(1);
    }

    if (IOObjectConformsTo(parent, "IOBlockStorageDriver")) {

	/* get drive properties */
	status = IORegistryEntryCreateCFProperties(drive, &properties,
					    kCFAllocatorDefault, kNilOptions);
	if (status != KERN_SUCCESS) {
	    snmp_log(LOG_ERR, "diskio: device has no properties\n");
/*	    fprintf(stderr, "device has no properties\n"); */
	    return(1);
	}

	/* get BSD name and unitnumber from properties */
	name = (CFStringRef)CFDictionaryGetValue(properties,
					  CFSTR(kIOBSDNameKey));
	number = (CFNumberRef)CFDictionaryGetValue(properties,
					    CFSTR(kIOBSDUnitKey));

	/* Collect stats and if succesful store them with the name and unitnumber */
	if (name && number && !collect_drive_stats(parent, dstat->stats)) {

	    CFStringGetCString(name, dstat->name, MAXDRIVENAME, CFStringGetSystemEncoding());
	    CFNumberGetValue(number, kCFNumberSInt32Type, &dstat->bsd_unit_number);
	    num_drives++;
	}

	/* clean up, return success */
	CFRelease(properties);
	return(0);
    }

    /* failed, don't keep parent */
    IOObjectRelease(parent);
    return(1);
}
예제 #15
0
파일: disk.c 프로젝트: goodwinos/pcp
static int
update_disk(diskstats_t *stats, io_registry_entry_t drive, int index)
{
    io_registry_entry_t		device;
    CFDictionaryRef		pproperties, properties;
    int				status;

    /* Get the drives parent, from which we get statistics. */
    status = IORegistryEntryGetParentEntry(drive, kIOServicePlane, &device);
    if (status != KERN_SUCCESS)
	return -oserror();

    if (!IOObjectConformsTo(device, "IOBlockStorageDriver")) {
	IOObjectRelease(device);
	return 0;
    }

    /* Obtain the drive properties. */
    pproperties = 0;
    status = IORegistryEntryCreateCFProperties(drive,
			(CFMutableDictionaryRef *)&pproperties,
			kCFAllocatorDefault, kNilOptions);
    if (status != KERN_SUCCESS) {
	IOObjectRelease(device);
	return -oserror();
    }

    /* Obtain the device properties. */
    properties = 0;
    status = IORegistryEntryCreateCFProperties(device,
			(CFMutableDictionaryRef *)&properties,
			kCFAllocatorDefault, kNilOptions);
    if (status != KERN_SUCCESS) {
	IOObjectRelease(device);
	return -oserror();
    }

    /* Make space to store the actual values, then go get them. */
    status = check_stats_size(stats, index + 1);
    if (status < 0) {
	IOObjectRelease(device);
    } else {
	update_disk_stats(&stats->disks[index], pproperties, properties);
	update_disk_totals(stats, &stats->disks[index]);
    }
    CFRelease(pproperties);
    CFRelease(properties);
    return status;
}
예제 #16
0
파일: iostat.c 프로젝트: PaxGordon/SEDarwin
/*
 * Determine whether an IORegistryEntry refers to a valid
 * I/O device, and if so, record it.
 */
static int
record_device(io_registry_entry_t drive)
{
    io_registry_entry_t parent;
    CFDictionaryRef properties;
    CFStringRef name;
    CFNumberRef number;
    kern_return_t status;

    /* get drive's parent */
    status = IORegistryEntryGetParentEntry(drive,
                                           kIOServicePlane, &parent);
    if (status != KERN_SUCCESS)
        errx(1, "device has no parent");
    if (IOObjectConformsTo(parent, "IOBlockStorageDriver")) {
        drivestat[num_devices].driver = parent;

        /* get drive properties */
        status = IORegistryEntryCreateCFProperties(drive,
                 (CFMutableDictionaryRef *)&properties,
                 kCFAllocatorDefault,
                 kNilOptions);
        if (status != KERN_SUCCESS)
            errx(1, "device has no properties");

        /* get name from properties */
        name = (CFStringRef)CFDictionaryGetValue(properties,
                CFSTR(kIOBSDNameKey));
        CFStringGetCString(name, drivestat[num_devices].name,
                           MAXDRIVENAME, CFStringGetSystemEncoding());

        /* get blocksize from properties */
        number = (CFNumberRef)CFDictionaryGetValue(properties,
                 CFSTR(kIOMediaPreferredBlockSizeKey));
        CFNumberGetValue(number, kCFNumberSInt64Type,
                         &drivestat[num_devices].blocksize);

        /* clean up, return success */
        CFRelease(properties);
        num_devices++;
        return(0);
    }

    /* failed, don't keep parent */
    IOObjectRelease(parent);
    return(1);
}
예제 #17
0
static int darwinIsWholeMedia(io_service_t service)
{
    int retval = 0;
    CFTypeRef wholeMedia;

    if (!IOObjectConformsTo(service, kIOMediaClass))
        return(0);
        
    wholeMedia = IORegistryEntryCreateCFProperty(service,
                                                 CFSTR(kIOMediaWholeKey),
                                                 kCFAllocatorDefault, 0);
    if (wholeMedia == NULL)
        return(0);

    retval = CFBooleanGetValue(wholeMedia);
    CFRelease(wholeMedia);

    return retval;
} /* darwinIsWholeMedia */
예제 #18
0
파일: rltkRegs.c 프로젝트: OTiZ/osx
io_object_t getInterfaceWithName( mach_port_t masterPort, char *className )
{
    io_iterator_t	ite;
    io_object_t		obj = 0;
    io_name_t		name;
    kern_return_t	rc;
    kern_return_t	kr;


    kr = IORegistryCreateIterator(	masterPort,
                                    kIOServicePlane,
                                    true,					/* recursive */
                                    &ite );
    if ( kr != kIOReturnSuccess )
    {
        printf( "IORegistryCreateIterator() error %08lx\n", (unsigned long)kr );
        return 0;
    }

    while ( (obj = IOIteratorNext( ite )) )
    {
        if ( IOObjectConformsTo( obj, (char*)className ) )
        {
            //	printf( "Found Realtek UserClient !!\n" );
            break;
        }
        else
        {
            rc = IOObjectGetClass( obj, name );
            if ( rc == kIOReturnSuccess )
            {
                //	printf( "Skipping class %s\n", name );
            }
        }
        IOObjectRelease( obj );
        obj = 0;
    }

    IORegistryDisposeEnumerator( ite );

    return obj;
}/* end getInterfaceWithName */
예제 #19
0
kern_return_t IOHIDSetHIDParameterToEventSystem(io_connect_t handle, CFStringRef key, CFTypeRef parameter) {
    IOHIDEventSystemClientRef client = IOHIDEventSystemClientCreateWithType (kCFAllocatorDefault, kIOHIDEventSystemClientTypeMonitor, NULL);
    kern_return_t  kr = kIOReturnNotReady;
    if (!client) {
        goto exit;
    }
 
    kr = kIOReturnUnsupported;
    io_service_t  service = 0;
    if (IOConnectGetService (handle, &service) == kIOReturnSuccess) {
        if (IOObjectConformsTo (service, "IOHIDSystem")) {
            IOHIDEventSystemClientSetProperty(client, key, parameter);
            kr = kIOReturnSuccess;
        } else {
            uint64_t entryID = 0;
            if (IORegistryEntryGetRegistryEntryID (service, &entryID) == kIOReturnSuccess) {
                IOHIDServiceClientRef serviceClient = IOHIDEventSystemClientCopyServiceForRegistryID(client, entryID);
                if (serviceClient) {
                    if (IOHIDServiceClientSetProperty(serviceClient, key, parameter)) {
                      kr = kIOReturnSuccess;
                    } else {
                      kr = kIOReturnInternalError;
                    }
                    CFRelease(serviceClient);
                }
            }
        }
        IOObjectRelease(service);
    }
    
 exit:

    if (client) {
        CFRelease(client);
    }
    if (kr) {
        os_log_error(_IOHIDLog(), "Fail to set parameter with status 0x%x", kr);
    }
    return kr;
}
예제 #20
0
kern_return_t IOHIDCopyHIDParameterFromEventSystem(io_connect_t handle, CFStringRef key, CFTypeRef *parameter) {
    CFTypeRef param = NULL;
    IOHIDEventSystemClientRef client = IOHIDEventSystemClientCreateWithType (kCFAllocatorDefault, kIOHIDEventSystemClientTypePassive, NULL);
    kern_return_t  kr = kIOReturnNotReady;
    if (!client) {
        goto exit;
    }
    io_service_t  service = 0;
    if (IOConnectGetService (handle, &service) == kIOReturnSuccess) {
        if (IOObjectConformsTo (service, "IOHIDSystem")) {
            param = IOHIDEventSystemClientCopyProperty(client, key);
        } else {
            uint64_t entryID = 0;
            if (IORegistryEntryGetRegistryEntryID (service, &entryID) == kIOReturnSuccess) {
                IOHIDServiceClientRef serviceClient = IOHIDEventSystemClientCopyServiceForRegistryID(client, entryID);
                if (serviceClient) {
                    param = IOHIDServiceClientCopyProperty(serviceClient, key);
                    CFRelease(serviceClient);
                }
            }
        }
        IOObjectRelease(service);
    }
  
 exit:
    if (param) {
        *parameter = param;
        kr = kIOReturnSuccess;
    }
    if (client) {
        CFRelease(client);
    }
    if (kr) {
        os_log_error(_IOHIDLog(), "Fail to get parameter with status 0x%x", kr);
    }
    return kr;
}
예제 #21
0
// Determine whether 'dev' is a SMART-capable device.
static bool is_smart_capable (io_object_t dev) {
  CFTypeRef smartCapableKey;
  CFDictionaryRef diskChars;

  // If the device has kIOPropertySMARTCapableKey, then it's capable,
  // no matter what it looks like.
  smartCapableKey = IORegistryEntryCreateCFProperty
    (dev, CFSTR (kIOPropertySMARTCapableKey),
     kCFAllocatorDefault, 0);
  if (smartCapableKey)
    {
      CFRelease (smartCapableKey);
      return true;
    }

  // If it's an kIOATABlockStorageDeviceClass then we're successful
  // only if its ATA features indicate it supports SMART.
  if (IOObjectConformsTo (dev, kIOATABlockStorageDeviceClass)
      && (diskChars = (CFDictionaryRef)IORegistryEntryCreateCFProperty                                                                                                           
	  (dev, CFSTR (kIOPropertyDeviceCharacteristicsKey),
	   kCFAllocatorDefault, kNilOptions)) != NULL)
    {
      CFNumberRef diskFeatures = NULL;
      UInt32 ataFeatures = 0;

      if (CFDictionaryGetValueIfPresent (diskChars, CFSTR ("ATA Features"),
					 (const void **)&diskFeatures))
	CFNumberGetValue (diskFeatures, kCFNumberLongType,
			  &ataFeatures);
      CFRelease (diskChars);
      if (diskFeatures)
	CFRelease (diskFeatures);
      
      return (ataFeatures & kIOATAFeatureSMART) != 0;
    }
  return false;
}
int main (int argc, const char *argv[])
{
    CFMutableDictionaryRef dictRef;
    io_iterator_t iter;
    io_service_t service;
    kern_return_t kr;
    CFNumberRef numberRef;
    SInt32 constantOne = 1;
    
    constantOne=42;
    
    if (argc > 1) {
        constantOne = atoi(argv[1]);
    }
    
    // The bulk of this code locates all instances of our driver running on the system.
    
    // First find all children of our driver. As opposed to nubs, drivers are often not registered
    // via the registerServices call because nothing is expected to match to them. Unregistered
    // objects in the I/O Registry are not returned by IOServiceGetMatchingServices.
    
    // IOBlockStorageServices is our child in the I/O Registry
    dictRef = IOServiceMatching("IOBlockStorageServices");
    if (!dictRef) {
        fprintf(stderr, "IOServiceMatching returned NULL.\n");
        return -1;
    }
    
    // Create an iterator over all matching IOService nubs.
    // This consumes a reference on dictRef.
    kr = IOServiceGetMatchingServices(kIOMasterPortDefault, dictRef, &iter);
    if (KERN_SUCCESS != kr) {
        fprintf(stderr, "IOServiceGetMatchingServices returned 0x%08x.\n", kr);
        CFRelease(dictRef);
        return -1;
    }
    
    // Create a dictionary to pass to our driver. This dictionary has the key "MyProperty"
    // and the value an integer 1.
    dictRef = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
                                        &kCFTypeDictionaryKeyCallBacks,
                                        &kCFTypeDictionaryValueCallBacks);
    
    numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &constantOne);
    CFDictionarySetValue(dictRef, CFSTR("MyProperty"), numberRef);
    CFRelease(numberRef);
    
    // Iterate across all instances of IOBlockStorageServices.
    while ((service = IOIteratorNext(iter))) {
        io_registry_entry_t parent;
        
        // Now that our child has been found we can traverse the I/O Registry to find our driver.
        kr = IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent);
        if (KERN_SUCCESS != kr) {
            fprintf(stderr, "IORegistryEntryGetParentEntry returned 0x%08x.\n", kr);
        }
        else {
            // We're only interested in the parent object if it's our driver class.
            if (IOObjectConformsTo(parent, "fi_dungeon_driver_IOSATDriver")) {
                // This is the function that results in ::setProperties() being called in our
                // kernel driver. The dictionary we created is passed to the driver here.
                kr = IORegistryEntrySetCFProperties(parent, dictRef);
                if (KERN_SUCCESS != kr) {
                    fprintf(stderr, "IORegistryEntrySetCFProperties returned 0x%08x.\n", kr);
                }
            }
            
            // Done with the parent object.
            IOObjectRelease(parent);
        }
        
        // Done with the object returned by the iterator.
        IOObjectRelease(service);
    }
    
    if (iter != IO_OBJECT_NULL) {
        IOObjectRelease(iter);
        iter = IO_OBJECT_NULL;
    }
    
    if (dictRef) {
        CFRelease(dictRef);
        dictRef = NULL;
    }
    
    return 0;
}
void MemoryCardDriverThreaded_MacOSX::GetUSBStorageDevices( vector<UsbStorageDevice>& vDevicesOut )
{
	LockMut( m_ChangedLock );
	// First, get all device paths
	struct statfs *fs;
	int num = getfsstat( NULL, 0, MNT_NOWAIT );
	
	fs = new struct statfs[num];
	
	num = getfsstat( fs, num * sizeof(struct statfs), MNT_NOWAIT );
	ASSERT( num != -1 );
	
	for( int i = 0; i < num; ++i )
	{
		if( strncmp(fs[i].f_mntfromname, _PATH_DEV, strlen(_PATH_DEV)) )
			continue;
		
		const RString& sDevicePath = fs[i].f_mntfromname;
		const RString& sDisk = Basename( sDevicePath ); // disk#[[s#] ...]
		
		// Now that we have the disk name, look up the IOServices associated with it.
		CFMutableDictionaryRef dict;
		
		if( !(dict = IOBSDNameMatching(kIOMasterPortDefault, 0, sDisk)) )
			continue;
		
		// Look for certain properties: Leaf, Ejectable, Writable.
		CFDictionarySetValue( dict, CFSTR(kIOMediaLeafKey), kCFBooleanTrue );
		CFDictionarySetValue( dict, CFSTR(kIOMediaEjectableKey), kCFBooleanTrue );
		CFDictionarySetValue( dict, CFSTR(kIOMediaWritableKey), kCFBooleanTrue );
		
		// Get the matching iterator. As always, this consumes a reference to dict.
		io_iterator_t iter;
		kern_return_t ret = IOServiceGetMatchingServices( kIOMasterPortDefault, dict, &iter );
		
		if( ret != KERN_SUCCESS || iter == 0 )
			continue;
		
		// I'm not quite sure what it means to have two services with this device.
		// Iterate over them all. If one contains what we want, stop.
		io_registry_entry_t device; // This is the same as an io_object_t.
		
		while( (device = IOIteratorNext(iter)) )
		{
			// Look at the parent of the device until we see an IOUSBMassStorageClass
			while( device != MACH_PORT_NULL && !IOObjectConformsTo(device, "IOUSBMassStorageClass") )
			{
				io_registry_entry_t entry;
				ret = IORegistryEntryGetParentEntry( device, kIOServicePlane, &entry );
				IOObjectRelease( device );
				device = ret == KERN_SUCCESS? entry:MACH_PORT_NULL;
			}
			// Now look for the corresponding IOUSBDevice, it's likely 2 up the tree
			while( device != MACH_PORT_NULL && !IOObjectConformsTo(device, "IOUSBDevice") )
			{
				io_registry_entry_t entry;
				ret = IORegistryEntryGetParentEntry( device, kIOServicePlane, &entry );
				IOObjectRelease( device );
				device = ret == KERN_SUCCESS? entry:MACH_PORT_NULL;
			}
			if( device == MACH_PORT_NULL )
				continue;
			
			// At this point, it is pretty safe to say that we've found a USB device.
			vDevicesOut.push_back( UsbStorageDevice() );
			UsbStorageDevice& usbd = vDevicesOut.back();
			
			LOG->Trace( "Found memory card at path: %s.", fs[i].f_mntonname );
			usbd.SetOsMountDir( fs[i].f_mntonname );
			usbd.iVolumeSizeMB = int( (uint64_t(fs[i].f_blocks) * fs[i].f_bsize) >> 20 );
		
			// Now we can get some more information from the registry tree.
			usbd.iBus = GetIntProperty( device, CFSTR("USB Address") );
			usbd.iPort = GetIntProperty( device, CFSTR("PortNum") );
			// usbd.iLevel ?
			usbd.sSerial = GetStringProperty( device, CFSTR("USB Serial Number") );
			usbd.sDevice = fs[i].f_mntfromname;
			usbd.idVendor = GetIntProperty( device, CFSTR(kUSBVendorID) );
			usbd.idProduct = GetIntProperty( device, CFSTR(kUSBProductID) );
			usbd.sVendor = GetStringProperty( device, CFSTR("USB Vendor Name") );
			usbd.sProduct = GetStringProperty( device, CFSTR("USB Product Name") );
			IOObjectRelease( device );
			break; // We found what we wanted
		}
		IOObjectRelease( iter );
	}
	m_bChanged = false;
	delete[] fs;
}
예제 #24
0
static kern_return_t CopyUserVisiblePortName(io_object_t interface, 
											 CFMutableDictionaryRef interfaceInfo, 
											 CFStringRef *userVisibleName)
	// Given an IOKit device (interface) and a dictionary of 
	// information about the device (interfaceInfo), guess at the 
	// user-visible name for the device.  The basic algorithm is 
	// as follows:
	// 
	// 1. Decide on a proposed user-visible name, using heuristics 
	//    that are based on the device type.  While doing this add 
	//    keyword substition values to interfaceInfo.
	//
	// 2. Call the client's callback to see whether it wants to 
	//    modify our decision.
	//
	// 3. Finally, replace certain keywords in the string with 
	//    values from the interfaceInfo dictionary.
	//
	// This design allows the client callback to see a limited number 
	// of strings, and hence makes it easy for the client to localise 
	// those strings.  It also means we only have one set of I/O Registry 
	// parsing code (in step 1), rather than messing with IOKit once in 
	// step 1 to decide on the device type and again in step 3 when 
	// doing the keyword replacement.
{
	kern_return_t err;
	CFStringRef   proposedName;
	CFStringRef   baseName;
	
	assert(interface        != 0  );
	assert(interfaceInfo    != NULL);
	assert( userVisibleName != NULL);
	assert(*userVisibleName == NULL);
	
	proposedName = NULL;
	baseName = NULL;
	
	// First we synthesise our candidate user-visible name.
	
	if ( IOObjectConformsTo(interface, kIOEthernetInterfaceClass) ) {
		err = CopyUserVisibleNameForEthernetPort(interface, interfaceInfo, &proposedName);
	} else if ( IOObjectConformsTo(interface, kIOSerialBSDServiceValue) ) {
		err = CopyUserVisibleNameForModemOrSerialPort(interface, interfaceInfo, &proposedName);
	} else {
		err = 0;
		proposedName = (CFStringRef) IORegistryEntryCreateCFProperty(interface, CFSTR(kIOBSDNameKey), NULL, kNilOptions);
		if (proposedName == NULL) {
			err = -1;
		}
	}
	
	// Then we ask our client to munge it as it likes.

	if (gPortNameCallback != NULL) {
		err = gPortNameCallback(interface, interfaceInfo, proposedName, &baseName);
	} else {
		// The debug build complains if you don't install a callback because, 
		// hey, localisability is important.
		
		#if MORE_DEBUG
			{
				static Boolean gHavePrinted;
				
				if ( !gHavePrinted ) {
					fprintf(stderr, "MoreSCFPortScanner.c: You should install a port name callback.\n");
					gHavePrinted = true;
				}
			}
		#endif
	}
	
	// If we didn't get a baseName, just use proposedName.
	
	if ( (err == 0) && (baseName == NULL) ) {
		baseName = CFStringCreateCopy(NULL, proposedName);
		if (baseName == NULL) {
			err = -1;
		}
	}
	
	// Then we do keyword substitution (as specified in the header file) on the result.
	
	if (err == 0) {
		err = SubstituteKeywordsInUserVisibleName(interface, interfaceInfo, baseName, userVisibleName);
	}
	
	CFQRelease(proposedName);
	CFQRelease(baseName);
	
	assert( (err == 0) == (*userVisibleName != NULL) );
	
	return err;
}
예제 #25
0
/**
 * Guess the media that a volume/partition is on
 */
MythMediaType FindMediaType(io_service_t service)
{
    kern_return_t  kernResult;
    io_iterator_t  iter;
    MythMediaType  mediaType = MEDIATYPE_UNKNOWN;
    QString        msg = QString("FindMediaType() - ");
    bool           isWholeMedia = false;

    // Create an iterator across all parents of the service object passed in.
    kernResult = IORegistryEntryCreateIterator(service,
                                               kIOServicePlane,
                                               kIORegistryIterateRecursively
                                               | kIORegistryIterateParents,
                                               &iter);

    if (KERN_SUCCESS != kernResult)
        LOG(VB_GENERAL, LOG_CRIT, msg +
            QString("IORegistryEntryCreateIterator returned %1")
                .arg(kernResult));
    else if (!iter)
        LOG(VB_GENERAL, LOG_CRIT, msg +
            "IORegistryEntryCreateIterator returned NULL iterator");
    else
    {
        // A reference on the initial service object is released in
        // the do-while loop below, so add a reference to balance
        IOObjectRetain(service);
        
        do
        {
            isWholeMedia = false;
            if (IOObjectConformsTo(service, kIOMediaClass))
            {
                CFTypeRef wholeMedia;

                wholeMedia = IORegistryEntryCreateCFProperty
                             (service, CFSTR(kIOMediaWholeKey), 
                              kCFAllocatorDefault, 0);

                if (!wholeMedia)
                    LOG(VB_GENERAL, LOG_ALERT, msg +
                        "Could not retrieve Whole property");
                else
                {
                    isWholeMedia = CFBooleanGetValue((CFBooleanRef)wholeMedia);
                    CFRelease(wholeMedia);
                }
            }

            if (isWholeMedia)
            {
                if (IOObjectConformsTo(service, kIODVDMediaClass))
                    mediaType = MEDIATYPE_DVD;
                else if (IOObjectConformsTo(service, kIOCDMediaClass))
                    mediaType = MEDIATYPE_AUDIO;
            }

            IOObjectRelease(service);

        } while ((service = IOIteratorNext(iter))
                 && (mediaType == MEDIATYPE_UNKNOWN));

        IOObjectRelease(iter);
    }
    return mediaType;
}
예제 #26
0
파일: cdrom.c 프로젝트: Geal/vlc
/****************************************************************************
 * darwin_getTOC: get the TOC
 ****************************************************************************/
static CDTOC *darwin_getTOC( vlc_object_t * p_this, const vcddev_t *p_vcddev )
{
    mach_port_t port;
    char *psz_devname;
    kern_return_t ret;
    CDTOC *pTOC = NULL;
    io_iterator_t iterator;
    io_registry_entry_t service;
    CFMutableDictionaryRef properties;
    CFDataRef data;

    /* get the device name */
    if( ( psz_devname = strrchr( p_vcddev->psz_dev, '/') ) != NULL )
        ++psz_devname;
    else
        psz_devname = p_vcddev->psz_dev;

    /* unraw the device name */
    if( *psz_devname == 'r' )
        ++psz_devname;

    /* get port for IOKit communication */
    if( ( ret = IOMasterPort( MACH_PORT_NULL, &port ) ) != KERN_SUCCESS )
    {
        msg_Err( p_this, "IOMasterPort: 0x%08x", ret );
        return( NULL );
    }

    /* get service iterator for the device */
    if( ( ret = IOServiceGetMatchingServices(
                    port, IOBSDNameMatching( port, 0, psz_devname ),
                    &iterator ) ) != KERN_SUCCESS )
    {
        msg_Err( p_this, "IOServiceGetMatchingServices: 0x%08x", ret );
        return( NULL );
    }

    /* first service */
    service = IOIteratorNext( iterator );
    IOObjectRelease( iterator );

    /* search for kIOCDMediaClass */
    while( service && !IOObjectConformsTo( service, kIOCDMediaClass ) )
    {
        if( ( ret = IORegistryEntryGetParentIterator( service,
                        kIOServicePlane, &iterator ) ) != KERN_SUCCESS )
        {
            msg_Err( p_this, "IORegistryEntryGetParentIterator: 0x%08x", ret );
            IOObjectRelease( service );
            return( NULL );
        }

        IOObjectRelease( service );
        service = IOIteratorNext( iterator );
        IOObjectRelease( iterator );
    }

    if( !service )
    {
        msg_Err( p_this, "search for kIOCDMediaClass came up empty" );
        return( NULL );
    }

    /* create a CF dictionary containing the TOC */
    if( ( ret = IORegistryEntryCreateCFProperties( service, &properties,
                    kCFAllocatorDefault, kNilOptions ) ) != KERN_SUCCESS )
    {
        msg_Err( p_this, "IORegistryEntryCreateCFProperties: 0x%08x", ret );
        IOObjectRelease( service );
        return( NULL );
    }

    /* get the TOC from the dictionary */
    if( ( data = (CFDataRef) CFDictionaryGetValue( properties,
                                    CFSTR(kIOCDMediaTOCKey) ) ) != NULL )
    {
        CFRange range;
        CFIndex buf_len;

        buf_len = CFDataGetLength( data ) + 1;
        range = CFRangeMake( 0, buf_len );

        if( ( pTOC = malloc( buf_len ) ) != NULL )
        {
            CFDataGetBytes( data, range, (u_char *)pTOC );
        }
    }
    else
    {
        msg_Err( p_this, "CFDictionaryGetValue failed" );
    }

    CFRelease( properties );
    IOObjectRelease( service );

    return( pTOC );
}
예제 #27
0
void genIOKitDevice(const io_service_t& device,
                    const io_service_t& parent,
                    const io_name_t plane,
                    int depth,
                    QueryData& results) {
  Row r;
  io_name_t name, device_class;
  auto kr = IORegistryEntryGetName(device, name);
  if (kr == KERN_SUCCESS) {
    r["name"] = std::string(name);
  }

  // Get the device class.
  kr = IOObjectGetClass(device, device_class);
  if (kr == KERN_SUCCESS) {
    r["class"] = std::string(device_class);
  }

  // The entry into the registry is the ID, and is used for children as parent.
  uint64_t device_id, parent_id;
  kr = IORegistryEntryGetRegistryEntryID(device, &device_id);
  if (kr == KERN_SUCCESS) {
    r["id"] = BIGINT(device_id);
  } else {
    r["id"] = "-1";
  }

  kr = IORegistryEntryGetRegistryEntryID(parent, &parent_id);
  if (kr == KERN_SUCCESS) {
    r["parent"] = BIGINT(parent_id);
  } else {
    r["parent"] = "-1";
  }

  r["depth"] = INTEGER(depth);

  if (IORegistryEntryInPlane(device, kIODeviceTreePlane)) {
    io_string_t device_path;
    kr = IORegistryEntryGetPath(device, kIODeviceTreePlane, device_path);
    if (kr == KERN_SUCCESS) {
      // Remove the "IODeviceTree:" from the device tree path.
      r["device_path"] = std::string(device_path).substr(13);
    }
  }

  // Fill in service bits and busy/latency time.
  if (IOObjectConformsTo(device, "IOService")) {
    r["service"] = "1";
  } else {
    r["service"] = "0";
  }

  uint32_t busy_state;
  kr = IOServiceGetBusyState(device, &busy_state);
  if (kr == KERN_SUCCESS) {
    r["busy_state"] = INTEGER(busy_state);
  } else {
    r["busy_state"] = "0";
  }

  auto retain_count = IOObjectGetKernelRetainCount(device);
  r["retain_count"] = INTEGER(retain_count);

  results.push_back(r);
}
예제 #28
0
/*
 * Return a Python dict of tuples for disk I/O information
 */
static PyObject*
get_disk_io_counters(PyObject* self, PyObject* args)
{
    PyObject* py_retdict = PyDict_New();
    PyObject* py_disk_info;

    CFDictionaryRef parent_dict;
    CFDictionaryRef props_dict;
    CFDictionaryRef stats_dict;
    io_registry_entry_t parent;
    io_registry_entry_t disk;
    io_iterator_t disk_list;

    /* Get list of disks */
    if (IOServiceGetMatchingServices(kIOMasterPortDefault,
                                     IOServiceMatching(kIOMediaClass),
                                     &disk_list) != kIOReturnSuccess) {
        Py_DECREF(py_retdict);
        PyErr_SetString(PyExc_RuntimeError, "Unable to get the list of disks.");
        return NULL;
    }

    /* Iterate over disks */
    while ((disk = IOIteratorNext(disk_list)) != 0) {
        parent_dict = NULL;
        props_dict = NULL;
        stats_dict = NULL;

        if (IORegistryEntryGetParentEntry(disk, kIOServicePlane, &parent) != kIOReturnSuccess) {
            PyErr_SetString(PyExc_RuntimeError, "Unable to get the disk's parent.");
            Py_DECREF(py_retdict);
            IOObjectRelease(disk);
            return NULL;
        }

        if (IOObjectConformsTo(parent, "IOBlockStorageDriver")) {
            if(IORegistryEntryCreateCFProperties(
                                     disk,
                                     (CFMutableDictionaryRef *) &parent_dict,
                                     kCFAllocatorDefault,
                                     kNilOptions) != kIOReturnSuccess)
            {
                PyErr_SetString(PyExc_RuntimeError,
                                "Unable to get the parent's properties.");
                Py_DECREF(py_retdict);
                IOObjectRelease(disk);
                IOObjectRelease(parent);
                return NULL;
            }

            if (IORegistryEntryCreateCFProperties(parent,
                                          (CFMutableDictionaryRef *) &props_dict,
                                          kCFAllocatorDefault,
                                          kNilOptions) != kIOReturnSuccess)
            {
                PyErr_SetString(PyExc_RuntimeError,
                                "Unable to get the disk properties.");
                Py_DECREF(py_retdict);
                IOObjectRelease(disk);
                return NULL;
            }

            const int kMaxDiskNameSize = 64;
            CFStringRef disk_name_ref = (CFStringRef)CFDictionaryGetValue(
                                                    parent_dict,
                                                    CFSTR(kIOBSDNameKey));
            char disk_name[kMaxDiskNameSize];

            CFStringGetCString(disk_name_ref,
                               disk_name,
                               kMaxDiskNameSize,
                               CFStringGetSystemEncoding());

            stats_dict = (CFDictionaryRef)CFDictionaryGetValue(
                                    props_dict,
                                    CFSTR(kIOBlockStorageDriverStatisticsKey));

            if (stats_dict == NULL) {
                PyErr_SetString(PyExc_RuntimeError, "Unable to get disk stats.");
                Py_DECREF(py_retdict);
                CFRelease(props_dict);
                IOObjectRelease(disk);
                IOObjectRelease(parent);
                return NULL;
            }

            CFNumberRef number;
            int64_t reads, writes, read_bytes, write_bytes, read_time, write_time = 0;

            /* Get disk reads/writes */
            if ((number = (CFNumberRef)CFDictionaryGetValue(
                            stats_dict,
                            CFSTR(kIOBlockStorageDriverStatisticsReadsKey))))
            {
                CFNumberGetValue(number, kCFNumberSInt64Type, &reads);
            }
            if ((number = (CFNumberRef)CFDictionaryGetValue(
                            stats_dict,
                            CFSTR(kIOBlockStorageDriverStatisticsWritesKey))))
            {
                CFNumberGetValue(number, kCFNumberSInt64Type, &writes);
            }

            /* Get disk bytes read/written */
            if ((number = (CFNumberRef)CFDictionaryGetValue(
                        stats_dict,
                        CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey))))
            {
                CFNumberGetValue(number, kCFNumberSInt64Type, &read_bytes);
            }
            if ((number = (CFNumberRef)CFDictionaryGetValue(
                stats_dict,
                CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey))))
            {
                CFNumberGetValue(number, kCFNumberSInt64Type, &write_bytes);
            }

            /* Get disk time spent reading/writing (nanoseconds) */
            if ((number = (CFNumberRef)CFDictionaryGetValue(
                    stats_dict,
                    CFSTR(kIOBlockStorageDriverStatisticsTotalReadTimeKey))))
            {
                CFNumberGetValue(number, kCFNumberSInt64Type, &read_time);
            }
            if ((number = (CFNumberRef)CFDictionaryGetValue(
                    stats_dict,
                    CFSTR(kIOBlockStorageDriverStatisticsTotalWriteTimeKey)))) {
                CFNumberGetValue(number, kCFNumberSInt64Type, &write_time);
            }

            // Read/Write time on OS X comes back in nanoseconds and in psutil
            // we've standardized on milliseconds so do the conversion.
            py_disk_info = Py_BuildValue("(KKKKKK)",
                                         reads, writes,
                                         read_bytes, write_bytes,
                                         read_time / 1000, write_time / 1000);
            PyDict_SetItemString(py_retdict, disk_name, py_disk_info);
            Py_XDECREF(py_disk_info);

            CFRelease(parent_dict);
            IOObjectRelease(parent);
            CFRelease(props_dict);
            IOObjectRelease(disk);
        }
    }

    IOObjectRelease (disk_list);

    return py_retdict;
}
static IOReturn
PrintSMARTDataForBSDNode ( const char * bsdNode )
{


    IOReturn error   = kIOReturnError;
    io_object_t object  = MACH_PORT_NULL;
    io_object_t parent  = MACH_PORT_NULL;
    bool found   = false;
    char *                  bsdName = NULL;
    char deviceName[MAXPATHLEN];

    sprintf ( deviceName, "%s", bsdNode );

    if ( !strncmp ( deviceName, "/dev/r", 6 ) )
    {

        // Strip off the /dev/r from /dev/rdiskX
        bsdName = &deviceName[6];

    }

    else if ( !strncmp ( deviceName, "/dev/", 5 ) )
    {

        // Strip off the /dev/r from /dev/rdiskX
        bsdName = &deviceName[5];

    }

    else
    {

        bsdName = deviceName;

    }

    require_action ( ( strncmp ( bsdName, "disk", 4 ) == 0 ), ErrorExit, PrintUsage ( ) );

    object = IOServiceGetMatchingService (  kIOMasterPortDefault,
        IOBSDNameMatching ( kIOMasterPortDefault, 0, bsdName ) );

    require ( ( object != MACH_PORT_NULL ), ErrorExit );

    parent = object;
    while ( IOObjectConformsTo ( object, kIOATABlockStorageDeviceClass ) == false )
    {

                #if DEBUG

        io_name_t className;

        error = IOObjectGetClass ( object, className );
        printf ( "Object class = %s\n", ( char * ) className );

                #endif

        error = IORegistryEntryGetParentEntry ( object, kIOServicePlane, &parent );
        require ( ( error == kIOReturnSuccess ), ReleaseObject );
        require ( ( parent != MACH_PORT_NULL ), ReleaseObject );

        IOObjectRelease ( object );
        object = parent;

    }

    if ( IOObjectConformsTo ( object, kIOATABlockStorageDeviceClass ) )
    {

        PrintSMARTDataForDevice ( object );
        found = true;

    }


ReleaseObject:


    require ( ( object != MACH_PORT_NULL ), ErrorExit );
    IOObjectRelease ( object );
    object = MACH_PORT_NULL;


ErrorExit:


    if ( found == false )
    {
        printf ( "No S.M.A.R.T. capable device at %s\n", bsdNode );
    }

    return error;

}
int BLGetParentDeviceAndPartitionType(BLContextPtr context,   const char * partitionDev,
			 char * parentDev,
			 uint32_t *partitionNum,
			BLPartitionType *partitionType) {

    int                     result = 0;
    kern_return_t           kret;
    io_iterator_t           services = MACH_PORT_NULL;
    io_iterator_t           parents = MACH_PORT_NULL;
    io_registry_entry_t     service = MACH_PORT_NULL;
    io_iterator_t           grandparents = MACH_PORT_NULL;
    io_registry_entry_t     service2 = MACH_PORT_NULL;
    io_object_t             obj = MACH_PORT_NULL;
    CFNumberRef             pn = NULL;
    CFStringRef             content = NULL;

    char par[MNAMELEN];

    parentDev[0] = '\0';

    kret = IOServiceGetMatchingServices(kIOMasterPortDefault,
					IOBSDNameMatching(kIOMasterPortDefault,
							  0,
							  (char *)partitionDev + 5),
					&services);
    if (kret != KERN_SUCCESS) {
      result = 3;
      goto finish;
    }

    // Should only be one IOKit object for this volume. (And we only want one.)
    obj = IOIteratorNext(services);
    if (!obj) {
        result = 4;
        goto finish;
    }  

    // we have the IOMedia for the partition.

    pn = (CFNumberRef)IORegistryEntryCreateCFProperty(obj, CFSTR(kIOMediaPartitionIDKey),
        kCFAllocatorDefault, 0);
    
    if(pn == NULL) {
        result = 4;
        goto finish;
    }
    
    if (CFGetTypeID(pn) != CFNumberGetTypeID()) {
        result = 5;
        goto finish;
    }
    
    CFNumberGetValue(pn, kCFNumberSInt32Type, partitionNum);
    
    kret = IORegistryEntryGetParentIterator (obj, kIOServicePlane,
					       &parents);
    if (kret) {
      result = 6;
      goto finish;
      /* We'll never loop forever. */
    }

    while ( (service = IOIteratorNext(parents)) != 0 ) {

        kret = IORegistryEntryGetParentIterator (service, kIOServicePlane,
                                                &grandparents);
        IOObjectRelease(service);
        service = MACH_PORT_NULL;

        if (kret) {
            result = 6;
            goto finish;
            /* We'll never loop forever. */
        }

        while ( (service2 = IOIteratorNext(grandparents)) != 0 ) {
        
            if (content) {
                CFRelease(content);
                content = NULL;
            }

            if (!IOObjectConformsTo(service2, "IOMedia")) {
                IOObjectRelease(service2);
                service2 = MACH_PORT_NULL;
                continue;
            }
        
            content = (CFStringRef)
                IORegistryEntryCreateCFProperty(service2,
                                                CFSTR(kIOMediaContentKey),
                                                kCFAllocatorDefault, 0);
            
            
            if(CFGetTypeID(content) != CFStringGetTypeID()) {
                result = 2;
                goto finish;
            }
            
            if(CFStringCompare(content, CFSTR("Apple_partition_scheme"), 0)
               == kCFCompareEqualTo) {
                if(partitionType) *partitionType = kBLPartitionType_APM;
            } else if(CFStringCompare(content, CFSTR("FDisk_partition_scheme"), 0)
                      == kCFCompareEqualTo) {
                if(partitionType) *partitionType = kBLPartitionType_MBR;
            } else if(CFStringCompare(content, CFSTR("GUID_partition_scheme"), 0)
                      == kCFCompareEqualTo) {
                if(partitionType) *partitionType = kBLPartitionType_GPT;
            } else {
                IOObjectRelease(service2);
                service2 = MACH_PORT_NULL;
                CFRelease(content);
                content = NULL;
                continue;
            }

            CFRelease(content);

            content = IORegistryEntryCreateCFProperty(service2, CFSTR(kIOBSDNameKey),
                                                        kCFAllocatorDefault, 0);
        
            if(CFGetTypeID(content) != CFStringGetTypeID()) {
                result = 3;
                goto finish;
            }
        
            if(!CFStringGetCString(content, par, MNAMELEN, kCFStringEncodingASCII)) {
                result = 4;
                goto finish;
            }

            CFRelease(content);
            content = NULL;

            sprintf(parentDev, "/dev/%s",par);
            break;
        }

        if(parentDev[0] == '\0') {
            break;
        }
    }

    if(parentDev[0] == '\0') {
      // nothing found
      result = 8;
      goto finish;
    }

finish:
    if (services != MACH_PORT_NULL)     IOObjectRelease(services);
    if (parents != MACH_PORT_NULL)      IOObjectRelease(parents);
    if (service != MACH_PORT_NULL)      IOObjectRelease(service);
    if (grandparents != MACH_PORT_NULL) IOObjectRelease(grandparents);
    if (service2 != MACH_PORT_NULL)     IOObjectRelease(service2);
    if (obj != MACH_PORT_NULL)          IOObjectRelease(obj);
    if (pn)                             CFRelease(pn);
    if (content)                        CFRelease(content);
    
    return result;
}