Example #1
0
void InitUPSNotifications()
{
    CFMutableDictionaryRef 	matchingDict;
    CFMutableDictionaryRef	propertyDict;
    kern_return_t		kr;

    // Create a notification port and add its run loop event source to our run loop
    // This is how async notifications get set up.
    //
    gNotifyPort = IONotificationPortCreate(kIOMasterPortDefault);
    CFRunLoopAddSource(	CFRunLoopGetCurrent(), 
                        IONotificationPortGetRunLoopSource(gNotifyPort), 
                        kCFRunLoopDefaultMode);

    // Create the IOKit notifications that we need
    //
    matchingDict = IOServiceMatching(kIOServiceClass); 
    
    if (!matchingDict)
	return;    
        
    propertyDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 
                    0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);

    if (!propertyDict)
    {
        CFRelease(matchingDict);
	return;
    }
        
    // We are only interested in devices that have kIOUPSDeviceKey property set
    CFDictionarySetValue(propertyDict, CFSTR(kIOUPSDeviceKey), kCFBooleanTrue);
    
    CFDictionarySetValue(matchingDict, CFSTR(kIOPropertyMatchKey), propertyDict);
    
    CFRelease(propertyDict);


    // Now set up a notification to be called when a device is first matched by I/O Kit.
    // Note that this will not catch any devices that were already plugged in so we take
    // care of those later.
    kr = IOServiceAddMatchingNotification(gNotifyPort,			// notifyPort
                                          kIOFirstMatchNotification,	// notificationType
                                          matchingDict,			// matching
                                          UPSDeviceAdded,		// callback
                                          NULL,				// refCon
                                          &gAddedIter			// notification
                                          );

    if ( kr != kIOReturnSuccess )
        return;
        
    UPSDeviceAdded( NULL, gAddedIter );
}
Example #2
0
bool HIDDevice::setupDevicePluggedInNotification()
{
    
    // Setup notification when devices are plugged in.
    RepluggedNotificationPort = IONotificationPortCreate(kIOMasterPortDefault);
    
    CFRunLoopSourceRef notificationRunLoopSource =
        IONotificationPortGetRunLoopSource(RepluggedNotificationPort);
    
    CFRunLoopAddSource(HIDManager->getRunLoop(),
                       notificationRunLoopSource,
                       kCFRunLoopDefaultMode);
    
    CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
    
    // Have to specify vendorId and productId. Doesn't seem to accept additional
    // things like serial number.
    SInt32 vendorId = DevDesc.VendorId;
    CFNumberRef numberRef = CFNumberCreate(kCFAllocatorDefault,
                                           kCFNumberSInt32Type,
                                           &vendorId);
    CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), numberRef);
    CFRelease(numberRef);
    
    SInt32 deviceProductId = DevDesc.ProductId;
    numberRef = CFNumberCreate(kCFAllocatorDefault,
                               kCFNumberSInt32Type,
                               &deviceProductId);
    CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), numberRef);
    CFRelease(numberRef);
    
    kern_return_t result =
            IOServiceAddMatchingNotification(RepluggedNotificationPort,
                                             kIOMatchedNotification,
                                             matchingDict,
                                             staticDeviceAddedCallback,
                                             this,
                                             &RepluggedNotification);
    
    if (result != KERN_SUCCESS)
    {
        CFRelease(RepluggedNotificationPort);
        RepluggedNotificationPort = 0;
        return false;
    }
    
    // Iterate through to arm.
    while (IOIteratorNext(RepluggedNotification))
    {
	}
    
    return true;
}
Example #3
0
io_connect_t IORegisterForSystemPower ( void * refcon,
                                        IONotificationPortRef * thePortRef,
                                        IOServiceInterestCallback callback,
                                        io_object_t * root_notifier )
{
    io_connect_t                fb = IO_OBJECT_NULL;
    IONotificationPortRef       notify = NULL;
    kern_return_t               kr;
    io_service_t                obj = IO_OBJECT_NULL;
     
    *root_notifier = IO_OBJECT_NULL;

    notify = IONotificationPortCreate(MACH_PORT_NULL);

    obj = IORegistryEntryFromPath( IO_OBJECT_NULL,
                    kIOPowerPlane ":/IOPowerConnection/IOPMrootDomain");

    if( obj == IO_OBJECT_NULL) goto failure_exit;
    
    kr = IOServiceOpen( obj,mach_task_self(), 0, &fb);

    if ( (kr != kIOReturnSuccess) || (fb == IO_OBJECT_NULL) )  {
        goto failure_exit;
    }

    kr = IOServiceAddInterestNotification(
                            notify,obj,kIOAppPowerStateInterest,
                            callback,refcon,root_notifier);

    IOObjectRelease(obj);
    if ( kr == KERN_SUCCESS ) {
        // Successful exit case
        *thePortRef = notify;
        return fb;
    }
    
failure_exit:    
    if ( obj != IO_OBJECT_NULL) {
        IOObjectRelease(obj);
    }
    if ( notify != NULL) {
        IONotificationPortDestroy(notify);
    }
    if ( fb != IO_OBJECT_NULL) {
        IOServiceClose(fb);
    }
    if ( *root_notifier != IO_OBJECT_NULL) {
        IOObjectRelease(*root_notifier);
    }
    
    return IO_OBJECT_NULL;
}
Example #4
0
void IOKitEventPublisher::restart() {
  static std::vector<const std::string*> device_classes = {
      &kIOUSBDeviceClassName_,
      &kIOPCIDeviceClassName_,
      &kIOPlatformExpertDeviceClassName_,
      &kIOACPIPlatformDeviceClassName_,
      &kIOPlatformDeviceClassname_,
  };

  if (run_loop_ == nullptr) {
    return;
  }

  // Remove any existing stream.
  stop();

  {
    WriteLock lock(mutex_);
    port_ = IONotificationPortCreate(kIOMasterPortDefault);
    // Get a run loop source from the created IOKit notification port.
    auto run_loop_source = IONotificationPortGetRunLoopSource(port_);
    CFRunLoopAddSource(run_loop_, run_loop_source, kCFRunLoopDefaultMode);
  }

  publisher_started_ = false;
  for (const auto& class_name : device_classes) {
    // Service matching is USB for now, must find a way to get more!
    // Can provide a "IOPCIDevice" here too.
    auto matches = IOServiceMatching(class_name->c_str());

    // Register attach/detaches (could use kIOPublishNotification).
    // Notification types are defined in IOKitKeys.
    IOReturn result = kIOReturnSuccess + 1;
    {
      WriteLock lock(mutex_);
      result = IOServiceAddMatchingNotification(
          port_,
          kIOFirstMatchNotification,
          matches,
          (IOServiceMatchingCallback)deviceAttach,
          this,
          &iterator_);
    }
    if (result == kIOReturnSuccess) {
      deviceAttach(this, iterator_);
    }
  }
  publisher_started_ = true;
}
Example #5
0
static void *media_poll_func(void *)
{
	media_poll_loop = CFRunLoopGetCurrent();

	mach_port_t masterPort;
	kern_return_t kernResult = IOMasterPort(bootstrap_port, &masterPort);
	if (kernResult != KERN_SUCCESS) {
		fprintf(stderr, "IOMasterPort() returned %d\n", kernResult);
		return NULL;
	}

	CFMutableDictionaryRef matchingDictionary = IOServiceMatching(kIOCDMediaClass);
	if (matchingDictionary == NULL) {
		fprintf(stderr, "IOServiceMatching() returned a NULL dictionary\n");
		return NULL;
	}
	matchingDictionary = (CFMutableDictionaryRef)CFRetain(matchingDictionary);

	IONotificationPortRef notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
	CFRunLoopAddSource(media_poll_loop,
					   IONotificationPortGetRunLoopSource(notificationPort),
					   kCFRunLoopDefaultMode);

	io_iterator_t mediaArrivedIterator;
	kernResult = IOServiceAddMatchingNotification(notificationPort,
												  kIOMatchedNotification,
												  matchingDictionary,
												  (IOServiceMatchingCallback)media_arrived,
												  (void *)MEDIA_CD, &mediaArrivedIterator);
	if (kernResult != KERN_SUCCESS)
		fprintf(stderr, "IOServiceAddMatchingNotification() returned %d\n", kernResult);
	media_arrived(MEDIA_CD, mediaArrivedIterator);

	io_iterator_t mediaRemovedIterator;
	kernResult = IOServiceAddMatchingNotification(notificationPort,
												  kIOTerminatedNotification,
												  matchingDictionary,
												  (IOServiceMatchingCallback)media_removed,
												  (void *)MEDIA_CD, &mediaRemovedIterator);
	if (kernResult != KERN_SUCCESS)
		fprintf(stderr, "IOServiceAddMatchingNotification() returned %d\n", kernResult);
	media_removed(MEDIA_CD, mediaRemovedIterator);

	CFRunLoopRun();
	return NULL;
}
Example #6
0
static void HPEstablishPCCardNotification(void)
{
	io_iterator_t deviceAddedIterator;
	io_iterator_t deviceRemovedIterator;
	CFMutableDictionaryRef matchingDictionary;
	IONotificationPortRef notificationPort;
	IOReturn kret;

	notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
	CFRunLoopAddSource(CFRunLoopGetCurrent(),
		IONotificationPortGetRunLoopSource(notificationPort),
		kCFRunLoopDefaultMode);

	matchingDictionary = IOServiceMatching("IOPCCard16Device");
	if (!matchingDictionary)
	{
		Log1(PCSC_LOG_ERROR, "IOServiceMatching() failed");
	}
	matchingDictionary =
		(CFMutableDictionaryRef) CFRetain(matchingDictionary);

	kret = IOServiceAddMatchingNotification(notificationPort,
		kIOMatchedNotification,
		matchingDictionary, HPDeviceAppeared, NULL, &deviceAddedIterator);
	if (kret)
	{
		Log2(PCSC_LOG_ERROR,
			"IOServiceAddMatchingNotification()-1 failed with code %d", kret);
	}
	HPDeviceAppeared(NULL, deviceAddedIterator);

	kret = IOServiceAddMatchingNotification(notificationPort,
		kIOTerminatedNotification,
		matchingDictionary,
		HPDeviceDisappeared, NULL, &deviceRemovedIterator);
	if (kret)
	{
		Log2(PCSC_LOG_ERROR,
			"IOServiceAddMatchingNotification()-2 failed with code %d", kret);
	}
	HPDeviceDisappeared(NULL, deviceRemovedIterator);
}
void InitDetection() {
	kern_return_t kr;

	// Set up the matching criteria for the devices we're interested in. The matching criteria needs to follow
	// the same rules as kernel drivers: mainly it needs to follow the USB Common Class Specification, pp. 6-7.
	// See also Technical Q&A QA1076 "Tips on USB driver matching on Mac OS X"
	// <http://developer.apple.com/qa/qa2001/qa1076.html>.
	// One exception is that you can use the matching dictionary "as is", i.e. without adding any matching
	// criteria to it and it will match every IOUSBDevice in the system. IOServiceAddMatchingNotification will
	// consume this dictionary reference, so there is no need to release it later on.

	// Interested in instances of class
	// IOUSBDevice and its subclasses
	matchingDict = IOServiceMatching(kIOUSBDeviceClassName);

	if (matchingDict == NULL) {
		fprintf(stderr, "IOServiceMatching returned NULL.\n");
	}

	// Create a notification port and add its run loop event source to our run loop
	// This is how async notifications get set up.

	gNotifyPort = IONotificationPortCreate(kIOMasterPortDefault);

	// Now set up a notification to be called when a device is first matched by I/O Kit.
	kr = IOServiceAddMatchingNotification(
			gNotifyPort, // notifyPort
			kIOFirstMatchNotification, // notificationType
			matchingDict, // matching
			DeviceAdded, // callback
			NULL, // refCon
			&gAddedIter // notification
		);

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

	// Iterate once to get already-present devices and arm the notification
	DeviceAdded(NULL, gAddedIter);
	initialDeviceImport = false;
}
static int
InitUSB()
{
    CFMutableDictionaryRef  matchingDict;
    CFRunLoopSourceRef      runLoopSource;

    //* To set up asynchronous notifications, create a notification port and
    //* add its run loop event source to the program's run loop
    notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
    runLoopSource = IONotificationPortGetRunLoopSource(notificationPort);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);

    //* Create our matching dictionary to find the Android device's
    //* adb interface
    //* IOServiceAddMatchingNotification consumes the reference, so we do
    //* not need to release this
    matchingDict = IOServiceMatching(kIOUSBInterfaceClassName);

    if (!matchingDict) {
        DBG("ERR: Couldn't create USB matching dictionary.\n");
        return -1;
    }

    //* We have to get notifications for all potential candidates and test them
    //* at connection time because the matching rules don't allow for a
    //* USB interface class of 0xff for class+subclass+protocol matches
    //* See https://developer.apple.com/library/mac/qa/qa1076/_index.html
    IOServiceAddMatchingNotification(
            notificationPort,
            kIOFirstMatchNotification,
            matchingDict,
            AndroidInterfaceAdded,
            NULL,
            &notificationIterator);

    //* Iterate over set of matching interfaces to access already-present
    //* devices and to arm the notification
    AndroidInterfaceAdded(NULL, notificationIterator);

    return 0;
}
void find_device () {
    CFMutableDictionaryRef matchingDict;
    CFNumberRef refUsage;
    CFNumberRef refUsagePageKey;
    SInt32 usage = 1;        /* mouse */
    SInt32 usagePageKey = 2; /* mouse */
    mach_port_t	masterPort;
    kern_return_t kr;

    kr = IOMasterPort (bootstrap_port, &masterPort);
    if (kr || !masterPort) {
        return;
    }

    gNotifyPort = IONotificationPortCreate (masterPort);
    CFRunLoopAddSource (CFRunLoopGetCurrent (), IONotificationPortGetRunLoopSource (gNotifyPort), kCFRunLoopDefaultMode);

    matchingDict = IOServiceMatching ("IOHIDDevice");

    if (!matchingDict) {
        return;
    }

    refUsage = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &usage);
    refUsagePageKey = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &usagePageKey);

    CFDictionarySetValue (matchingDict, CFSTR (kIOHIDPrimaryUsageKey), refUsagePageKey);
    CFDictionarySetValue (matchingDict, CFSTR (kIOHIDPrimaryUsagePageKey), refUsage);

    CFRelease (refUsage);
    CFRelease (refUsagePageKey);

    kr = IOServiceAddMatchingNotification (gNotifyPort, kIOFirstMatchNotification, matchingDict, init_device, NULL, &gAddedIter);

    if (kr != kIOReturnSuccess) {
        return;
    }

    init_device (NULL, gAddedIter);
}
CFStringRef copy_wifi_mac_address() {
    CFStringRef wifimac = NULL;
    IONotificationPortRef notify_port = 0;
    io_iterator_t iterator = 0;
    
    wifimac = lookup_mac_address("sdio");
    if (wifimac != NULL)
        return wifimac;

    wifimac = lookup_mac_address("wlan");
    if (wifimac != NULL)
        return wifimac;
    
    notify_port = IONotificationPortCreate(kIOMasterPortDefault);
    
    CFRunLoopSourceRef  runLoopSource = IONotificationPortGetRunLoopSource(notify_port);
    
    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);

    if (!IOServiceAddMatchingNotification( notify_port,
          kIOMatchedNotification,
          IOServiceMatching("IONetworkController"),
          (IOServiceMatchingCallback) search_wifi_mac_callback,
          &wifimac,
          &iterator
          ))
    {
        search_wifi_mac_callback((void**)&wifimac, iterator);
        while( wifimac == NULL)
        {
            if( CFRunLoopRunInMode(kCFRunLoopDefaultMode,0, TRUE) != kCFRunLoopRunHandledSource)
            {
                printf("giving up on wifi mac address\n");
                break;
            }
        }
    }
    IONotificationPortDestroy(notify_port);
    return wifimac;
}
InputHandler_MacOSX_HID::InputHandler_MacOSX_HID() : m_Sem( "Input thread started" ), m_ChangeLock( "Input handler change lock" )
{
	InputDevice id = DEVICE_KEYBOARD;

	// Set up the notify ports.
	m_NotifyPort = IONotificationPortCreate( kIOMasterPortDefault );

	// Add devices.
	LOG->Trace( "Finding keyboards" );
	AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard, id );
	
	LOG->Trace( "Finding mice" );
	AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse, id );
	
	LOG->Trace( "Finding joysticks" );
	id = DEVICE_JOY1;
	AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick, id );
	AddDevices( kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad, id );
	LOG->Trace( "Finding pump" );
	id = DEVICE_PUMP1;
	AddDevices( kHIDPage_VendorDefinedStart, 0x0001, id ); // Pump pads use the first vendor specific usage page.
	m_bChanged = false;

	if( PREFSMAN->m_bThreadedInput )
	{
		m_InputThread.SetName( "Input thread" );
		m_InputThread.Create( InputHandler_MacOSX_HID::Run, this );
		// Wait for the run loop to start before returning.
		m_Sem.Wait();
	}
	else
	{
		m_LoopRef = CFRunLoopRef( GetCFRunLoopFromEventLoop(GetMainEventLoop()) );
		CFRetain( m_LoopRef );
		StartDevices();
	}
}
Example #12
0
static void initializeDisplayNotifications (void)
{
	io_service_t		displayWrangler;
	IONotificationPortRef	notificationPort;
	io_object_t		notifier;

	displayWrangler = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceNameMatching("IODisplayWrangler"));
	if (! displayWrangler) {
		message (LOG_ERR, "IOServiceGetMatchingService failed\n");
		exit (1);
	}
	notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
	if (! notificationPort) {
		message (LOG_ERR, "IONotificationPortCreate failed\n");
		exit (1);
	}
	if (IOServiceAddInterestNotification(notificationPort, displayWrangler, kIOGeneralInterest,
		displayCallback, NULL, &notifier) != kIOReturnSuccess) {
		message (LOG_ERR, "IOServiceAddInterestNotification failed\n");
		exit (1);
	}
	CFRunLoopAddSource (CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notificationPort), kCFRunLoopDefaultMode);
	IOObjectRelease (displayWrangler);
}
Example #13
0
io_connect_t ks_connect_to_service(const char *className)
{
	kern_return_t kernResult;
    io_connect_t connect = IO_OBJECT_NULL;
	io_iterator_t iterator = IO_OBJECT_NULL;
    IONotificationPortRef notifyport = NULL;
	CFDictionaryRef	classToMatch;

	if ((classToMatch = IOServiceMatching(className)) == NULL) {
		asl_log(NULL, NULL, ASL_LEVEL_ERR,
            "IOServiceMatching failed for '%s'", className);
		return connect;
	}

    /* consumed by IOServiceGetMatchingServices, we need it if that fails. */
    CFRetain(classToMatch);
    kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault,
        classToMatch, &iterator);

    if (kernResult == KERN_SUCCESS) {
        CFRelease(classToMatch);
    } else {
        asl_log(NULL, NULL, ASL_LEVEL_WARNING,
            "IOServiceGetMatchingServices() failed %d", kernResult);

        notifyport = IONotificationPortCreate(kIOMasterPortDefault);
        if (!notifyport) {
            asl_log(NULL, NULL, ASL_LEVEL_ERR,
                "IONotificationPortCreate() failed");
            return connect;
        }

        kernResult = IOServiceAddMatchingNotification(notifyport,
            kIOFirstMatchNotification, classToMatch,
            ks_service_matching_callback, &connect, &iterator);
        if (kernResult) {
            asl_log(NULL, NULL, ASL_LEVEL_ERR,
                "IOServiceAddMatchingNotification() failed: %d", kernResult);
            return connect;
        }
    }

    /* Check whether it was already there before we registered for the
       notification. */
    ks_service_matching_callback(&connect, iterator);

    if (notifyport) {
        /* We'll get set up to wait for it to appear */
        if (connect == IO_OBJECT_NULL) {
            asl_log(NULL, NULL, ASL_LEVEL_ERR,
                "Waiting for %s to show up.", className);
            CFStringRef mode = CFSTR("WaitForCryptoService");
            CFRunLoopAddSource(CFRunLoopGetCurrent(),
                IONotificationPortGetRunLoopSource(notifyport), mode);
            CFRunLoopRunInMode(mode, 30.0, true);
            if (connect == MACH_PORT_NULL)
                asl_log(NULL, NULL, ASL_LEVEL_ERR, "Cannot find %s", className);
        }
        IONotificationPortDestroy(notifyport);
    }

    IOObjectRelease(iterator);

    if (connect != IO_OBJECT_NULL) {
        secdebug("iokit", "obtained connection for '%s'", className);
    }
    return connect;
}
Example #14
0
int main(int argc, const char *argv[])
{
    time_t current_time = time(NULL);
    char* c_time_string = ctime(&current_time);
    size_t l = strlen(c_time_string);
    if (l > 0)
        c_time_string[l-1] = 0;
    DEBUG_LOG("%s: VoodooPS2Daemon 1.7.12 starting...\n", c_time_string);

    // first check for trackpad driver
	g_ioservice = IOServiceGetMatchingService(0, IOServiceMatching("ApplePS2SynapticsTouchPad"));
	if (!g_ioservice)
	{
        // otherwise, talk to mouse driver
        g_ioservice = IOServiceGetMatchingService(0, IOServiceMatching("ApplePS2Mouse"));
        if (!g_ioservice)
        {
            DEBUG_LOG("No ApplePS2SynapticsTouchPad or ApplePS2Mouse found\n");
            return -1;
        }
	}
    
    // Set up a signal handler so we can clean up when we're interrupted from the command line
    // or otherwise asked to terminate.
    if (SIG_ERR == signal(SIGINT, SignalHandler1))
        DEBUG_LOG("Could not establish new SIGINT handler\n");
    if (SIG_ERR == signal(SIGTERM, SignalHandler1))
        DEBUG_LOG("Could not establish new SIGTERM handler\n");
    
    // First create a master_port for my task
    mach_port_t masterPort;
    kern_return_t kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
    if (kr || !masterPort)
    {
        DEBUG_LOG("ERR: Couldn't create a master IOKit Port(%08x)\n", kr);
        return -1;
    }
    
    // Create dictionary to match all USB devices
    CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
    if (!matchingDict)
    {
        DEBUG_LOG("Can't create a USB matching dictionary\n");
        mach_port_deallocate(mach_task_self(), masterPort);
        return -1;
    }
    
    // Create a notification port and add its run loop event source to our run loop
    // This is how async notifications get set up.
    g_NotifyPort = IONotificationPortCreate(masterPort);
    CFRunLoopSourceRef runLoopSource = IONotificationPortGetRunLoopSource(g_NotifyPort);
    CFRunLoopRef runLoop = CFRunLoopGetCurrent();
    CFRunLoopAddSource(runLoop, runLoopSource, kCFRunLoopDefaultMode);
    
    // Now set up a notification to be called when a device is first matched by I/O Kit.
    // Note that this will not catch any devices that were already plugged in so we take
    // care of those later.
    kr = IOServiceAddMatchingNotification(g_NotifyPort, kIOFirstMatchNotification, matchingDict, DeviceAdded, NULL, &g_AddedIter);
    
    // Iterate once to get already-present devices and arm the notification
    DeviceAdded(NULL, g_AddedIter);
    
    // Now done with the master_port
    mach_port_deallocate(mach_task_self(), masterPort);
    masterPort = 0;
    
    // Start the run loop. Now we'll receive notifications.
    CFRunLoopRun();
    
    // We should never get here
    DEBUG_LOG("Unexpectedly back from CFRunLoopRun()!\n");
    
    return 0;
}
Example #15
0
//  rawhid_open - open 1 or more devices
//
//    Inputs:
//	max = maximum number of devices to open
//	vid = Vendor ID, or -1 if any
//	pid = Product ID, or -1 if any
//	usage_page = top level usage page, or -1 if any
//	usage = top level usage number, or -1 if any
//    Output:
//	actual number of devices opened
//
int rawhid_open(int max, int vid, int pid, int usage_page, int usage)
{
   //***
   kern_return_t           result;
   mach_port_t             masterPort;
   CFMutableDictionaryRef  matchingDict;
   CFRunLoopSourceRef      runLoopSource;
   
   
   //Create a master port for communication with the I/O Kit
   result = IOMasterPort(MACH_PORT_NULL, &masterPort);
   if (result || !masterPort)
   {
      return -1;
   }
   
   //To set up asynchronous notifications, create a notification port and
   //add its run loop event source to the programs run loop
   gNotifyPort = IONotificationPortCreate(masterPort);
   runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort);
   CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource,
                      kCFRunLoopDefaultMode);
   // ***
   /*
   IOServiceAddMatchingNotification(
                                    gNotifyPort,
                                    kIOFirstMatchNotification,
                                    matchingDict,
                                    attach_callback, 
                                    NULL,
                                    &gAddedIter);
   */
   // ***
   
   static IOHIDManagerRef hid_manager=NULL;
   CFMutableDictionaryRef dict;
   CFNumberRef num;
   IOReturn ret;
	hid_t *p;
	int count=0;
   //fprintf(stderr,"fprintf rawhid_open\n");
	if (first_hid) free_all_hid();
	//printf("rawhid_open, max=%d\n", max);
   //fflush (stdout); 
	if (max < 1) return 0;
   // Start the HID Manager
   // http://developer.apple.com/technotes/tn2007/tn2187.html
	if (!hid_manager) {
      hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
      if (hid_manager == NULL || CFGetTypeID(hid_manager) != IOHIDManagerGetTypeID()) {
         if (hid_manager) CFRelease(hid_manager);
         return 0;
      }
	}
	if (vid > 0 || pid > 0 || usage_page > 0 || usage > 0) {
		// Tell the HID Manager what type of devices we want
      dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
                                       &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
      if (!dict) return 0;
		if (vid > 0) 
      {
			num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &vid);
			CFDictionarySetValue(dict, CFSTR(kIOHIDVendorIDKey), num);
			CFRelease(num);
		}
		if (pid > 0) 
      {
			num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &pid);
			CFDictionarySetValue(dict, CFSTR(kIOHIDProductIDKey), num);
			CFRelease(num);
		}
		if (usage_page > 0) 
      {
			num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage_page);
			CFDictionarySetValue(dict, CFSTR(kIOHIDPrimaryUsagePageKey), num);
			CFRelease(num);
		}
		if (usage > 0) 
      {
			num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage);
			CFDictionarySetValue(dict, CFSTR(kIOHIDPrimaryUsageKey), num);
			CFRelease(num);
		}
      IOHIDManagerSetDeviceMatching(hid_manager, dict);
      CFRelease(dict);
	} 
   else 
   {
      IOHIDManagerSetDeviceMatching(hid_manager, NULL);
	}
	// set up a callbacks for device attach & detach
   IOHIDManagerScheduleWithRunLoop(hid_manager, CFRunLoopGetCurrent(),
                                   kCFRunLoopDefaultMode);
   IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, attach_callback, NULL);
	IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, detach_callback, NULL);
   ret = IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone);
   if (ret != kIOReturnSuccess) 
   {
      IOHIDManagerUnscheduleFromRunLoop(hid_manager,
                                        CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
      CFRelease(hid_manager);
      return 0;
   }
	printf("run loop\n");
	// let it do the callback for all devices
	while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) == kCFRunLoopRunHandledSource) ;
	// count up how many were added by the callback
	for (p = first_hid; p; p = p->next) count++;
   
   usbstatus=count;
	return count;
}
Example #16
0
//================================================================================================
//  main
//================================================================================================
int main(int argc, const char *argv[])
{
    CFMutableDictionaryRef  matchingDict;
    CFRunLoopSourceRef      runLoopSource;
    CFNumberRef             numberRef;
    kern_return_t           kr;
    long                    usbVendor = kMyVendorID;
    long                    usbProduct = kMyProductID;
    sig_t                   oldHandler;
    
    // pick up command line arguments
    if (argc > 1) {
        usbVendor = atoi(argv[1]);
    }
    if (argc > 2) {
        usbProduct = atoi(argv[2]);
    }
    
    // Set up a signal handler so we can clean up when we're interrupted from the command line
    // Otherwise we stay in our run loop forever.
    oldHandler = signal(SIGINT, SignalHandler);
    if (oldHandler == SIG_ERR) {
        fprintf(stderr, "Could not establish new signal handler.");
    }
    
    fprintf(stderr, "Looking for devices matching vendor ID=%ld and product ID=%ld.\n", usbVendor, usbProduct);
    
    // Set up the matching criteria for the devices we're interested in. The matching criteria needs to follow
    // the same rules as kernel drivers: mainly it needs to follow the USB Common Class Specification, pp. 6-7.
    // See also Technical Q&A QA1076 "Tips on USB driver matching on Mac OS X" 
    // <http://developer.apple.com/qa/qa2001/qa1076.html>.
    // One exception is that you can use the matching dictionary "as is", i.e. without adding any matching 
    // criteria to it and it will match every IOUSBDevice in the system. IOServiceAddMatchingNotification will 
    // consume this dictionary reference, so there is no need to release it later on.
    
    matchingDict = IOServiceMatching(kIOUSBDeviceClassName);    // Interested in instances of class
    // IOUSBDevice and its subclasses
    if (matchingDict == NULL) {
        fprintf(stderr, "IOServiceMatching returned NULL.\n");
        return -1;
    }
    
    // We are interested in all USB devices (as opposed to USB interfaces).  The Common Class Specification
    // tells us that we need to specify the idVendor, idProduct, and bcdDevice fields, or, if we're not interested
    // in particular bcdDevices, just the idVendor and idProduct.  Note that if we were trying to match an 
    // IOUSBInterface, we would need to set more values in the matching dictionary (e.g. idVendor, idProduct, 
    // bInterfaceNumber and bConfigurationValue.
    
    // Create a CFNumber for the idVendor and set the value in the dictionary
    numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor);
    CFDictionarySetValue(matchingDict, 
                         CFSTR(kUSBVendorID), 
                         numberRef);
    CFRelease(numberRef);
    
    // Create a CFNumber for the idProduct and set the value in the dictionary
    numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct);
    CFDictionarySetValue(matchingDict, 
                         CFSTR(kUSBProductID), 
                         numberRef);
    CFRelease(numberRef);
    numberRef = NULL;
    
    // Create a notification port and add its run loop event source to our run loop
    // This is how async notifications get set up.
    
    gNotifyPort = IONotificationPortCreate(kIOMasterPortDefault);
    runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort);
    
    gRunLoop = CFRunLoopGetCurrent();
    CFRunLoopAddSource(gRunLoop, runLoopSource, kCFRunLoopDefaultMode);
    
    // Now set up a notification to be called when a device is first matched by I/O Kit.
    kr = IOServiceAddMatchingNotification(gNotifyPort,                  // notifyPort
                                          kIOFirstMatchNotification,    // notificationType
                                          matchingDict,                 // matching
                                          DeviceAdded,                  // callback
                                          NULL,                         // refCon
                                          &gAddedIter                   // notification
                                          );        
    
    // Iterate once to get already-present devices and arm the notification    
    DeviceAdded(NULL, gAddedIter);  
    
    // Start the run loop. Now we'll receive notifications.
    fprintf(stderr, "Starting run loop.\n\n");
    CFRunLoopRun();
    
    // We should never get here
    fprintf(stderr, "Unexpectedly back from CFRunLoopRun()!\n");
    return 0;
}
Example #17
0
int main (int argc, const char *argv[])
{
    mach_port_t 		masterPort;
    CFMutableDictionaryRef 	matchingDict;
    CFRunLoopSourceRef		runLoopSource;
    kern_return_t		kr;
    SInt32			usbVendor = kOurVendorID;
    SInt32			usbProduct = kOurProductID;
    sig_t			oldHandler;
    
    // pick up command line arguments
    if (argc > 1)
        usbVendor = atoi(argv[1]);
    if (argc > 2)
        usbProduct = atoi(argv[2]);

    // Set up a signal handler so we can clean up when we're interrupted from the command line
    // Otherwise we stay in our run loop forever.
    oldHandler = signal(SIGINT, SignalHandler);
    if (oldHandler == SIG_ERR)
        printf("Could not establish new signal handler");
        
    // first create a master_port for my task
    kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
    if (kr || !masterPort)
    {
        printf("ERR: Couldn't create a master IOKit Port(%08x)\n", kr);
        return -1;
    }

    printf("Looking for devices matching vendor ID=%ld and product ID=%ld\n", usbVendor, usbProduct);

    // Set up the matching criteria for the devices we're interested in
    matchingDict = IOServiceMatching(kIOUSBDeviceClassName);	// Interested in instances of class IOUSBDevice and its subclasses
    if (!matchingDict)
    {
        printf("Can't create a USB matching dictionary\n");
        mach_port_deallocate(mach_task_self(), masterPort);
        return -1;
    }
    
    // Add our vendor and product IDs to the matching criteria
    CFDictionarySetValue( 
            matchingDict, 
            CFSTR(kUSBVendorID), 
            CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor)); 
    CFDictionarySetValue( 
            matchingDict, 
            CFSTR(kUSBProductID), 
            CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct)); 

    // Create a notification port and add its run loop event source to our run loop
    // This is how async notifications get set up.
    gNotifyPort = IONotificationPortCreate(masterPort);
    runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort);
    
    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
    
    // Retain additional references because we use this same dictionary with four calls to 
    // IOServiceAddMatchingNotification, each of which consumes one reference.
    matchingDict = (CFMutableDictionaryRef) CFRetain( matchingDict ); 
    matchingDict = (CFMutableDictionaryRef) CFRetain( matchingDict ); 
    matchingDict = (CFMutableDictionaryRef) CFRetain( matchingDict ); 
    
    // Now set up two notifications, one to be called when a raw device is first matched by I/O Kit, and the other to be
    // called when the device is terminated.
    kr = IOServiceAddMatchingNotification(  gNotifyPort,
                                            kIOFirstMatchNotification,
                                            matchingDict,
                                            RawDeviceAdded,
                                            NULL,
                                            &gRawAddedIter );
                                            
    RawDeviceAdded(NULL, gRawAddedIter);	// Iterate once to get already-present devices and
                                                // arm the notification

    kr = IOServiceAddMatchingNotification(  gNotifyPort,
                                            kIOTerminatedNotification,
                                            matchingDict,
                                            RawDeviceRemoved,
                                            NULL,
                                            &gRawRemovedIter );
                                            
    RawDeviceRemoved(NULL, gRawRemovedIter);	// Iterate once to arm the notification
    
    // Change the USB product ID in our matching dictionary to the one the device will have once the
    // bulktest firmware has been downloaded.
    usbProduct = kOurProductIDBulkTest;
    
    CFDictionarySetValue( 
            matchingDict, 
            CFSTR(kUSBProductID), 
            CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct)); 

    // Now set up two more notifications, one to be called when a bulk test device is first matched by I/O Kit, and the other to be
    // called when the device is terminated.
    kr = IOServiceAddMatchingNotification(  gNotifyPort,
                                            kIOFirstMatchNotification,
                                            matchingDict,
                                            BulkTestDeviceAdded,
                                            NULL,
                                            &gBulkTestAddedIter );
                                            
    BulkTestDeviceAdded(NULL, gBulkTestAddedIter);	// Iterate once to get already-present devices and
                                                        // arm the notification

    kr = IOServiceAddMatchingNotification(  gNotifyPort,
                                            kIOTerminatedNotification,
                                            matchingDict,
                                            BulkTestDeviceRemoved,
                                            NULL,
                                            &gBulkTestRemovedIter );
                                            
    BulkTestDeviceRemoved(NULL, gBulkTestRemovedIter); 	// Iterate once to arm the notification

    // Now done with the master_port
    mach_port_deallocate(mach_task_self(), masterPort);
    masterPort = 0;

    // Start the run loop. Now we'll receive notifications.
    CFRunLoopRun();
        
    // We should never get here
    return 0;
}
Example #18
0
/* Function to scan the system for joysticks.
 * Joystick 0 should be the system default joystick.
 * This function should return the number of available joysticks, or -1
 * on an unrecoverable fatal error.
 */
