void dumpIter( io_iterator_t iter, mach_port_t recvPort )
{
    kern_return_t	kr;
    io_object_t		obj;
    io_name_t		name;
    io_string_t		path;
    mach_port_t		iter3;
    
    while( (obj = IOIteratorNext( iter))) {
        assert( KERN_SUCCESS == (
        kr = IORegistryEntryGetName( obj, name )
        ));
	printf("name:%s(%d)\n", name, obj);
        kr = IORegistryEntryGetPath( obj, kIOServicePlane, path );
        if( KERN_SUCCESS == kr) {
            
	    // if the object is detached, getPath will fail
            printf("path:%s\n", path);

            // as will IOServiceAddInterestNotification
            if( KERN_SUCCESS != (
                    kr = IOServiceAddInterestNotificationMsg( obj, kIOGeneralInterest,
                            recvPort, (unsigned int) obj, &iter3)
            )) printf("IOServiceAddInterestNotification(%lx)\n", kr);
            // can compare two kernel objects with IOObjectIsEqualTo() if we keep the object,
            // otherwise, release
            IOObjectRelease( obj );
        }
    }
}
Beispiel #2
0
// makes a list of ATA or SCSI devices for the DEVICESCAN directive of
// smartd.  Returns number N of devices, or -1 if out of
// memory. Allocates N+1 arrays: one of N pointers (devlist); the
// other N arrays each contain null-terminated character strings.  In
// the case N==0, no arrays are allocated because the array of 0
// pointers has zero length, equivalent to calling malloc(0).
int make_device_names (char*** devlist, const char* name) {
  IOReturn err;
  io_iterator_t i;
  io_object_t device = MACH_PORT_NULL;
  int result;
  int index;

  // We treat all devices as ATA so long as they support SMARTLib.
  if (strcmp (name, "ATA") != 0)
    return 0;

  err = IOServiceGetMatchingServices 
    (kIOMasterPortDefault, IOServiceMatching (kIOBlockStorageDeviceClass), &i);
  if (err != kIOReturnSuccess)
    return -1;

  // Count the devices.
  result = 0;
  while ((device = IOIteratorNext (i)) != MACH_PORT_NULL) {
    if (is_smart_capable (device))
      result++;
    IOObjectRelease (device);
  }

  // Create an array of service names.
  IOIteratorReset (i);
  *devlist = (char**)Calloc (result, sizeof (char *)); 
  if (! *devlist)
    goto error;
  index = 0;
  while ((device = IOIteratorNext (i)) != MACH_PORT_NULL) {
    if (is_smart_capable (device))
      {
	io_string_t devName;
	IORegistryEntryGetPath(device, kIOServicePlane, devName);
	(*devlist)[index] = CustomStrDup (devName, true, __LINE__, __FILE__);
	if (! (*devlist)[index])
	  goto error;
	index++;
      }
    IOObjectRelease (device);
  }

  IOObjectRelease (i);
  return result;

 error:
  if (device != MACH_PORT_NULL)
    IOObjectRelease (device);
  IOObjectRelease (i);
  if (*devlist)
    {
      for (index = 0; index < result; index++)
	if ((*devlist)[index])
	  FreeNonZero ((*devlist)[index], 0, __LINE__, __FILE__);
      FreeNonZero (*devlist, result * sizeof (char *), __LINE__, __FILE__);
    }
  return -1;
}
Beispiel #3
0
struct usb_device_info *find_usb_devices(int (*match)(const struct usb_device_info*))
{
    struct usb_device_info *devlist = 0;
    struct usb_device_info devinfo;
    /*static const int vendor_id = 1133;*/	/* 3dconnexion */
    static char dev_path[512];
    io_object_t dev;
    io_iterator_t iter;
    CFMutableDictionaryRef match_dict;
    CFNumberRef number_ref;

    match_dict = IOServiceMatching(kIOHIDDeviceKey);

    /* add filter rule: vendor-id should be 3dconnexion's */
    /*number_ref = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &vendor_id);
    CFDictionarySetValue(match_dict, CFSTR(kIOHIDVendorIDKey), number_ref);
    CFRelease(number_ref);
    */

    /* fetch... */
    if(IOServiceGetMatchingServices(kIOMasterPortDefault, match_dict, &iter) != kIOReturnSuccess) {
        fprintf(stderr, "failed to retrieve USB HID devices\n");
        return 0;
    }

    while((dev = IOIteratorNext(iter))) {
        memset(&devinfo, 0, sizeof devinfo);

        IORegistryEntryGetPath(dev, kIOServicePlane, dev_path);
        if(!(devinfo.devfiles[0] = strdup(dev_path))) {
            perror("failed to allocate device file path buffer");
            continue;
        }
        devinfo.num_devfiles = 1;

        /* TODO retrieve vendor id and product id */

        if(!match || match(&devinfo)) {
            struct usb_device_info *node = malloc(sizeof *node);
            if(node) {
                if(verbose) {
                    printf("found usb device: ");
                    print_usb_device_info(&devinfo);
                }

                *node = devinfo;
                node->next = devlist;
                devlist = node;
            } else {
                free(devinfo.devfiles[0]);
                perror("failed to allocate usb device info node");
            }
        }
    }

