Example #1
0
void TorcUSBPrivOSX::DeviceAddedCallback(void *Context, io_iterator_t Iterator)
{
    if (!Context)
        return;

    io_service_t device;

    while ((device = IOIteratorNext(Iterator)))
    {
        TorcUSBDevice usbdevice = GetDevice(device);
        TorcUSBPrivOSX* context = static_cast<TorcUSBPrivOSX*>(Context);

        if (!usbdevice.m_product.isEmpty() && context)
        {
            io_object_t notification;
            if (kIOReturnSuccess == IOServiceAddInterestNotification(
                        context->GetNotificationPort(), device,
                        kIOGeneralInterest,
                        (IOServiceInterestCallback)DeviceRemovedCallback,
                        context, &notification))
            {
                context->AddDevice(usbdevice, device, notification);
            }
        }

        IOObjectRelease(device);
    }
}
void InputHandler_MacOSX_HID::AddDevices( int usagePage, int usage, InputDevice &id )
{
	io_iterator_t iter;
	CFDictionaryRef dict = GetMatchingDictionary( usagePage, usage );
	kern_return_t ret = IOServiceAddMatchingNotification( m_NotifyPort, kIOFirstMatchNotification, dict,
						InputHandler_MacOSX_HID::DeviceAdded, this, &iter );
	io_object_t device;

	if( ret != KERN_SUCCESS )
		return;

	m_vIters.push_back( iter );

	// Iterate over the devices and add them
	while( (device = IOIteratorNext(iter)) )
	{
		LOG->Trace( "\tFound device %d", id );
		HIDDevice *dev = MakeDevice( id );
		int num;

		if( !dev )
		{
			LOG->Trace( "\t\tInvalid id, deleting device" );
			IOObjectRelease( device );
			continue;
		}

		if( !dev->Open(device) || (num = dev->AssignIDs(id)) == -1 )
		{
			LOG->Trace( "\tFailed top open or assign id, deleting device" );
			delete dev;
			IOObjectRelease( device );
			continue;
		}
		io_iterator_t i;

		enum_add( id, num );
		m_vDevices.push_back( dev );

		ret = IOServiceAddInterestNotification(
			m_NotifyPort, device, kIOGeneralInterest,
			InputHandler_MacOSX_HID::DeviceChanged,
			this, &i
		);

		if( ret == KERN_SUCCESS )
			m_vIters.push_back( i );
		else
			LOG->Trace( "\t\tFailed to add device changed notification, deleting device" );
		IOObjectRelease( device );
	}
}
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;
}
static void DeviceAdded(void *refCon, io_iterator_t iter1)
{
    int oldMouseCount = g_MouseCount;
    io_service_t service;
    while ((service = IOIteratorNext(iter1)))
    {
        io_iterator_t iter2;
        kern_return_t kr = IORegistryEntryCreateIterator(service, kIOServicePlane, kIORegistryIterateRecursively, &iter2);
        if (KERN_SUCCESS != kr)
        {
            DEBUG_LOG("IORegistryEntryCreateIterator returned 0x%08x\n", kr);
            continue;
        }
        
        io_service_t temp;
        while ((temp = IOIteratorNext(iter2)))
        {
            io_name_t name;
            kr = IORegistryEntryGetName(temp, name);
            if (KERN_SUCCESS != kr)
                continue;
            if (0 == strcmp("IOHIDPointing", name) || 0 == strcmp("IOHIDPointingDevice", name))
            {
                NotificationData* pData = (NotificationData*)malloc(sizeof(*pData));
                if (pData == NULL)
                    continue;
                kr = IOServiceAddInterestNotification(g_NotifyPort, temp, kIOGeneralInterest, DeviceNotification, pData, &pData->notification);
                if (KERN_SUCCESS != kr)
                {
                    DEBUG_LOG("IOServiceAddInterestNotification returned 0x%08x\n", kr);
                    continue;
                }
                ++g_MouseCount;
                DEBUG_LOG("mouse count is now: %d\n", g_MouseCount);
            }
            IOObjectRelease(temp);
        }
        IOObjectRelease(iter2);
        IOObjectRelease(service);
    }
    if (oldMouseCount != g_MouseCount)
        SendMouseCount(g_MouseCount);
}
Example #5
0
static void iterate_devices(void* context, io_iterator_t iterator){
    io_service_t device;
    while((device = IOIteratorNext(iterator)) != 0){
        // Get the plugin interface for the device
        IOCFPlugInInterface** plugin;
        SInt32 score;
        kern_return_t err = IOCreatePlugInInterfaceForService(device, kIOHIDDeviceTypeID, kIOCFPlugInInterfaceID, &plugin, &score);
        if(err != kIOReturnSuccess){
            ckb_err("Failed to create device plugin: %x\n", err);
            continue;
        }
        // Get the device interface
        hid_dev_t handle;
        err = (*plugin)->QueryInterface(plugin, CFUUIDGetUUIDBytes(kIOHIDDeviceDeviceInterfaceID), (LPVOID*)&handle);
        if(err != kIOReturnSuccess){
            ckb_err("QueryInterface failed: %x\n", err);
            continue;
        }
        // Plugin is no longer needed
        IODestroyPlugInInterface(plugin);
        // Seize the device handle
        euid_guard_start;
        err = (*handle)->open(handle, kIOHIDOptionsTypeSeizeDevice);
        euid_guard_stop;
        if(err != kIOReturnSuccess){
            ckb_err("Failed to seize device: %x\n", err);
            continue;
        }
        // Connect it
        io_object_t* rm_notify = 0;
        usbdevice* kb = usbadd(handle, &rm_notify);
        if(kb)
            // If successful, register for removal notification
            IOServiceAddInterestNotification(notify, device, kIOGeneralInterest, remove_device, kb, rm_notify);
        else {
            // Otherwise, release it now
            (*handle)->close(handle, kIOHIDOptionsTypeNone);
            remove_device(0, device, kIOMessageServiceIsTerminated, 0);
        }
    }
}
Example #6
0
io_connect_t IORegisterApp( 
    void * refcon,
    io_service_t theDriver,
    IONotificationPortRef * thePortRef,
    IOServiceInterestCallback callback,
    io_object_t * notifier )
{
    io_connect_t        fb = MACH_PORT_NULL;
    kern_return_t        kr;
    
    *notifier = MACH_PORT_NULL;
    
    if ( theDriver == MACH_PORT_NULL ) goto failure_exit;

    kr = IOServiceOpen(theDriver, mach_task_self(), 0, &fb);

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

    kr = IOServiceAddInterestNotification(
                            *thePortRef, theDriver, kIOAppPowerStateInterest,
                            callback, refcon, notifier);

    if ( kr == KERN_SUCCESS ) {
        // Successful exit case
        return fb;
    }

failure_exit:
    if ( fb != MACH_PORT_NULL ) {
        IOServiceClose(fb);
    }
    if ( *notifier != MACH_PORT_NULL ) {
        IOObjectRelease(*notifier);
    }
    return MACH_PORT_NULL;
}
Example #7
0
void IOKitEventPublisher::deviceAttach(void* refcon, io_iterator_t iterator) {
  auto self = (IOKitEventPublisher*)refcon;
  io_service_t device;
  // The iterator may also have become invalid due to a change in the registry.
  // It is possible to reiterate devices, but that will cause duplicate events.
  while ((device = IOIteratorNext(iterator))) {
    // Create a notification tracker.
    {
      WriteLock lock(self->mutex_);
      auto tracker = std::make_shared<struct DeviceTracker>(self);
      self->devices_.push_back(tracker);
      IOServiceAddInterestNotification(self->port_,
                                       device,
                                       kIOGeneralInterest,
                                       (IOServiceInterestCallback)deviceDetach,
                                       tracker.get(),
                                       &(tracker->notification));
    }
    if (self->publisher_started_) {
      self->newEvent(device, IOKitEventContext::Action::DEVICE_ATTACH);
    }
    IOObjectRelease(device);
  }
}
Example #8
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 #9
0
void UPSDeviceAdded(void *refCon, io_iterator_t iterator)
{
    io_object_t             upsDevice           = MACH_PORT_NULL;
    UPSDataRef              upsDataRef          = NULL;
    CFDictionaryRef         upsProperties       = NULL;
    CFDictionaryRef         upsEvent            = NULL;
    CFSetRef                upsCapabilites 		= NULL;
    CFRunLoopSourceRef      upsEventSource      = NULL;
    CFRunLoopTimerRef       upsEventTimer       = NULL;
    CFTypeRef               typeRef             = NULL;
    IOCFPlugInInterface **	plugInInterface 	= NULL;
    IOUPSPlugInInterface_v140 **	upsPlugInInterface 	= NULL;
    HRESULT                 result              = S_FALSE;
    IOReturn                kr;
    SInt32                  score;
        
    while ( (upsDevice = IOIteratorNext(iterator)) )
    {        
        // Create the CF plugin for this device
        kr = IOCreatePlugInInterfaceForService(upsDevice, kIOUPSPlugInTypeID, 
                    kIOCFPlugInInterfaceID, &plugInInterface, &score);
                    
        if ( kr != kIOReturnSuccess )
            goto UPSDEVICEADDED_NONPLUGIN_CLEANUP;
            
        // Grab the new v140 interface
        result = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUPSPlugInInterfaceID_v140), 
                                                (LPVOID)&upsPlugInInterface);
                                                
        if ( ( result == S_OK ) && upsPlugInInterface )
        {
            kr = (*upsPlugInInterface)->createAsyncEventSource(upsPlugInInterface, &typeRef);
            
            if ((kr != kIOReturnSuccess) || !typeRef)
                goto UPSDEVICEADDED_FAIL;
                
            if ( CFGetTypeID(typeRef) == CFRunLoopTimerGetTypeID() )
            {
                upsEventTimer = (CFRunLoopTimerRef)typeRef;
                CFRunLoopAddTimer(CFRunLoopGetCurrent(), upsEventTimer, kCFRunLoopDefaultMode);
            }
            else if ( CFGetTypeID(typeRef) == CFRunLoopSourceGetTypeID() )
            {
                upsEventSource = (CFRunLoopSourceRef)typeRef;
                CFRunLoopAddSource(CFRunLoopGetCurrent(), upsEventSource, kCFRunLoopDefaultMode);
            }
        }
        // Couldn't grab the new interface.  Fallback on the old.
        else
        {
            result = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUPSPlugInInterfaceID), 
                                                (LPVOID)&upsPlugInInterface);
        }
                                                        
        // Got the interface
        if ( ( result == S_OK ) && upsPlugInInterface )
        {
            kr = (*upsPlugInInterface)->getProperties(upsPlugInInterface, &upsProperties);
            
            if (kr != kIOReturnSuccess)
                goto UPSDEVICEADDED_FAIL;
                
            upsDataRef = GetPrivateData(upsProperties);

            if ( !upsDataRef )
                goto UPSDEVICEADDED_FAIL;

            upsDataRef->upsPlugInInterface  = (IOUPSPlugInInterface **)upsPlugInInterface;
            upsDataRef->upsEventSource      = upsEventSource;
            upsDataRef->upsEventTimer       = upsEventTimer;
            upsDataRef->isPresent           = true;
            
            kr = (*upsPlugInInterface)->getCapabilities(upsPlugInInterface, &upsCapabilites);

            if (kr != kIOReturnSuccess)
                goto UPSDEVICEADDED_FAIL;

            kr = CreatePowerManagerUPSEntry(upsDataRef, upsProperties, upsCapabilites);

            if (kr != kIOReturnSuccess)
                goto UPSDEVICEADDED_FAIL;

            kr = (*upsPlugInInterface)->getEvent(upsPlugInInterface, &upsEvent);

            if (kr != kIOReturnSuccess)
                goto UPSDEVICEADDED_FAIL;

            ProcessUPSEvent(upsDataRef, upsEvent);

            (*upsPlugInInterface)->setEventCallback(upsPlugInInterface, UPSEventCallback, NULL, upsDataRef);

            IOServiceAddInterestNotification(	
                                    gNotifyPort,		// notifyPort
                                    upsDevice,			// service
                                    kIOGeneralInterest,		// interestType
                                    DeviceNotification,		// callback
                                    upsDataRef,			// refCon
                                    &(upsDataRef->notification)	// notification
                                    );
                                    
            goto UPSDEVICEADDED_CLEANUP;
        }