int
SDL_SYS_JoystickInit(void)
{
    IOReturn result = kIOReturnSuccess;
    mach_port_t masterPort = 0;
    io_iterator_t hidObjectIterator = 0;
    CFMutableDictionaryRef hidMatchDictionary = NULL;
    io_object_t ioHIDDeviceObject = 0;
	io_iterator_t portIterator = 0;

    if (gpDeviceList) {
        SDL_SetError("Joystick: Device list already inited.");
        return -1;
    }

    result = IOMasterPort(bootstrap_port, &masterPort);
    if (kIOReturnSuccess != result) {
        SDL_SetError("Joystick: IOMasterPort error with bootstrap_port.");
        return -1;
    }

    /* Set up a matching dictionary to search I/O Registry by class name for all HID class devices. */
    hidMatchDictionary = IOServiceMatching(kIOHIDDeviceKey);
    if (hidMatchDictionary) {
        /* Add key for device type (joystick, in this case) to refine the matching dictionary. */

        /* NOTE: we now perform this filtering later
           UInt32 usagePage = kHIDPage_GenericDesktop;
           UInt32 usage = kHIDUsage_GD_Joystick;
           CFNumberRef refUsage = NULL, refUsagePage = NULL;

           refUsage = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &usage);
           CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsageKey), refUsage);
           refUsagePage = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &usagePage);
           CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsagePageKey), refUsagePage);
         */
    } else {
        SDL_SetError
            ("Joystick: Failed to get HID CFMutableDictionaryRef via IOServiceMatching.");
        return -1;
    }

    /*/ Now search I/O Registry for matching devices. */
    result =
        IOServiceGetMatchingServices(masterPort, hidMatchDictionary,
                                     &hidObjectIterator);
    /* Check for errors */
    if (kIOReturnSuccess != result) {
        SDL_SetError("Joystick: Couldn't create a HID object iterator.");
        return -1;
    }
    if (!hidObjectIterator) {   /* there are no joysticks */
        gpDeviceList = NULL;
        return 0;
    }
    /* IOServiceGetMatchingServices consumes a reference to the dictionary, so we don't need to release the dictionary ref. */

    /* build flat linked list of devices from device iterator */

    gpDeviceList = NULL;

    while ((ioHIDDeviceObject = IOIteratorNext(hidObjectIterator))) {
		AddDeviceHelper( ioHIDDeviceObject );
    }
    result = IOObjectRelease(hidObjectIterator);        /* release the iterator */
	
	/* now connect notification for new devices */
	notificationPort = IONotificationPortCreate(masterPort);
	hidMatchDictionary = IOServiceMatching(kIOHIDDeviceKey);

	CFRunLoopAddSource(CFRunLoopGetCurrent(), 
					   IONotificationPortGetRunLoopSource(notificationPort), 
					   kCFRunLoopDefaultMode);
	
	// Register for notifications when a serial port is added to the system
	result = IOServiceAddMatchingNotification(notificationPort,
															kIOFirstMatchNotification,
															hidMatchDictionary,
															JoystickDeviceWasAddedCallback,
															NULL,           
															&portIterator);
	while (IOIteratorNext(portIterator)) {}; // Run out the iterator or notifications won't start (you can also use it to iterate the available devices).

    return SDL_SYS_NumJoysticks();
}
Example #19
0
static IOReturn
HIDCreateOpenDeviceInterface(io_object_t hidDevice, recDevice * pDevice)
{
    IOReturn result = kIOReturnSuccess;
    HRESULT plugInResult = S_OK;
    SInt32 score = 0;
    IOCFPlugInInterface **ppPlugInInterface = NULL;

    if (NULL == pDevice->interface) {
        result =
            IOCreatePlugInInterfaceForService(hidDevice,
                                              kIOHIDDeviceUserClientTypeID,
                                              kIOCFPlugInInterfaceID,
                                              &ppPlugInInterface, &score);
        if (kIOReturnSuccess == result) {
            /* Call a method of the intermediate plug-in to create the device interface */
            plugInResult =
                (*ppPlugInInterface)->QueryInterface(ppPlugInInterface,
                                                     CFUUIDGetUUIDBytes
                                                     (kIOHIDDeviceInterfaceID),
                                                     (void *)
                                                     &(pDevice->interface));
            if (S_OK != plugInResult)
                HIDReportErrorNum
                    ("CouldnÕt query HID class device interface from plugInInterface",
                     plugInResult);
            (*ppPlugInInterface)->Release(ppPlugInInterface);
        } else
            HIDReportErrorNum
                ("Failed to create **plugInInterface via IOCreatePlugInInterfaceForService.",
                 result);
    }
    if (NULL != pDevice->interface) {
        result = (*(pDevice->interface))->open(pDevice->interface, 0);
        if (kIOReturnSuccess != result)
            HIDReportErrorNum
                ("Failed to open pDevice->interface via open.", result);
        else
		{
			pDevice->portIterator = 0;

			// It's okay if this fails, we have another detection method below
            (*(pDevice->interface))->setRemovalCallback(pDevice->interface,
                                                        HIDRemovalCallback,
                                                        pDevice, pDevice);
			
			/* now connect notification for new devices */
			pDevice->notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
			
			CFRunLoopAddSource(CFRunLoopGetCurrent(), 
							   IONotificationPortGetRunLoopSource(pDevice->notificationPort), 
							   kCFRunLoopDefaultMode);
			
			// Register for notifications when a serial port is added to the system
			result = IOServiceAddInterestNotification(pDevice->notificationPort,
													  hidDevice,
													  kIOGeneralInterest,
													  JoystickDeviceWasRemovedCallback,
													  pDevice,           
													  &pDevice->portIterator);
        	if (kIOReturnSuccess != result) {
            	HIDReportErrorNum
                	("Failed to register for removal callback.", result);		
			}	
		}

    }
    return result;
}
Example #20
0
//
// Add Notification observer from Device Driver.
//
bool createDeviceNotification(const char *className, const io_name_t interestName, IOServiceInterestCallback callback, io_object_t *notification)
{
	kern_return_t			kernReturn;
	bool					bResult = false;
	IONotificationPortRef	notificationObject = NULL;
	CFRunLoopSourceRef		notificationRunLoopSource = NULL;
	io_connect_t			dataPort;
	io_service_t			serviceObject;
	io_iterator_t			iterator = 0;
	CFDictionaryRef			classToMatch = NULL;
	
	// Obtain the device service.
	classToMatch = IOServiceMatching(className);
	if(classToMatch == NULL) {
		syslog(LOG_ERR, "IOServiceMatching returned a NULL dictionary.");
		
		return false;
	}
	
	notificationObject = IONotificationPortCreate(kIOMasterPortDefault);
	
	notificationRunLoopSource = IONotificationPortGetRunLoopSource(notificationObject);
	
	CFRetain(notificationRunLoopSource);
	
	CFRunLoopAddSource(
					   CFRunLoopGetCurrent(), 
					   notificationRunLoopSource,
					   kCFRunLoopCommonModes
					   );
	

	// Obtain the I/O Kit communication handle.
	kernReturn = IOMasterPort(MACH_PORT_NULL, &dataPort);
	if(kernReturn != KERN_SUCCESS) {
		syslog(LOG_ERR, "can't obtain I/O Kit's master port. %d\n", kernReturn);
		
		goto out;
	}
	
	kernReturn = IOServiceGetMatchingServices(dataPort, classToMatch, &iterator);
	classToMatch = NULL;	// It will release by IOServiceGetMatchingServices
	if(kernReturn != KERN_SUCCESS) {
		syslog(LOG_ERR, "IOServiceGetMatchingServices returned. %d\n", kernReturn);
		
		goto out;
	}
	
	serviceObject = IOIteratorNext(iterator);
/*	
	kernReturn = IOServiceAddInterestNotification(
												  notificationObject,
												  serviceObject,
												  kIOGeneralInterest,
												  callback,
												  NULL,
												  &notification
												  );
*/	
	kernReturn = IOServiceAddInterestNotification(
												  notificationObject,
												  serviceObject,
												  interestName,
												  callback,
												  NULL,
												  notification
												  );
	if(kernReturn != KERN_SUCCESS) {
		syslog(LOG_ERR, "IOServiceAddInterestNotification returned. %d\n", kernReturn);
		
		goto out;		
	}
	
	bResult = true;

out:
	if(iterator)					IOObjectRelease(iterator);
	if(notificationRunLoopSource)	CFRelease(notificationRunLoopSource);
	if(classToMatch)				CFRelease(classToMatch);
		
	return bResult;
}
Example #21
0
void HPMPrivate::run()
{
    mach_port_t masterPort = 0;
    IONotificationPortRef notifyPort = 0;
    io_iterator_t rawAddedIter = 0;
    io_iterator_t rawRemovedIter = 0;

    // Create an IOMasterPort for accessing IOKit
    kern_return_t kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
    if (kr || !masterPort)
    {
        qWarning() << Q_FUNC_INFO << "Unable to create a master I/O Kit port" << (void*) kr;
        return;
    }

    // Create a new dictionary for matching device classes
    CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
    if (!matchingDict)
    {
        qWarning() << Q_FUNC_INFO << "Unable to create a USB matching dictionary";
        mach_port_deallocate(mach_task_self(), masterPort);
        return;
    }

    // Take an extra reference because IOServiceAddMatchingNotification consumes one
    matchingDict = (CFMutableDictionaryRef) CFRetain(matchingDict);

    // Store the thread's run loop context
    loop = CFRunLoopGetCurrent();
    // New notification port
    notifyPort = IONotificationPortCreate(masterPort);

    CFRunLoopSourceRef runLoopSource = IONotificationPortGetRunLoopSource(notifyPort);
    CFRunLoopAddSource(loop, runLoopSource, kCFRunLoopDefaultMode);

    // Listen to device add notifications
    kr = IOServiceAddMatchingNotification(notifyPort,
                                          kIOFirstMatchNotification,
                                          matchingDict,
                                          onHPMPrivateRawDeviceAdded,
                                          (void*) this,
                                          &rawAddedIter);
    if (kr != kIOReturnSuccess)
        qFatal("Unable to add notification for device additions");

    // Iterate over set of matching devices to access already-present devices
    // and to arm the notification.
    onHPMPrivateRawDeviceAdded(this, rawAddedIter);

    // Listen to device removal notifications
    kr = IOServiceAddMatchingNotification(notifyPort,
                                          kIOTerminatedNotification,
                                          matchingDict,
                                          onHPMPrivateRawDeviceRemoved,
                                          (void*) this,
                                          &rawRemovedIter);
    if (kr != kIOReturnSuccess)
        qFatal("Unable to add notification for device termination");

    // Iterate over set of matching devices to release each one and to
    // arm the notification.
    onHPMPrivateRawDeviceRemoved(this, rawRemovedIter);

    // No longer needed
    mach_port_deallocate(mach_task_self(), masterPort);
    masterPort = 0;

    // Start the run loop inside this thread. The thread "stops" here.
    CFRunLoopRun();

    // Destroy the notification port when the thread exits
    IONotificationPortDestroy(notifyPort);
    notifyPort = 0;
}
Example #22
0
//================================================================================================
//	main
//================================================================================================
//
int main (int argc, const char *argv[])
{
    mach_port_t 		masterPort;
    CFMutableDictionaryRef 	matchingDict;
    CFRunLoopSourceRef		runLoopSource;
    CFNumberRef			numberRef;
    CFStringRef         stringRef;
    kern_return_t		kr;
    long			usbVendor = kMyVendorID;
    sig_t			oldHandler;

    // pick up command line arguments
    //
    if (argc > 1)
        usbVendor = atoi(argv[1]);

    // Set up a signal handler so we can clean up when we're interrupted from the command line
    // Otherwise we stay in our run loop forever.
    //
    oldHandler = signal(SIGINT, SignalHandler);
    if (oldHandler == SIG_ERR)
        printf("Could not establish new signal handler");

    // first create a master_port for my task
    //
    kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
    if (kr || !masterPort)
    {
        printf("ERR: Couldn't create a master IOKit Port(%08x)\n", kr);
        return -1;
    }

    printf("Looking for devices matching vendor ID=%ld\n", usbVendor);

    // Set up the matching criteria for the devices we're interested in.  The matching criteria needs to follow
    // the same rules as kernel drivers:  mainly it needs to follow the USB Common Class Specification, pp. 6-7.
    // See also http://developer.apple.com/qa/qa2001/qa1076.html
    // One exception is that you can use the matching dictionary "as is", i.e. without adding any matching criteria
    // to it and it will match every IOUSBDevice in the system.  IOServiceAddMatchingNotification will consume this
    // dictionary reference, so there is no need to release it later on.
    //
    matchingDict = IOServiceMatching(kIOUSBDeviceClassName);	// Interested in instances of class
    // IOUSBDevice and its subclasses
    if (!matchingDict)
    {
        printf("Can't create a USB matching dictionary\n");
        mach_port_deallocate(mach_task_self(), masterPort);
        return -1;
    }

    // We are interested in all USB Devices (as opposed to USB interfaces).  The Common Class Specification
    // tells us that we need to specify the idVendor, idProduct, and bcdDevice fields, or, if we're not interested
    // in particular bcdDevices, just the idVendor and idProduct.  Note that if we were trying to match an IOUSBInterface,
    // we would need to set more values in the matching dictionary (e.g. idVendor, idProduct, bInterfaceNumber and
    // bConfigurationValue.
    //

    // Create a CFNumber for the idVendor and set the value in the dictionary
    //
    numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor);
    CFDictionarySetValue(
        matchingDict,
        CFSTR(kUSBVendorID),
        numberRef);
    CFRelease(numberRef);
    numberRef = 0;

    // Create a CFString for the wildcard product ID and set the value in the dictionary
    //
    stringRef = CFSTR("*");
    CFDictionarySetValue(
        matchingDict,
        CFSTR(kUSBProductID),
        stringRef);
    CFRelease(stringRef);
    stringRef = 0;

    // Create a notification port and add its run loop event source to our run loop
    // This is how async notifications get set up.
    //
    gNotifyPort = IONotificationPortCreate(masterPort);
    runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort);

    gRunLoop = CFRunLoopGetCurrent();
    CFRunLoopAddSource(gRunLoop, runLoopSource, kCFRunLoopDefaultMode);

    // Now set up a notification to be called when a device is first matched by I/O Kit.
    // Note that this will not catch any devices that were already plugged in so we take
    // care of those later.
    //
    kr = IOServiceAddMatchingNotification(gNotifyPort,			// notifyPort
                                          kIOFirstMatchNotification,	// notificationType
                                          matchingDict,			// matching
                                          DeviceAdded,			// callback
                                          NULL,				// refCon
                                          &gAddedIter			// notification
                                         );

    // Iterate once to get already-present devices and arm the notification
    //
    DeviceAdded(NULL, gAddedIter);

    // Now done with the master_port
    mach_port_deallocate(mach_task_self(), masterPort);
    masterPort = 0;

    // Start the run loop. Now we'll receive notifications.
    //
    printf("Starting run loop.\n");
    CFRunLoopRun();

    // We should never get here
    //
    printf("Unexpectedly back from CFRunLoopRun()!\n");

    return 0;
}
/*
  Create matching dictionaries for the devices we want to get notifications for,
  and add them to the current run loop.  Invoke the callbacks that will be responding
  to these notifications once to arm them, and discover any devices that
  are currently connected at the time notifications are setup.
*/
void QextSerialEnumerator::setUpNotificationOSX( )
{
    kern_return_t kernResult;
    mach_port_t masterPort;
    CFRunLoopSourceRef notificationRunLoopSource;
    CFMutableDictionaryRef classesToMatch;
    CFMutableDictionaryRef cdcClassesToMatch;
    io_iterator_t portIterator;

    kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort);
    if (KERN_SUCCESS != kernResult) {
        qDebug() << "IOMasterPort returned:" << kernResult;
        return;
    }

    classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
    if (classesToMatch == NULL)
        qDebug("IOServiceMatching returned a NULL dictionary.");
    else
        CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));

    if( !(cdcClassesToMatch = IOServiceNameMatching("AppleUSBCDC") ) ) {
        qWarning("couldn't create cdc matching dict");
        return;
    }

    // Retain an additional reference since each call to IOServiceAddMatchingNotification consumes one.
    classesToMatch = (CFMutableDictionaryRef) CFRetain(classesToMatch);
    cdcClassesToMatch = (CFMutableDictionaryRef) CFRetain(cdcClassesToMatch);

    notificationPortRef = IONotificationPortCreate(masterPort);
    if(notificationPortRef == NULL) {
        qDebug("IONotificationPortCreate return a NULL IONotificationPortRef.");
        return;
    }

    notificationRunLoopSource = IONotificationPortGetRunLoopSource(notificationPortRef);
    if (notificationRunLoopSource == NULL) {
        qDebug("IONotificationPortGetRunLoopSource returned NULL CFRunLoopSourceRef.");
        return;
    }

    CFRunLoopAddSource(CFRunLoopGetCurrent(), notificationRunLoopSource, kCFRunLoopDefaultMode);

    kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOMatchedNotification, classesToMatch,
                                                  deviceDiscoveredCallbackOSX, this, &portIterator);
    if (kernResult != KERN_SUCCESS) {
        qDebug() << "IOServiceAddMatchingNotification return:" << kernResult;
        return;
    }

    // arm the callback, and grab any devices that are already connected
    deviceDiscoveredCallbackOSX( this, portIterator );

    kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOMatchedNotification, cdcClassesToMatch,
                                                  deviceDiscoveredCallbackOSX, this, &portIterator);
    if (kernResult != KERN_SUCCESS) {
        qDebug() << "IOServiceAddMatchingNotification return:" << kernResult;
        return;
    }

    // arm the callback, and grab any devices that are already connected
    deviceDiscoveredCallbackOSX( this, portIterator );

    kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOTerminatedNotification, classesToMatch,
                                                  deviceTerminatedCallbackOSX, this, &portIterator);
    if (kernResult != KERN_SUCCESS) {
        qDebug() << "IOServiceAddMatchingNotification return:" << kernResult;
        return;
    }

    // arm the callback, and clear any devices that are terminated
    deviceTerminatedCallbackOSX( this, portIterator );

    kernResult = IOServiceAddMatchingNotification(notificationPortRef, kIOTerminatedNotification, cdcClassesToMatch,
                                                  deviceTerminatedCallbackOSX, this, &portIterator);
    if (kernResult != KERN_SUCCESS) {
        qDebug() << "IOServiceAddMatchingNotification return:" << kernResult;
        return;
    }

    // arm the callback, and clear any devices that are terminated
    deviceTerminatedCallbackOSX( this, portIterator );
}
Example #24
0
int main (int argc, const char *argv[])
{
    mach_port_t                 masterPort;
    CFMutableDictionaryRef      matchingDict;
    CFRunLoopSourceRef          runLoopSource;
    kern_return_t               kr;
    SInt32                      usbVendor = kOurVendorID;
    SInt32                      usbProduct = kOurProductID;
    
    kr = IOMasterPort(MACH_PORT_NULL, &masterPort);

    if (kr || !masterPort)
    {
        printf("ERR: Couldn't create a master I/O Kit port(%08x)\n", kr);
        return -1;
    }

    // Setup matching dictionary for class IOUSBDevice and its subclasses

    matchingDict = IOServiceMatching(kIOUSBDeviceClassName);

    if (!matchingDict)
    {

        printf("couldn't craete a usb matching dictionary :(\n");

        mach_port_deallocate(mach_task_self(), masterPort);

        return -1;
    }

    // add vendor and product Ids to dict

    CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorName),
                            CFNumberCreate(kCFAllocatorDefault,
                                        kCFNumberSInt32Type, &usbVendor));

    CFDictionarySetValue(matchingDict, CFSTR(kUSBProductName),
                            CFNumberCreate(kCFAllocatorDefault,
                                        kCFNumberSInt32Type, &usbProduct));

    gNotifyPort = IONotificationPortCreate(masterPort);
    runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource,
                    kCFRunLoopDefaultMode);

    //Now set up two notifications: one to be called when a raw device
    //is first matched by the I/O Kit and another to be called when the
    //device is terminated
    //Notification of first match:
    kr = IOServiceAddMatchingNotification(gNotifyPort,
                    kIOFirstMatchNotification, matchingDict,
                    RawDeviceAdded, NULL, &gRawAddedIter);
    //Iterate over set of matching devices to access already-present devices
    //and to arm the notification
    RawDeviceAdded(NULL, gRawAddedIter);


/* 
    //Notification of termination:
    kr = IOServiceAddMatchingNotification(gNotifyPort,
                    kIOTerminatedNotification, matchingDict,
                    RawDeviceRemoved, NULL, &gRawRemovedIter);
    //Iterate over set of matching devices to release each one and to
    //arm the notification
    RawDeviceRemoved(NULL, gRawRemovedIter);
*/
    mach_port_deallocate(mach_task_self(), masterPort);
    masterPort = 0;

    CFRunLoopRun();

    return 0;
}