    IOObjectRelease(dev);
    IOObjectRelease(iter);
    return devlist;
}
int main(int argc, char *argv[]) {

  char *path;
  kern_return_t ret;
  io_registry_entry_t entry = 0;
  io_string_t iopath;

  if(argc != 2) {
    fprintf(stderr, "Usage: %s disk1s1\n", getprogname());
    exit(1);
  }

  path = argv[1];

  //  entry = IORegistryEntryFromPath(kIOMasterPortDefault, path);
  entry = IOServiceGetMatchingService(kIOMasterPortDefault,
				      IOBSDNameMatching(kIOMasterPortDefault, 0, path));

  printf("entry is %p\n", entry);

  if(entry == 0) exit(1);


  ret = IORegistryEntryGetPath(entry, kIOServicePlane, iopath);
  if(ret) {
    fprintf(stderr, "Could not get entry path\n");
    exit(1);
  }
  printf("%s path: %s\n", kIOServicePlane, iopath);

  ret = IORegistryEntryGetPath(entry, kIODeviceTreePlane, iopath);
  if(ret) {
    fprintf(stderr, "Could not get entry path\n");
    exit(1);
  }
  printf("%s path: %s\n", kIODeviceTreePlane, iopath);


 IOObjectRelease(entry); 

  return 0;
}
int main( int argc, char * argv[] )
{
    kern_return_t kr;
    io_service_t  framebuffer, interface;
    IOOptionBits  bus;
    IOItemCount   busCount;

    framebuffer = CGDisplayIOServicePort(CGMainDisplayID());

    {
        io_string_t path;
        kr = IORegistryEntryGetPath(framebuffer, kIOServicePlane, path);
        assert( KERN_SUCCESS == kr );
        printf("\nUsing device: %s\n", path);

        kr = IOFBGetI2CInterfaceCount( framebuffer, &busCount );
        assert( kIOReturnSuccess == kr );
    
        for( bus = 0; bus < busCount; bus++ )
        {
            IOI2CConnectRef  connect;
    
            kr = IOFBCopyI2CInterfaceForBus(framebuffer, bus, &interface);
            if( kIOReturnSuccess != kr)
                continue;
    
            kr = IOI2CInterfaceOpen( interface, kNilOptions, &connect );
    
            IOObjectRelease(interface);
            assert( kIOReturnSuccess == kr );
            if( kIOReturnSuccess != kr)
                continue;
    
            printf("\nEDID using bus %ld:\n", bus);
            EDIDTest( connect );
    
            printf("\niTV using bus %ld:\n", bus);
            iTVTest( connect );
    
            IOI2CInterfaceClose( connect, kNilOptions );
        }
    }

    exit(0);
    return(0);
}
Beispiel #6
0
bool find_service(const char *target_name, io_connect_t *ptarget_port) {
  io_iterator_t iter;
  kern_return_t r =
    IOServiceGetMatchingServices(kIOMasterPortDefault,
				 IOServiceMatching("IOService"), &iter);

  if (r != KERN_SUCCESS) {
    fprintf(stderr, " [!] IOServiceGetMatchingServices() failed\n");
    return -1;
  }

  io_object_t service;
  while ((service = IOIteratorNext(iter)) != IO_OBJECT_NULL) {
    /* Get service name */
    io_name_t name;
    r = IORegistryEntryGetName(service, name);
    if (r != KERN_SUCCESS) {
      fprintf(stderr, " [!] IORegistryEntryGetName() failed\n");
      IOObjectRelease(service);
      continue;
    }

    io_string_t path;
    r = IORegistryEntryGetPath(service, "IOService", path);

    /* Try to open service */
    io_connect_t port = (io_connect_t) 0;
    r = IOServiceOpen(service, mach_task_self(), 0, &port);
    IOObjectRelease(service);
    if (r != kIOReturnSuccess) {
      continue;
    }

    if (strstr(name, target_name)) {
      printf(" [+] Found service %s\n", name);
      *ptarget_port = port;
      return true;
    }

    IOServiceClose(port);
  }

  return false;
}
Beispiel #7
0
// gets the parent's Udi from an entry
static QString getParentDeviceUdi(const io_registry_entry_t &entry)
{
    io_registry_entry_t parent = 0;
    kern_return_t ret = IORegistryEntryGetParentEntry(entry, kIOServicePlane, &parent);
    if (ret != KERN_SUCCESS) {
        // don't release parent here - docs say only on success
        return QString();
    }

    QString result;
    io_string_t pathName;
    ret = IORegistryEntryGetPath(parent, kIOServicePlane, pathName);
    if (ret == KERN_SUCCESS)
        result = QString::fromUtf8(pathName);

    // now we can release the parent
    IOObjectRelease(parent);

    return result;
}
Beispiel #8
0
int main()
{
	mach_port_t masterPort;
	io_iterator_t iter = 0;
	io_service_t service = 0;
	kern_return_t ret;
	io_string_t path;

	ret = IOMasterPort(MACH_PORT_NULL, &masterPort);
	if (ret != KERN_SUCCESS) {
		printf("error: IOMasterPort returned 0x%08x\n", ret);
		goto failure;
	}

	ret = IOServiceGetMatchingServices(masterPort, IOServiceMatching(kVoodooHDAClassName), &iter);
	if (ret != KERN_SUCCESS) {
		printf("error: IOServiceGetMatchingServices returned 0x%08x\n", ret);
		goto failure;
	}
	while ((service = IOIteratorNext(iter)) != 0) {
		ret = IORegistryEntryGetPath(service, kIOServicePlane, path);
		if (ret != KERN_SUCCESS) {
	    	printf("error: IORegistryEntryGetPath returned 0x%08x\n", ret);
			goto failure;
		}
		printf("Found a device of class "kVoodooHDAClassName": %s\n\n", path);
		printMsgBuffer(service);
		IOObjectRelease(service);
	}

failure:
	if (service)
		IOObjectRelease(service);
	if (iter)
		IOObjectRelease(iter);

	return 0;
}
bool QextSerialEnumerator::getServiceDetailsOSX( io_object_t service, QextPortInfo* portInfo )
{
    bool retval = true;
    CFTypeRef bsdPathAsCFString = NULL;
    CFTypeRef productNameAsCFString = NULL;
    CFTypeRef vendorIdAsCFNumber = NULL;
    CFTypeRef productIdAsCFNumber = NULL;
    // check the name of the modem's callout device
    bsdPathAsCFString = IORegistryEntryCreateCFProperty(service, CFSTR(kIOCalloutDeviceKey),
                                                        kCFAllocatorDefault, 0);

    // wander up the hierarchy until we find the level that can give us the
    // vendor/product IDs and the product name, if available
    io_registry_entry_t parent;
    kern_return_t kernResult = IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent);
    while( kernResult == KERN_SUCCESS && !vendorIdAsCFNumber && !productIdAsCFNumber )
    {
        if(!productNameAsCFString)
            productNameAsCFString = IORegistryEntrySearchCFProperty(parent,
                                                                    kIOServicePlane,
                                                                    CFSTR("Product Name"),
                                                                    kCFAllocatorDefault, 0);
        vendorIdAsCFNumber = IORegistryEntrySearchCFProperty(parent,
                                                             kIOServicePlane,
                                                             CFSTR(kUSBVendorID),
                                                             kCFAllocatorDefault, 0);
        productIdAsCFNumber = IORegistryEntrySearchCFProperty(parent,
                                                              kIOServicePlane,
                                                              CFSTR(kUSBProductID),
                                                              kCFAllocatorDefault, 0);
        io_registry_entry_t oldparent = parent;
        kernResult = IORegistryEntryGetParentEntry(parent, kIOServicePlane, &parent);
        IOObjectRelease(oldparent);
    }

    io_string_t ioPathName;
    IORegistryEntryGetPath( service, kIOServicePlane, ioPathName );
    portInfo->physName = ioPathName;

    if( bsdPathAsCFString )
    {
        char path[MAXPATHLEN];
        if( CFStringGetCString((CFStringRef)bsdPathAsCFString, path,
                               PATH_MAX, kCFStringEncodingUTF8) )
            portInfo->portName = path;
        CFRelease(bsdPathAsCFString);
    }

    if(productNameAsCFString)
    {
        char productName[MAXPATHLEN];
        if( CFStringGetCString((CFStringRef)productNameAsCFString, productName,
                               PATH_MAX, kCFStringEncodingUTF8) )
            portInfo->friendName = productName;
        CFRelease(productNameAsCFString);
    }

    if(vendorIdAsCFNumber)
    {
        SInt32 vID;
        if(CFNumberGetValue((CFNumberRef)vendorIdAsCFNumber, kCFNumberSInt32Type, &vID))
            portInfo->vendorID = vID;
        CFRelease(vendorIdAsCFNumber);
    }

    if(productIdAsCFNumber)
    {
        SInt32 pID;
        if(CFNumberGetValue((CFNumberRef)productIdAsCFNumber, kCFNumberSInt32Type, &pID))
            portInfo->productID = pID;
        CFRelease(productIdAsCFNumber);
    }
    IOObjectRelease(service);
    return retval;
}
Beispiel #10
0
struct hid_device_info  HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)
{
	struct hid_device_info *root = NULL; /* return object */
	struct hid_device_info *cur_dev = NULL;
	CFIndex num_devices;
	int i;