UPSDEVICEADDED_FAIL:
        // Failed to allocated a UPS interface.  Do some cleanup
        if ( upsPlugInInterface )
        {
            (*upsPlugInInterface)->Release(upsPlugInInterface);
            upsPlugInInterface = NULL;
        }
        
        if ( upsEventSource )
        {
            CFRunLoopRemoveSource(CFRunLoopGetCurrent(), upsEventSource, kCFRunLoopDefaultMode);
            upsEventSource = NULL;
        }

        if ( upsEventTimer )
        {
            CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), upsEventTimer, kCFRunLoopDefaultMode);
            upsEventSource = NULL;
        }

UPSDEVICEADDED_CLEANUP:
        // Clean up
        (*plugInInterface)->Release(plugInInterface);
        
UPSDEVICEADDED_NONPLUGIN_CLEANUP:
        IOObjectRelease(upsDevice);
    }
}
Example #10
0
static void
AndroidInterfaceAdded(void *refCon, io_iterator_t iterator)
{
    kern_return_t            kr;
    io_service_t             usbDevice;
    io_service_t             usbInterface;
    IOCFPlugInInterface      **plugInInterface = NULL;
    IOUSBInterfaceInterface220  **iface = NULL;
    IOUSBDeviceInterface197  **dev = NULL;
    HRESULT                  result;
    SInt32                   score;
    UInt32                   locationId;
    UInt16                   vendor;
    UInt16                   product;
    UInt8                    serialIndex;
    char                     serial[256];
    char                     devpathBuf[64];
    char                     *devpath = NULL;

    while ((usbInterface = IOIteratorNext(iterator))) {
        //* Create an intermediate interface plugin
        kr = IOCreatePlugInInterfaceForService(usbInterface,
                                               kIOUSBInterfaceUserClientTypeID,
                                               kIOCFPlugInInterfaceID,
                                               &plugInInterface, &score);
        IOObjectRelease(usbInterface);
        if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
            DBG("ERR: Unable to create an interface plug-in (%08x)\n", kr);
            continue;
        }

        //* This gets us the interface object
        result = (*plugInInterface)->QueryInterface(plugInInterface,
                CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID*)
                &iface);
        //* We only needed the plugin to get the interface, so discard it
        (*plugInInterface)->Release(plugInInterface);
        if (result || !iface) {
            DBG("ERR: Couldn't query the interface (%08x)\n", (int) result);
            continue;
        }

        //* this gets us an ioservice, with which we will find the actual
        //* device; after getting a plugin, and querying the interface, of
        //* course.
        //* Gotta love OS X
        kr = (*iface)->GetDevice(iface, &usbDevice);
        if (kIOReturnSuccess != kr || !usbDevice) {
            DBG("ERR: Couldn't grab device from interface (%08x)\n", kr);
            continue;
        }

        plugInInterface = NULL;
        score = 0;
        //* create an intermediate device plugin
        kr = IOCreatePlugInInterfaceForService(usbDevice,
                                               kIOUSBDeviceUserClientTypeID,
                                               kIOCFPlugInInterfaceID,
                                               &plugInInterface, &score);
        //* only needed this to find the plugin
        (void)IOObjectRelease(usbDevice);
        if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
            DBG("ERR: Unable to create a device plug-in (%08x)\n", kr);
            continue;
        }

        result = (*plugInInterface)->QueryInterface(plugInInterface,
                CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID*) &dev);
        //* only needed this to query the plugin
        (*plugInInterface)->Release(plugInInterface);
        if (result || !dev) {
            DBG("ERR: Couldn't create a device interface (%08x)\n",
                (int) result);
            continue;
        }

        //* Now after all that, we actually have a ref to the device and
        //* the interface that matched our criteria

        kr = (*dev)->GetDeviceVendor(dev, &vendor);
        kr = (*dev)->GetDeviceProduct(dev, &product);
        kr = (*dev)->GetLocationID(dev, &locationId);
        if (kr == 0) {
            snprintf(devpathBuf, sizeof(devpathBuf), "usb:%lX", locationId);
            devpath = devpathBuf;
        }
        kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex);

	if (serialIndex > 0) {
		IOUSBDevRequest req;
		UInt16          buffer[256];
		UInt16          languages[128];

		memset(languages, 0, sizeof(languages));

		req.bmRequestType =
			USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
		req.bRequest = kUSBRqGetDescriptor;
		req.wValue = (kUSBStringDesc << 8) | 0;
		req.wIndex = 0;
		req.pData = languages;
		req.wLength = sizeof(languages);
		kr = (*dev)->DeviceRequest(dev, &req);

		if (kr == kIOReturnSuccess && req.wLenDone > 0) {

			int langCount = (req.wLenDone - 2) / 2, lang;

			for (lang = 1; lang <= langCount; lang++) {

                                memset(buffer, 0, sizeof(buffer));
                                memset(&req, 0, sizeof(req));

				req.bmRequestType =
					USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
				req.bRequest = kUSBRqGetDescriptor;
				req.wValue = (kUSBStringDesc << 8) | serialIndex;
				req.wIndex = languages[lang];
				req.pData = buffer;
				req.wLength = sizeof(buffer);
				kr = (*dev)->DeviceRequest(dev, &req);

				if (kr == kIOReturnSuccess && req.wLenDone > 0) {
					int i, count;

					// skip first word, and copy the rest to the serial string,
					// changing shorts to bytes.
					count = (req.wLenDone - 1) / 2;
					for (i = 0; i < count; i++)
						serial[i] = buffer[i + 1];
					serial[i] = 0;
                                        break;
				}
			}
		}
	}
        (*dev)->Release(dev);

        DBG("INFO: Found vid=%04x pid=%04x serial=%s\n", vendor, product,
            serial);

        usb_handle* handle = CheckInterface((IOUSBInterfaceInterface**)iface,
                                            vendor, product);
        if (handle == NULL) {
            DBG("ERR: Could not find device interface: %08x\n", kr);
            (*iface)->Release(iface);
            continue;
        }

        DBG("AndroidDeviceAdded calling register_usb_transport\n");
        register_usb_transport(handle, (serial[0] ? serial : NULL), devpath, 1);

        // Register for an interest notification of this device being removed.
        // Pass the reference to our private data as the refCon for the
        // notification.
        kr = IOServiceAddInterestNotification(notificationPort,
                usbInterface,
                kIOGeneralInterest,
                AndroidInterfaceNotify,
                handle,
                &handle->usbNotification);

        if (kIOReturnSuccess != kr) {
            DBG("ERR: Unable to create interest notification (%08x)\n", kr);
        }
    }
}
Example #11
0
//================================================================================================
//
//  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);
	}
}
Example #12
0
//================================================================================================
//
//  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.
//
//================================================================================================
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;   
        MyPrivateData   *privateDataRef = NULL;
        UInt32          locationID;
        
        printf("Device added.\n");
        
        //
        // Launch our application
        system("open /Users/seanwhitsell/development/Pressure/Pressure/build/Debug/Pressure.app");
        
        // Add some app-specific information about this device.
        // Create a buffer to hold the data.
        privateDataRef = malloc(sizeof(MyPrivateData));
        bzero(privateDataRef, sizeof(MyPrivateData));
        
        // Get the USB device's name.
        kr = IORegistryEntryGetName(usbDevice, deviceName);
        if (KERN_SUCCESS != kr) {
            deviceName[0] = '\0';
        }
        
        deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, deviceName, 
                                                         kCFStringEncodingASCII);
        
        // Dump our data to stderr just to see what it looks like.
        fprintf(stderr, "deviceName: ");
        CFShow(deviceNameAsCFString);
        
        // Save the device's name to our private data.        
        privateDataRef->deviceName = deviceNameAsCFString;
        
        // 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;
        }
        
        // Use the plugin interface to retrieve the device interface.
        res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
                                                 (LPVOID*) &privateDataRef->deviceInterface);
        
        // Now done with the plugin interface.
        (*plugInInterface)->Release(plugInInterface);
        
        if (res || privateDataRef->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 = (*privateDataRef->deviceInterface)->GetLocationID(privateDataRef->deviceInterface, &locationID);
        if (KERN_SUCCESS != kr) {
            fprintf(stderr, "GetLocationID returned 0x%08x.\n", kr);
            continue;
        }
        else {
            fprintf(stderr, "Location ID: 0x%x\n\n", locationID);
        }
        
        privateDataRef->locationID = locationID;
        
        // 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
                                              DeviceNotification,               // callback
                                              privateDataRef,                   // refCon
                                              &(privateDataRef->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);
    }
}
Example #13
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 #14
0
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;
        MyPrivateData		*privateDataRef = NULL;
        UInt32			locationID;

        printf("Device 0x%08x added.\n", usbDevice);

        // Make activity and turn screen on
        printf("Wake up on Yubikey insertion.\n");
        IOPMAssertionID assertionID;
        IOPMAssertionDeclareUserActivity(CFSTR(""), kIOPMUserActiveLocal, &assertionID);

        // Add some app-specific information about this device.
        // Create a buffer to hold the data.

        privateDataRef = malloc(sizeof(MyPrivateData));
        bzero( privateDataRef, sizeof(MyPrivateData));

        // In this sample we'll just use the service's name.
        //
        kr = IORegistryEntryGetName(usbDevice, deviceName);
        if (KERN_SUCCESS != kr)
        {
            deviceName[0] = '\0';
        }

        deviceNameAsCFString = CFStringCreateWithCString(kCFAllocatorDefault, deviceName, kCFStringEncodingASCII);

        // Dump our data to stdout just to see what it looks like.
        //
        CFShow(deviceNameAsCFString);

        privateDataRef->deviceName = deviceNameAsCFString;

        // 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 user land application and the kernel object
        // for the USB Device.
        //
        kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score);

        if ((kIOReturnSuccess != kr) || !plugInInterface)
        {
            printf("unable to create a plugin (%08x)\n", kr);
            continue;
        }

        // I have the device plugin, I need the device interface
        //
        res = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID)&privateDataRef->deviceInterface);
        (*plugInInterface)->Release(plugInInterface);			// done with this
        if (res || !privateDataRef->deviceInterface)
        {
            printf("couldn't create a device interface (%08x)\n", (int) res);
            continue;
        }

        // Now that we have the IOUSBDeviceInterface, we can call the routines in IOUSBLib.h
        // In this case, we just want the locationID.
        //
        kr = (*privateDataRef->deviceInterface)->GetLocationID(privateDataRef->deviceInterface, &locationID);
        if (KERN_SUCCESS != kr)
        {
            printf("GetLocationID returned %08x\n", kr);
            continue;
        }
        else
        {
            printf("Location ID: 0x%lx\n", (unsigned long)locationID);

        }

        privateDataRef->locationID = locationID;

        // Register for an interest notification for this device. Pass the reference to our
        // private data as the refCon for the notification.
        //
        kr = IOServiceAddInterestNotification(	gNotifyPort,			// notifyPort
                                                usbDevice,			// service
                                                kIOGeneralInterest,		// interestType
                                                DeviceNotification,		// callback
                                                privateDataRef,			// refCon
                                                &(privateDataRef->notification)	// notification
                                             );

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

        // Done with this io_service_t
        //
        kr = IOObjectRelease(usbDevice);

        free(privateDataRef);
    }
}
Example #15
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;
}
void init_device (void *refCon, io_iterator_t iterator) {
    io_object_t hidDevice = 0;
    IOCFPlugInInterface **plugInInterface = NULL;
    IOHIDDeviceInterface122 **hidDeviceInterface = NULL;
    HRESULT result = S_FALSE;
    HIDDataRef hidDataRef = NULL;
    IOReturn kr;
    SInt32 score;

    while (hidDevice = IOIteratorNext (iterator)) {
        kr = IOCreatePlugInInterfaceForService (hidDevice,
                                                kIOHIDDeviceUserClientTypeID,
                                                kIOCFPlugInInterfaceID,
                                                &plugInInterface, &score);

        if (kr != kIOReturnSuccess) {
            goto HIDDEVICEADDED_NONPLUGIN_CLEANUP;
        }

        result = (*plugInInterface)->QueryInterface (plugInInterface,
                 CFUUIDGetUUIDBytes
                 (kIOHIDDeviceInterfaceID),
                 (LPVOID *)&hidDeviceInterface);

        if ((result == S_OK) && hidDeviceInterface) {
            hidDataRef = malloc (sizeof (HIDData));
            bzero (hidDataRef, sizeof (HIDData));

            hidDataRef->hidDeviceInterface = hidDeviceInterface;

            result = (*(hidDeviceInterface))->open
                     (hidDataRef->hidDeviceInterface, 0);
            result = (*(hidDeviceInterface))->createAsyncEventSource
                     (hidDataRef->hidDeviceInterface, &hidDataRef->eventSource);
            result = (*(hidDeviceInterface))->setInterruptReportHandlerCallback
                     (hidDataRef->hidDeviceInterface, hidDataRef->buffer,
                      sizeof(hidDataRef->buffer), &interrupt_callback, NULL,
                      hidDataRef);

            CFRunLoopAddSource (CFRunLoopGetCurrent (), hidDataRef->eventSource,
                                kCFRunLoopDefaultMode);

            IOServiceAddInterestNotification (gNotifyPort, hidDevice,
                                              kIOGeneralInterest,
                                              device_release, hidDataRef,
                                              &(hidDataRef->notification));

            goto HIDDEVICEADDED_CLEANUP;
        }

        if (hidDeviceInterface) {
            (*hidDeviceInterface)->Release(hidDeviceInterface);
            hidDeviceInterface = NULL;
        }

        if (hidDataRef) {
            free ( hidDataRef );
        }

HIDDEVICEADDED_CLEANUP:
        (*plugInInterface)->Release(plugInInterface);

HIDDEVICEADDED_NONPLUGIN_CLEANUP:
        IOObjectRelease(hidDevice);
    }
}