	/* Set up the HID Manager if it hasn't been done */
	if (hid_init() < 0)
		return NULL;

	/* give the IOHIDManager a chance to update itself */
	process_pending_events();

	/* Get a list of the Devices */
	IOHIDManagerSetDeviceMatching(hid_mgr, NULL);
	CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);

	/* Convert the list into a C array so we can iterate easily. */
	num_devices = CFSetGetCount(device_set);
	IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef));
	CFSetGetValues(device_set, (const void **) device_array);

	/* Iterate over each device, making an entry for it. */
	for (i = 0; i < num_devices; i++) {
		unsigned short dev_vid;
		unsigned short dev_pid;
		#define BUF_LEN 256
		wchar_t buf[BUF_LEN];

		IOHIDDeviceRef dev = device_array[i];

        if (!dev) {
            continue;
        }
		dev_vid = get_vendor_id(dev);
		dev_pid = get_product_id(dev);

		/* Check the VID/PID against the arguments */
		if ((vendor_id == 0x0 || vendor_id == dev_vid) &&
		    (product_id == 0x0 || product_id == dev_pid)) {
			struct hid_device_info *tmp;
			io_object_t iokit_dev;
			kern_return_t res;
			io_string_t path;

			/* VID/PID match. Create the record. */
			tmp = malloc(sizeof(struct hid_device_info));
			if (cur_dev) {
				cur_dev->next = tmp;
			}
			else {
				root = tmp;
			}
			cur_dev = tmp;

			/* Get the Usage Page and Usage for this device. */
			cur_dev->usage_page = get_int_property(dev, CFSTR(kIOHIDPrimaryUsagePageKey));
			cur_dev->usage = get_int_property(dev, CFSTR(kIOHIDPrimaryUsageKey));

			/* Fill out the record */
			cur_dev->next = NULL;

			/* Fill in the path (IOService plane) */
			iokit_dev = hidapi_IOHIDDeviceGetService(dev);
			res = IORegistryEntryGetPath(iokit_dev, kIOServicePlane, path);
			if (res == KERN_SUCCESS)
				cur_dev->path = strdup(path);
			else
				cur_dev->path = strdup("");

			/* Serial Number */
			get_serial_number(dev, buf, BUF_LEN);
			cur_dev->serial_number = dup_wcs(buf);

			/* Manufacturer and Product strings */
			get_manufacturer_string(dev, buf, BUF_LEN);
			cur_dev->manufacturer_string = dup_wcs(buf);
			get_product_string(dev, buf, BUF_LEN);
			cur_dev->product_string = dup_wcs(buf);

			/* VID/PID */
			cur_dev->vendor_id = dev_vid;
			cur_dev->product_id = dev_pid;

			/* Release Number */
			cur_dev->release_number = get_int_property(dev, CFSTR(kIOHIDVersionNumberKey));

			/* Interface Number (Unsupported on Mac)*/
			cur_dev->interface_number = -1;
		}
	}

	free(device_array);
	CFRelease(device_set);

	return root;
}
//================================================================================================
//
//  DeviceAdded
//
//  This routine is the callback for our IOServiceAddMatchingNotification.  When we get called
//  we will look at all the devices that were added and we will:
//
//  1.  Create some private data to relate to each device (in this case we use the service's name
//      and the location ID of the device
//  2.  Submit an IOServiceAddInterestNotification of type kIOGeneralInterest for this device,
//      using the refCon field to store a pointer to our private data.  When we get called with
//      this interest notification, we can grab the refCon and access our private data.
//
//================================================================================================
static void DeviceAdded(void *refCon, io_iterator_t iterator) {
	kern_return_t kr;
	io_service_t usbDevice;
	IOCFPlugInInterface **plugInInterface = NULL;
	SInt32 score;
	HRESULT res;

	while((usbDevice = IOIteratorNext(iterator))) {
		io_name_t deviceName;
		CFStringRef deviceNameAsCFString;
		UInt32 locationID;
		UInt16 vendorId;
		UInt16 productId;
		UInt16 addr;

		DeviceItem_t* deviceItem = new DeviceItem_t();

		// Get the USB device's name.
		kr = IORegistryEntryGetName(usbDevice, deviceName);
		if(KERN_SUCCESS != kr) {
			deviceName[0] = '\0';
		}

		deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, deviceName, kCFStringEncodingASCII);


		if(deviceNameAsCFString) {
			Boolean result;
			char    deviceName[MAXPATHLEN];

			// Convert from a CFString to a C (NUL-terminated)
			result = CFStringGetCString(deviceNameAsCFString,
										deviceName,
										sizeof(deviceName),
										kCFStringEncodingUTF8);

			if(result) {
				deviceItem->deviceParams.deviceName = deviceName;
			}

			CFRelease(deviceNameAsCFString);
		}

		CFStringRef manufacturerAsCFString = (CFStringRef)IORegistryEntrySearchCFProperty(
				usbDevice,
				kIOServicePlane,
				CFSTR(kUSBVendorString),
				kCFAllocatorDefault,
				kIORegistryIterateRecursively
			);

		if(manufacturerAsCFString) {
			Boolean result;
			char    manufacturer[MAXPATHLEN];

			// Convert from a CFString to a C (NUL-terminated)
			result = CFStringGetCString(
					manufacturerAsCFString,
					manufacturer,
					sizeof(manufacturer),
					kCFStringEncodingUTF8
				);

			if(result) {
				deviceItem->deviceParams.manufacturer = manufacturer;
			}

			CFRelease(manufacturerAsCFString);
		}

		CFStringRef serialNumberAsCFString = (CFStringRef) IORegistryEntrySearchCFProperty(
				usbDevice,
				kIOServicePlane,
				CFSTR(kUSBSerialNumberString),
				kCFAllocatorDefault,
				kIORegistryIterateRecursively
			);

		if(serialNumberAsCFString) {
			Boolean result;
			char    serialNumber[MAXPATHLEN];

			// Convert from a CFString to a C (NUL-terminated)
			result = CFStringGetCString(
					serialNumberAsCFString,
					serialNumber,
					sizeof(serialNumber),
					kCFStringEncodingUTF8
				);

			if(result) {
				deviceItem->deviceParams.serialNumber = serialNumber;
			}

			CFRelease(serialNumberAsCFString);
		}


		// Now, get the locationID of this device. In order to do this, we need to create an IOUSBDeviceInterface
		// for our device. This will create the necessary connections between our userland application and the
		// kernel object for the USB Device.
		kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score);

		if((kIOReturnSuccess != kr) || !plugInInterface) {
			fprintf(stderr, "IOCreatePlugInInterfaceForService returned 0x%08x.\n", kr);
			continue;
		}

		stDeviceListItem *deviceListItem = new stDeviceListItem();

		// Use the plugin interface to retrieve the device interface.
		res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID*) &deviceListItem->deviceInterface);

		// Now done with the plugin interface.
		(*plugInInterface)->Release(plugInInterface);

		if(res || deviceListItem->deviceInterface == NULL) {
			fprintf(stderr, "QueryInterface returned %d.\n", (int) res);
			continue;
		}

		// Now that we have the IOUSBDeviceInterface, we can call the routines in IOUSBLib.h.
		// In this case, fetch the locationID. The locationID uniquely identifies the device
		// and will remain the same, even across reboots, so long as the bus topology doesn't change.

		kr = (*deviceListItem->deviceInterface)->GetLocationID(deviceListItem->deviceInterface, &locationID);
		if(KERN_SUCCESS != kr) {
			fprintf(stderr, "GetLocationID returned 0x%08x.\n", kr);
			continue;
		}
		std::stringstream sstream;
		sstream << std::hex << locationID;
		deviceItem->deviceParams.locationId = sstream.str();

		kr = (*deviceListItem->deviceInterface)->GetDeviceAddress(deviceListItem->deviceInterface, &addr);
		if(KERN_SUCCESS != kr) {
			fprintf(stderr, "GetDeviceAddress returned 0x%08x.\n", kr);
			continue;
		}
		deviceItem->deviceParams.deviceAddress = addr;


		kr = (*deviceListItem->deviceInterface)->GetDeviceVendor(deviceListItem->deviceInterface, &vendorId);
		if(KERN_SUCCESS != kr) {
			fprintf(stderr, "GetDeviceVendor returned 0x%08x.\n", kr);
			continue;
		}
		deviceItem->deviceParams.vendorId = vendorId;

		kr = (*deviceListItem->deviceInterface)->GetDeviceProduct(deviceListItem->deviceInterface, &productId);
		if(KERN_SUCCESS != kr) {
			fprintf(stderr, "GetDeviceProduct returned 0x%08x.\n", kr);
			continue;
		}
		deviceItem->deviceParams.productId = productId;


		// Extract path name as unique key
		io_string_t pathName;
		IORegistryEntryGetPath(usbDevice, kIOServicePlane, pathName);
		deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, pathName, kCFStringEncodingASCII);
		char cPathName[MAXPATHLEN];

		if(deviceNameAsCFString) {
			Boolean result;

			// Convert from a CFString to a C (NUL-terminated)
			result = CFStringGetCString(
					deviceNameAsCFString,
					cPathName,
					sizeof(cPathName),
					kCFStringEncodingUTF8
				);


			CFRelease(deviceNameAsCFString);
		}

		AddItemToList(cPathName, deviceItem);
		deviceListItem->deviceItem = deviceItem;

		if(initialDeviceImport == false) {
			WaitForDeviceHandled();
			currentItem = &deviceItem->deviceParams;
			isAdded = true;
			uv_async_send(&async_handler);
		}

		// Register for an interest notification of this device being removed. Use a reference to our
		// private data as the refCon which will be passed to the notification callback.
		kr = IOServiceAddInterestNotification(
				gNotifyPort, // notifyPort
				usbDevice, // service
				kIOGeneralInterest, // interestType
				DeviceRemoved, // callback
				deviceListItem, // refCon
				&(deviceListItem->notification) // notification
			);

		if(KERN_SUCCESS != kr) {
			printf("IOServiceAddInterestNotification returned 0x%08x.\n", kr);
		}

		// Done with this USB device; release the reference added by IOIteratorNext
		kr = IOObjectRelease(usbDevice);
	}
}
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);
}
int main(int argc, char * argv[])
{
    kern_return_t       kr;
    io_iterator_t       iter;
    io_service_t        framebuffer;
    io_string_t         path;
    uint32_t            index, maxIndex;
    io_connect_t        connect;
    mach_timebase_info_data_t timebase;
    StdFBShmem_t *      shmem[16];
    vm_size_t           shmemSize;
    CFNumberRef         clk, count;
    vm_address_t        mapAddr;

    kr = IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching(
                IOFRAMEBUFFER_CONFORMSTO), &iter);
    assert( KERN_SUCCESS == kr );

    for ( index = 0; 
            index++, (framebuffer = IOIteratorNext(iter));
            IOObjectRelease(framebuffer))
    {


        kr = IORegistryEntryGetPath(framebuffer, kIOServicePlane, path);
        assert( KERN_SUCCESS == kr );
        printf("\n/* [%d] Using device: %s */\n", index, path);

	clk = IORegistryEntryCreateCFProperty(framebuffer, CFSTR(kIOFBCurrentPixelClockKey),
								kCFAllocatorDefault, kNilOptions);
	count = IORegistryEntryCreateCFProperty(framebuffer, CFSTR(kIOFBCurrentPixelCountKey),
								kCFAllocatorDefault, kNilOptions);
	if (clk && count)
	{
	    float num, div;
	    CFNumberGetValue(clk, kCFNumberFloatType, &num);
	    CFNumberGetValue(count, kCFNumberFloatType, &div);
	    printf("clock %.0f, count %.0f, rate %f Hz, period %f us\n",
		    num, div, num / div, div * 1000 / num);
	}
	if (clk)
	    CFRelease(clk);
	if (count)
	    CFRelease(count);
    
	kr = mach_timebase_info(&timebase);
	assert(kIOReturnSuccess == kr);
    
	kr = IOServiceOpen(framebuffer, mach_task_self(), kIOFBSharedConnectType, &connect);
	if (kIOReturnSuccess != kr)
	{
    	    printf("IOServiceOpen(%x)\n", kr);
    	    continue;
    	}
	kr = IOConnectMapMemory(connect, kIOFBCursorMemory, mach_task_self(),
			&mapAddr, &shmemSize,
			kIOMapAnywhere);
	if (kIOReturnSuccess != kr)
	{
    	    printf("IOConnectMapMemory(%x)\n", kr);
    	    continue;
    	}
	shmem[index] = (StdFBShmem_t *) mapAddr;
    
 //     bzero( shmem, shmemSize); // make sure its read only!
    
	printf("screenBounds (%d, %d), (%d, %d)\n",
		shmem[index]->screenBounds.minx, shmem[index]->screenBounds.miny, 
		shmem[index]->screenBounds.maxx, shmem[index]->screenBounds.maxy);

    }
    maxIndex = index;
    while (true)
    {
	printf("\n");
	for (index = 0; index < maxIndex; index++)
	{
	    if (!shmem[index])
		continue;
    
	    uint64_t time  = (((uint64_t) shmem[index]->vblTime.hi) << 32 | shmem[index]->vblTime.lo);
	    uint64_t delta = (((uint64_t) shmem[index]->vblDelta.hi) << 32 | shmem[index]->vblDelta.lo);
	    double usecs = delta * timebase.numer / timebase.denom / 1e6;

		if (!delta) continue;
    
	    printf("[%d] time of last VBL 0x%qx, delta %qd (%f us), count %qd, measured delta %qd(%f%%), drift %qd(%qd%%)\n", 
		    index, time, delta, usecs, shmem[index]->vblCount,
		    shmem[index]->vblDeltaMeasured, ((shmem[index]->vblDeltaMeasured * 100.0) / delta),
		    shmem[index]->vblDrift, ((shmem[index]->vblDrift * 100) / delta));
	}
	for (index = 0; index < maxIndex; index++)
	{
	    if (!shmem[index]) continue;
		if ((shmem[index]->screenBounds.maxx - shmem[index]->screenBounds.minx) < 128) continue;

	    printf("[%d] cursorShow %d, hw %d, frame %d, loc (%d, %d), hs (%d, %d), cursorRect (%d, %d), (%d, %d), saveRect (%d, %d), (%d, %d)\n",
		    index, 
		    shmem[index]->cursorShow, shmem[index]->hardwareCursorActive, 
		    shmem[index]->frame, shmem[index]->cursorLoc.x, shmem[index]->cursorLoc.y,
			shmem[index]->hotSpot[0].x, shmem[index]->hotSpot[0].y,
		    shmem[index]->cursorRect.minx, shmem[index]->cursorRect.miny, 
		    shmem[index]->cursorRect.maxx, shmem[index]->cursorRect.maxy,
		    shmem[index]->saveRect.minx, shmem[index]->saveRect.miny, 
		    shmem[index]->saveRect.maxx, shmem[index]->saveRect.maxy);
	}
	sleep(1);
    }
    
    exit(0);
    return(0);
}
// first look up the media object, then create a
// custom matching dictionary that should be persistent
// from boot to boot
int addMatchingInfoForBSDName(BLContextPtr context,
			      mach_port_t masterPort,
			      CFMutableDictionaryRef dict,
			      const char *bsdName,
                  bool shortForm)
{
    io_service_t                media = IO_OBJECT_NULL, checkMedia = IO_OBJECT_NULL;
    CFStringRef                 uuid = NULL;
    CFMutableDictionaryRef      propDict = NULL;
    kern_return_t               kret;
    CFStringRef			lastBSDName = NULL;

    lastBSDName = CFStringCreateWithCString(kCFAllocatorDefault,
					    bsdName,
					    kCFStringEncodingUTF8);

    propDict = IOBSDNameMatching(masterPort, 0, bsdName);
    CFDictionarySetValue(propDict, CFSTR(kIOProviderClassKey), CFSTR(kIOMediaClass));
    
    media = IOServiceGetMatchingService(masterPort,
                                        propDict);
    propDict = NULL;
    
    if(media == IO_OBJECT_NULL) {
        contextprintf(context, kBLLogLevelError, "Could not find object for %s\n", bsdName);
        CFRelease(lastBSDName);
        return 1;
    }
    
    uuid = IORegistryEntryCreateCFProperty(media, CFSTR(kIOMediaUUIDKey),
                                           kCFAllocatorDefault, 0);
    if(uuid == NULL) {
        CFUUIDRef       fsuuid = NULL;
		CFStringRef     fsuuidstr = NULL;        
		io_string_t path;
#if USE_DISKARBITRATION
        DASessionRef    session = NULL;
        DADiskRef       dadisk = NULL;
		
        contextprintf(context, kBLLogLevelVerbose, "IOMedia %s does not have a partition %s\n",
                      bsdName, kIOMediaUUIDKey);
		
        session = DASessionCreate(kCFAllocatorDefault);
        if(session) {
            dadisk = DADiskCreateFromIOMedia(kCFAllocatorDefault, session, 
                                             media);
            if(dadisk) {
                CFDictionaryRef descrip = DADiskCopyDescription(dadisk);
                if(descrip) {
                    fsuuid = CFDictionaryGetValue(descrip, kDADiskDescriptionVolumeUUIDKey);
                    
                    if(fsuuid)
                        CFRetain(fsuuid);
                    CFRelease(descrip);
                }
                
                CFRelease(dadisk);
            }
            
            CFRelease(session);
        }
#endif // USE_DISKARBITRATION
		
        if(fsuuid) {
            char        fsuuidCString[64];
			
            fsuuidstr = CFUUIDCreateString(kCFAllocatorDefault, fsuuid);
            
            CFStringGetCString(fsuuidstr,fsuuidCString,sizeof(fsuuidCString),kCFStringEncodingUTF8);
            
            contextprintf(context, kBLLogLevelVerbose, "DADiskRef %s has Volume UUID %s\n",
                          bsdName, fsuuidCString);
            
            CFRelease(fsuuid);
		} else {
            contextprintf(context, kBLLogLevelVerbose, "IOMedia %s does not have a Volume UUID\n",
                          bsdName);
		}
		
		
		// we have a volume UUID, but our primary matching mechanism will be the device path
		
		kret = IORegistryEntryGetPath(media, kIODeviceTreePlane,path);
		if(kret) {
			contextprintf(context, kBLLogLevelVerbose, "IOMedia %s does not have device tree path\n",
						  bsdName);
			
			propDict = IOServiceMatching(kIOMediaClass);
			CFDictionaryAddValue(propDict,  CFSTR(kIOBSDNameKey), lastBSDName);
			
			// add UUID as hint
			if(fsuuidstr)
				CFDictionaryAddValue(dict, CFSTR("BLVolumeUUID"), fsuuidstr);
			
		} else {
			CFStringRef blpath = CFStringCreateWithCString(kCFAllocatorDefault, path, kCFStringEncodingUTF8);
			
			contextprintf(context, kBLLogLevelVerbose, "IOMedia %s has path %s\n",
						  bsdName, path);
			
			propDict = IOServiceMatching(kIOMediaClass);
			CFDictionaryAddValue(propDict, CFSTR(kIOPathMatchKey), blpath);
			CFRelease(blpath);
			
			// add UUID as hint
			if(fsuuidstr)
				CFDictionaryAddValue(dict, CFSTR("BLVolumeUUID"), fsuuidstr);
			
			CFDictionaryAddValue(dict, CFSTR("BLLastBSDName"), lastBSDName);
		}
		
		if(fsuuidstr) {
			CFRelease(fsuuidstr);
		}
		
    } else {
      CFMutableDictionaryRef propMatch;

        contextprintf(context, kBLLogLevelVerbose, "IOMedia %s has UUID %s\n",
                      bsdName, BLGetCStringDescription(uuid));

        propMatch = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
                              &kCFTypeDictionaryKeyCallBacks,
                              &kCFTypeDictionaryValueCallBacks);
        CFDictionaryAddValue(propMatch, CFSTR(kIOMediaUUIDKey), uuid);

        propDict = IOServiceMatching(kIOMediaClass);
        CFDictionaryAddValue(propDict,  CFSTR(kIOPropertyMatchKey), propMatch);
        CFRelease(propMatch);

        // add a hint to the top-level dict
        CFDictionaryAddValue(dict, CFSTR("BLLastBSDName"), lastBSDName);

        CFRelease(uuid);
    }

    // verify the dictionary matches
    CFRetain(propDict); // consumed below
    checkMedia = IOServiceGetMatchingService(masterPort,
					     propDict);
    
    if(IO_OBJECT_NULL == checkMedia
       || !IOObjectIsEqualTo(media, checkMedia)) {
      contextprintf(context, kBLLogLevelVerbose, "Inconsistent registry entries for %s\n",
		    bsdName);
      
      if(IO_OBJECT_NULL != checkMedia) IOObjectRelease(checkMedia);
      IOObjectRelease(media);
      CFRelease(lastBSDName);
      CFRelease(propDict);
      
      return 2;
    }
    
    IOObjectRelease(checkMedia);
    IOObjectRelease(media);

    CFDictionaryAddValue(dict, CFSTR("IOMatch"), propDict);        
    CFRelease(lastBSDName);
    CFRelease(propDict);

    if(shortForm) {
        CFDictionaryAddValue(dict, CFSTR("IOEFIShortForm"), kCFBooleanTrue);
    }
    
    return 0;
}
int main(int argc, char * argv[])
{
    kern_return_t 				kr;
    io_iterator_t 				iter;
    io_service_t  				framebuffer;
    io_string_t   				path;
    uint32_t                    index;
    CFIndex						idx;
    IODisplayModeInformation *  modeInfo;
    IODetailedTimingInformationV2 *timingInfo;

    CFDictionaryRef             dict;
    CFArrayRef                  modes;
    CFIndex                     count;
    CFDictionaryRef             mode;
    CFDataRef                   data;
    CFNumberRef                 num;

    kr = IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching(
                IOFRAMEBUFFER_CONFORMSTO), &iter);
    assert( KERN_SUCCESS == kr );

    for ( index = 0; 
            index++, (framebuffer = IOIteratorNext(iter));
            IOObjectRelease(framebuffer))
    {
        kr = IORegistryEntryGetPath(framebuffer, kIOServicePlane, path);
        assert( KERN_SUCCESS == kr );
        fprintf(stderr, "\n%s\n", path);

        dict = IORegistryEntryCreateCFProperty(framebuffer, CFSTR(kIOFBConfigKey),
                                                kCFAllocatorDefault, kNilOptions);
		if (!dict) continue;

        modes = CFDictionaryGetValue(dict, CFSTR(kIOFBModesKey));
        assert(modes);

        count = CFArrayGetCount(modes);
        for (idx = 0; idx < count; idx++)
        {
            mode = CFArrayGetValueAtIndex(modes, idx);

            data = CFDictionaryGetValue(mode, CFSTR(kIOFBModeDMKey));
            if (!data)
                continue;
            modeInfo = (IODisplayModeInformation *) CFDataGetBytePtr(data);

            data = CFDictionaryGetValue(mode, CFSTR(kIOFBModeTMKey));
            if (!data)
                continue;
            timingInfo = (IODetailedTimingInformationV2 *) CFDataGetBytePtr(data);

			IODisplayModeID modeID = 0;
            num = CFDictionaryGetValue(mode, CFSTR(kIOFBModeIDKey));
            if (num) CFNumberGetValue(num, kCFNumberSInt32Type, &modeID );

            printf("0x%x: %d x %d %d Hz - %d x %d - flags 0x%x\n",
            		modeID,
            		modeInfo->nominalWidth, modeInfo->nominalHeight, 
            		((modeInfo->refreshRate + 0x8000) >> 16),
            		modeInfo->imageWidth, modeInfo->imageHeight, 
            		modeInfo->flags);

			if (argc > 1)
			{
				printf("  horizontalScaledInset    %d\n", timingInfo->horizontalScaledInset);
				printf("  verticalScaledInset      %d\n", timingInfo->verticalScaledInset);
				printf("  scalerFlags              0x%x\n", timingInfo->scalerFlags);
				printf("  horizontalScaled         %d\n", timingInfo->horizontalScaled);
				printf("  verticalScaled           %d\n", timingInfo->verticalScaled);
				printf("  pixelClock               %lld\n", timingInfo->pixelClock);
				printf("  minPixelClock            %lld\n", timingInfo->minPixelClock);
				printf("  maxPixelClock            %lld\n", timingInfo->maxPixelClock);
				printf("  horizontalActive         %d\n", timingInfo->horizontalActive);
				printf("  horizontalBlanking       %d\n", timingInfo->horizontalBlanking);
				printf("  horizontalSyncOffset     %d\n", timingInfo->horizontalSyncOffset);
				printf("  horizontalSyncPulseWidth %d\n", timingInfo->horizontalSyncPulseWidth);
				printf("  verticalActive           %d\n", timingInfo->verticalActive);
				printf("  verticalBlanking         %d\n", timingInfo->verticalBlanking);
				printf("  verticalSyncOffset       %d\n", timingInfo->verticalSyncOffset);
				printf("  verticalSyncPulseWidth   %d\n", timingInfo->verticalSyncPulseWidth);
				printf("  horizontalBorderLeft     %d\n", timingInfo->horizontalBorderLeft);
				printf("  horizontalBorderRight    %d\n", timingInfo->horizontalBorderRight);
				printf("  verticalBorderTop        %d\n", timingInfo->verticalBorderTop);
				printf("  verticalBorderBottom     %d\n", timingInfo->verticalBorderBottom);
				printf("  horizontalSyncConfig     %d\n", timingInfo->horizontalSyncConfig);
				printf("  horizontalSyncLevel      %d\n", timingInfo->horizontalSyncLevel);
				printf("  verticalSyncConfig       0x%x\n", timingInfo->verticalSyncConfig);
				printf("  verticalSyncLevel        %d\n", timingInfo->verticalSyncLevel);
				printf("  signalConfig             0x%x\n", timingInfo->signalConfig);
				printf("  signalLevels             %d\n", timingInfo->signalLevels);
				printf("  numLinks                 %d\n", timingInfo->numLinks);
			}
		}
		CFRelease(dict);
    }
    IOObjectRelease(iter);
    exit(0);
    return(0);
}
int main( int argc, char * argv[] )
{
    mach_port_t   		masterPort;
    io_iterator_t 		iter;
    io_service_t 		service;
    kern_return_t		kr;
    CFMutableDictionaryRef	properties;
    CFStringRef			cfStr;

    kr = IOMasterPort( MACH_PORT_NULL, &masterPort);
    assert( KERN_SUCCESS == kr );

    // Look up the object we wish to open. This example uses simple class
    // matching (IOServiceMatching()) to look up the object that is the
    // AppleSamplePCI driver class instantiated by the kext.

    kr = IOServiceGetMatchingServices( masterPort,
                        IOServiceMatching( kAppleSamplePCIClassName ), &iter);
    assert( KERN_SUCCESS == kr );

    for( ;
      (service = IOIteratorNext(iter));
      IOObjectRelease(service)) {

        io_string_t path;
        kr = IORegistryEntryGetPath(service, kIOServicePlane, path);
        assert( KERN_SUCCESS == kr );
        printf("Found a device of class "kAppleSamplePCIClassName": %s\n", path);

        // print the value of kIONameMatchedKey property, as an example of 
	// getting properties from the registry. Property based access
	// doesn't require a user client connection.

        // grab a copy of the properties
        kr = IORegistryEntryCreateCFProperties( service, &properties,
                    kCFAllocatorDefault, kNilOptions );
        assert( KERN_SUCCESS == kr );
	
        cfStr = CFDictionaryGetValue( properties, CFSTR(kIONameMatchedKey) );
        if( cfStr) {
            const char * c = NULL;
            char * buffer = NULL;
            c = CFStringGetCStringPtr(cfStr, kCFStringEncodingMacRoman);
            if(!c) {
                CFIndex bufferSize = CFStringGetLength(cfStr) + 1;
                buffer = malloc(bufferSize);
                if(buffer) {
                    if(CFStringGetCString(cfStr, buffer, bufferSize, kCFStringEncodingMacRoman))
                        c = buffer;
                }
            }
            if(c)
                printf("it matched on name \"%s\"\n", c);
            if(buffer)
                free(buffer);
        }
        CFRelease( properties );

        // test out the user client
        Test( masterPort, service );
    }
    IOObjectRelease(iter);

    exit(0);
    return(0);
}