Beispiel #1
0
void HIDDevice::closeDevice(bool wasUnplugged)
{
    OVR_ASSERT(Device != NULL);
    
    if (!wasUnplugged)
    {
        // Clear the registered callbacks.
        IOHIDDeviceRegisterInputReportCallback(Device,
                                               ReadBuffer,
                                               InputReportBufferLength,
                                               NULL,
                                               this);
        
        IOHIDDeviceRegisterRemovalCallback(Device, NULL, this);
        
        IOHIDDeviceUnscheduleFromRunLoop(Device,
                                         HIDManager->getRunLoop(),
                                         kCFRunLoopDefaultMode);
        IOHIDDeviceClose(Device, kIOHIDOptionsTypeNone);
    }
    
	CFRelease(Device);
    Device = NULL;
        
    LogText("OVR::OSX::HIDDevice - HID Device Closed '%s'\n", DevDesc.Path.ToCStr());
}
Beispiel #2
0
static void iohidmanager_hid_device_add(void *data, IOReturn result,
      void* sender, IOHIDDeviceRef device)
{
   IOReturn ret;
   uint16_t dev_vid, dev_pid;

   settings_t *settings = config_get_ptr();
   iohidmanager_hid_t     *hid = (iohidmanager_hid_t*)hid_driver_get_data();
   struct iohidmanager_hid_adapter *adapter = (struct iohidmanager_hid_adapter*)
      calloc(1, sizeof(*adapter));

   if (!adapter || !hid)
      return;

   adapter->handle        = device;

   ret = IOHIDDeviceOpen(device, kIOHIDOptionsTypeNone);

   if (ret != kIOReturnSuccess)
   {
      free(adapter);
      return;
   }

   /* Move the device's run loop to this thread. */
   IOHIDDeviceScheduleWithRunLoop(device, CFRunLoopGetCurrent(),
         kCFRunLoopCommonModes);
   IOHIDDeviceRegisterRemovalCallback(device, iohidmanager_hid_device_remove, adapter);

#ifndef IOS
   iohidmanager_hid_device_get_product_string(device, adapter->name,
         sizeof(adapter->name));
#endif

   dev_vid = iohidmanager_hid_device_get_vendor_id  (device);
   dev_pid = iohidmanager_hid_device_get_product_id (device);

   adapter->slot = pad_connection_pad_init(hid->slots,
         adapter->name, dev_vid, dev_pid, adapter, &iohidmanager_hid_device_send_control);

   if (adapter->slot == -1)
       return;

   if (pad_connection_has_interface(hid->slots, adapter->slot))
      IOHIDDeviceRegisterInputReportCallback(device,
            adapter->data + 1, sizeof(adapter->data) - 1,
            iohidmanager_hid_device_report, adapter);
   else
      IOHIDDeviceRegisterInputValueCallback(device,
            iohidmanager_hid_device_input_callback, adapter);

   if (adapter->name[0] == '\0')
      return;

   strlcpy(settings->input.device_names[adapter->slot],
         adapter->name, sizeof(settings->input.device_names[adapter->slot]));

   iohidmanager_hid_device_add_autodetect(adapter->slot,
         adapter->name, iohidmanager_hid.ident, dev_vid, dev_pid);
}
  void osxPointingDeviceManager::AddDevice(void *sender, IOReturn, void *, IOHIDDeviceRef devRef)
  {
    // Prevent other HID devices from being detected
    if (isNotPointingDevice(devRef))
      return;
    osxPointingDeviceManager *self = (osxPointingDeviceManager *)sender;
    osxPointingDeviceData *pdd = new osxPointingDeviceData;
    fillDescriptorInfo(devRef, pdd->desc);
    pdd->devRef = devRef;
    self->registerDevice(devRef, pdd);

    CFDataRef descriptor = (CFDataRef)IOHIDDeviceGetProperty(devRef, CFSTR(kIOHIDReportDescriptorKey));
    if (descriptor) {
      const UInt8 *bytes = CFDataGetBytePtr(descriptor);
      CFIndex length = CFDataGetLength(descriptor);
      if (!pdd->parser.setDescriptor(bytes, length))
      {
        if (self->debugLevel > 1)
          std::cerr << "    osxPointingDeviceManager::AddDevice: unable to parse the HID report descriptor" << std::endl;
      }
      else
        IOHIDDeviceRegisterInputReportCallback(devRef, pdd->report, sizeof(pdd->report),
                                               hidReportCallback, self);

      if (self->debugLevel > 1)
      {
        std::cerr << "HID descriptors: [ " << std::flush ;
        for (int i=0; i<length; ++i)
          std::cerr << std::hex << std::setfill('0') << std::setw(2) << (int)bytes[i] << " " ;
        std::cerr << "]" << std::endl ;
      }
    }
  }
void yyyPacketShutdown(yInterfaceSt  *iface)
{
    int i;

    // remove iface from setuped ifaces
    for (i=0; i< SETUPED_IFACE_CACHE_SIZE ; i++) {
        if(yContext->setupedIfaceCache[i]==iface){
            yContext->setupedIfaceCache[i] = NULL;
            break;
        }
    }
    YASSERT(i<SETUPED_IFACE_CACHE_SIZE);
    if(iface->devref!=NULL){
        IOHIDDeviceRegisterInputReportCallback(iface->devref,              // IOHIDDeviceRef for the HID device
                                               (u8*) &iface->tmprxpkt,   // pointer to the report data (uint8_t's)
                                               USB_PKT_SIZE,              // number of bytes in the report (CFIndex)
                                               NULL,   // the callback routine
                                               iface);                      // context passed to callback
        IOHIDDeviceClose(iface->devref, kIOHIDOptionsTypeNone);
        iface->devref=NULL;
    }
    yPktQueueFree(&iface->rxQueue);
	yPktQueueFree(&iface->txQueue);
    iface->flags.yyySetupDone = 0;
    CFRelease(iface->run_loop_mode);
    if (yContext->osx_flags & YCTX_OSX_MULTIPLES_HID) {
        stopHIDManager(&iface->hid);
    }
}
Beispiel #5
0
static void attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev)
{
   struct hid_struct *h;
   
	//fprintf(stderr,"attach callback\n");
   //
	if (IOHIDDeviceOpen(dev, kIOHIDOptionsTypeNone) != kIOReturnSuccess) return;
	h = (hid_t *)malloc(sizeof(hid_t));
	if (!h) return;
   
	memset(h, 0, sizeof(hid_t));
   
	IOHIDDeviceScheduleWithRunLoop(dev, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);	
   IOHIDDeviceRegisterInputReportCallback(dev, h->buffer, sizeof(h->buffer),
                                          input_callback, h);
   h->ref = dev;
	h->open = 1;
   
	add_hid(h);
   usbstatus=1; 
   
   /*
   r = rawhid_open(1, 0x16C0, 0x0480, 0xFFAB, 0x0200);
   if (r <= 0) 
   {
      fprintf(stderr,"no rawhid device found\n");
   }
   else
   {
      
      fprintf(stderr,"new rawhid device found\n");
   }
   */

}
Beispiel #6
0
int yyySetup(yInterfaceSt *iface,char *errmsg)
{  
    char str[32];

    yyyInitPktQueue(iface);
    yInitializeCriticalSection(&iface->yyyCS);

    if(iface->devref==NULL){
        return YERR(YAPI_DEVICE_NOT_FOUND);
    }
    IOReturn ret = IOHIDDeviceOpen(iface->devref, kIOHIDOptionsTypeNone);
    if (ret != kIOReturnSuccess) {
        YSPRINTF(str,32,"Unable to open device (0x%x)",ret);
        return YERRMSG(YAPI_IO_ERROR,str);
    }
    
    /* Create the Run Loop Mode for this device. printing the reference seems to work. */
    sprintf(str, "yocto_%p", iface->devref);
    iface->run_loop_mode = CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII);

    /* Attach the device to a Run Loop */
    IOHIDDeviceScheduleWithRunLoop(iface->devref, yContext->usb_run_loop, iface->run_loop_mode);
    IOHIDDeviceRegisterInputReportCallback( iface->devref,              // IOHIDDeviceRef for the HID device
                                            (u8*) &iface->tmprxpkt,     // pointer to the report data 
                                            USB_PKT_SIZE,               // number of bytes in the report (CFIndex)
                                            &Handle_IOHIDDeviceIOHIDReportCallback,   // the callback routine
                                            iface);                     // context passed to callback
    return 0;
}
Beispiel #7
0
static void hid_manager_device_attached(void* context, IOReturn result, void* sender, IOHIDDeviceRef device)
{
    char device_name[1024];
    CFStringRef device_name_ref;
    struct apple_pad_connection* connection = (struct apple_pad_connection*)calloc(1, sizeof(*connection));
    
    connection->device = device;
    connection->slot = MAX_PLAYERS;
    
    IOHIDDeviceOpen(device, kIOHIDOptionsTypeNone);
    IOHIDDeviceScheduleWithRunLoop(device, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
    IOHIDDeviceRegisterRemovalCallback(device, hid_device_removed, connection);
    
    device_name_ref = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
    CFStringGetCString(device_name_ref, device_name, sizeof(device_name), kCFStringEncodingUTF8);
    
    connection->slot = apple_joypad_connect(device_name, connection);
    
    if (apple_joypad_has_interface(connection->slot))
        IOHIDDeviceRegisterInputReportCallback(device, connection->data + 1, sizeof(connection->data) - 1, hid_device_report, connection);
    else
        IOHIDDeviceRegisterInputValueCallback(device, hid_device_input_callback, connection);

    if (device_name[0] != '\0')
    {
       strlcpy(g_settings.input.device_names[connection->slot], device_name, sizeof(g_settings.input.device_names));
       input_config_autoconfigure_joypad(connection->slot, device_name, apple_joypad.ident);
       RARCH_LOG("Port %d: %s.\n", connection->slot, device_name);
    }
}
Beispiel #8
0
void openusb(usbdevice* kb){
    // The driver sometimes isn't completely ready yet, so give it a short delay
    sleep(1);

    // Handle 3 is the control handle
    kb->lastkeypress = -1;
    kb->handle = kb->handles[3];

    // Set up the device
    int setup = setupusb(kb);
    if(setup == -1){
        closehandle(kb);
        pthread_mutex_unlock(&kb->mutex);
        pthread_mutex_destroy(&kb->mutex);
        pthread_mutex_destroy(&kb->keymutex);
        return;
    } else if(setup){
        // If the setup had a communication error, wait a bit and try again.
        sleep(1);
        resetusb(kb);
    }

    // Start handling HID reports for the Corsair input
    IOHIDDeviceRegisterInputReportCallback(kb->handles[2], kb->intinput, MSG_SIZE, reportcallback, kb);

    // Register for close notification
    IOHIDDeviceRegisterRemovalCallback(kb->handle, usbremove, kb);

    // Update connected
    updateconnected();
    notifyconnect(kb, 1);
    int index = INDEX_OF(kb, keyboard);
    printf("Device ready at %s%d\n", devpath, index);
    pthread_mutex_unlock(&kb->mutex);
}
Beispiel #9
0
void TeensyControls_usb_close(void)
{
	teensy_t *t;
	int wait=0;

	for (t = TeensyControls_first_teensy; t; t = t->next) {
		if (t->online) {
			printf("close USB device\n");
			IOHIDDeviceRegisterInputReportCallback(t->usb.dev,
				t->usb.inbuf, 64, NULL, NULL);
			// TODO: how to terminate input thread?
			// TODO: how to terminate output thread?
			pthread_cond_signal(&t->output_event);
			IOHIDDeviceClose(t->usb.dev, 0);
			t->online = 0;
		}
	}
	if (hmgr) {
		printf("closing hid manager\n");
		IOHIDManagerRegisterDeviceMatchingCallback(hmgr, NULL, NULL);
		IOHIDManagerRegisterDeviceRemovalCallback(hmgr, NULL, NULL);
		IOHIDManagerClose(hmgr, 0);
		hmgr = NULL;
	}
	while (++wait < 20 && num_thread_alive() > 0) {
		usleep(10000);
		printf("wait #%d for thread exit\n", wait);
	}
}
static void match_callback(void *context, IOReturn result,
                           void *sender, IOHIDDeviceRef device)
{
	static int captured_devices = 0;
	static int failed_captures = 0;

	// dump instead of capturing
	if (false)
	{
		{
			CFTypeRef o = IOHIDDeviceGetProperty(
				device, CFSTR(kIOHIDDeviceUsagePairsKey));
			printf("\tkIOHIDDeviceUsagePairsKey = %p\n", o);
			CFShow(o);
		}

		{
			CFTypeRef o = IOHIDDeviceGetProperty(
				device, CFSTR(kIOHIDElementKey));
			printf("\tkIOHIDElementKey = %p\n", o);
			CFShow(o);
		}

		return;
	}

	IOReturn r = IOHIDDeviceOpen(device, kIOHIDOptionsTypeSeizeDevice);
	if (r == kIOReturnSuccess) {
		struct keyboard_handler *handler =
			(struct keyboard_handler*) malloc(sizeof(*handler));
		memset(handler, 0x00, sizeof(*handler));
		handler->index = captured_devices++;
		IOHIDDeviceRegisterInputReportCallback(
			device,
			handler->hid_report_buffer,
			sizeof(handler->hid_report_buffer),
			&got_hid_report,
			(void*) handler);

		move(handler->index + 1, 0);
		printw("%i <no reports yet>", handler->index);

	}
	else {
		failed_captures++;
	}

	move(0, 0);
	clrtoeol();
	printw("Seized %i devices", captured_devices);
	if (failed_captures) {
		printw(" (%i failed)", failed_captures);
	}
	refresh();
}
Beispiel #11
0
void openusb(usbdevice* kb, short vendor, short product){
    kb->lastkeypress = KEY_NONE;
    if(IS_RGB(vendor, product))
        // Handle 3 is the control handle
        kb->handle = kb->handles[3];
    else
        // Non RGB keyboards don't have one, so just use 0
        kb->handle = kb->handles[0];

    // Set up the device
    int setup = setupusb(kb, vendor, product);
    if(setup == -1 || (setup && usb_tryreset(kb))){
        closehandle(kb);
        pthread_mutex_unlock(&kb->mutex);
        pthread_mutex_destroy(&kb->mutex);
        pthread_mutex_destroy(&kb->keymutex);
        return;
    }

    // Start handling HID reports for the input
    IOHIDDeviceRegisterInputReportCallback(kb->handles[0], kb->urbinput, 8, reportcallback, kb);
    if(IS_RGB(vendor, product))
        IOHIDDeviceRegisterInputReportCallback(kb->handles[1], kb->urbinput + 8, 21, reportcallback, kb);
    else
        IOHIDDeviceRegisterInputReportCallback(kb->handles[1], kb->urbinput + 8, 4, reportcallback, kb);
    if(IS_RGB(vendor, product))
        IOHIDDeviceRegisterInputReportCallback(kb->handles[2], kb->kbinput, MSG_SIZE, reportcallback, kb);
    else
        IOHIDDeviceRegisterInputReportCallback(kb->handles[2], kb->urbinput + 8 + 4, 15, reportcallback, kb);

    // Register for close notification
    IOHIDDeviceRegisterRemovalCallback(kb->handle, usbremove, kb);

    // Update connected
    updateconnected();
    notifyconnect(kb, 1);
    int index = INDEX_OF(kb, keyboard);
    printf("Device ready at %s%d\n", devpath, index);
    pthread_mutex_unlock(&kb->mutex);
}
Beispiel #12
0
static void add_device(void* context, IOReturn result,
      void* sender, IOHIDDeviceRef device)
{
   char device_name[PATH_MAX_LENGTH];
   CFStringRef device_name_ref;
   CFNumberRef vendorID, productID;
   struct pad_connection* connection = (struct pad_connection*)
      calloc(1, sizeof(*connection));

   connection->device_handle = device;
   connection->slot          = MAX_USERS;

   IOHIDDeviceOpen(device, kIOHIDOptionsTypeNone);

   /* Move the device's run loop to this thread. */
   IOHIDDeviceScheduleWithRunLoop(device, CFRunLoopGetCurrent(),
         kCFRunLoopCommonModes);
   IOHIDDeviceRegisterRemovalCallback(device, remove_device, connection);

#ifndef IOS
   device_name_ref = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
   CFStringGetCString(device_name_ref, device_name,
         sizeof(device_name), kCFStringEncodingUTF8);
#endif

   vendorID = (CFNumberRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey));
   CFNumberGetValue(vendorID, kCFNumberIntType, &connection->v_id);

   productID = (CFNumberRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey));
   CFNumberGetValue(productID, kCFNumberIntType, &connection->p_id);

   connection->slot = pad_connection_pad_init(slots, device_name,
         connection, &hid_pad_connection_send_control);

   if (pad_connection_has_interface(slots, connection->slot))
      IOHIDDeviceRegisterInputReportCallback(device,
            connection->data + 1, sizeof(connection->data) - 1,
            hid_device_report, connection);
   else
      IOHIDDeviceRegisterInputValueCallback(device,
            hid_device_input_callback, connection);

   if (device_name[0] == '\0')
      return;

   strlcpy(g_settings.input.device_names[connection->slot],
         device_name, sizeof(g_settings.input.device_names));

   input_config_autoconfigure_joypad(connection->slot,
         device_name, connection->v_id, connection->p_id, apple_hid_joypad.ident);
   RARCH_LOG("Port %d: %s.\n", connection->slot, device_name);
}
Beispiel #13
0
static void input_thread(void *arg)
{
	teensy_t *t = (teensy_t *)arg;
	printf("input_thread begin\n");
	IOHIDDeviceRegisterInputReportCallback(t->usb.dev,
		t->usb.inbuf, 64, input_callback, t);
	while (1) {
		int r;
		if (t->online == 0) break;
		r = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, true);
	}
	t->input_thread_quit = 1;
	printf("input_thread end\n");
}
Beispiel #14
0
/**
 * @brief Called by the USB system
 * @param dev The device that was attached
 */
void pjrc_rawhid::attach(IOHIDDeviceRef d)
{
    // Store the device handle
    dev = d;

    if (IOHIDDeviceOpen(dev, kIOHIDOptionsTypeNone) != kIOReturnSuccess) return;
    // Disconnect the attach callback since we don't want to automatically reconnect
    IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, NULL, NULL);
    IOHIDDeviceScheduleWithRunLoop(dev, the_correct_runloop, kCFRunLoopDefaultMode);
    IOHIDDeviceRegisterInputReportCallback(dev, buffer, sizeof(buffer), pjrc_rawhid::input_callback, this);

    attach_count++;
    device_open = true;
    unplugged = false;
}
Beispiel #15
0
static void attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev)
{
    struct hid_struct *h;

    printf("attach callback\n");
    if (IOHIDDeviceOpen(dev, kIOHIDOptionsTypeNone) != kIOReturnSuccess) return;
    h = (hid_t *)malloc(sizeof(hid_t));
    if (!h) return;
    memset(h, 0, sizeof(hid_t));
    IOHIDDeviceScheduleWithRunLoop(dev, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    IOHIDDeviceRegisterInputReportCallback(dev, h->buffer, sizeof(h->buffer), input_callback, h);
    h->ref = dev;
    h->open = 1;
    add_hid(h);
}
    static void DeviceAttached(void* context, IOReturn result, void* sender, IOHIDDeviceRef device)
    {
       Connection* connection = new Connection();
       connection->device = device;

       IOHIDDeviceOpen(device, kIOHIDOptionsTypeNone);
       IOHIDDeviceScheduleWithRunLoop(device, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
       IOHIDDeviceRegisterRemovalCallback(device, DeviceRemoved, connection);

       CFStringRef device_name_ref = (CFStringRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
       char device_name[1024];
       CFStringGetCString(device_name_ref, device_name, sizeof(device_name), kCFStringEncodingUTF8);

       connection->hidpad = HIDPad::Connect(device_name, connection);
       IOHIDDeviceRegisterInputReportCallback(device, connection->data + 1, sizeof(connection->data) - 1, DeviceReport, connection);
    }
Beispiel #17
0
void HID_API_EXPORT hid_close(hid_device *dev)
{
	if ( !dev )
	{
		return;
	}

	/* Disconnect the report callback before close. */
	if (!dev->disconnected) {
		IOHIDDeviceRegisterInputReportCallback(
			dev->device_handle, dev->input_report_buf, dev->max_input_report_len,
			NULL, dev);
		IOHIDManagerRegisterDeviceRemovalCallback(hid_mgr, NULL, dev);
		IOHIDDeviceUnscheduleFromRunLoop(dev->device_handle, dev->run_loop, dev->run_loop_mode);
		IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
	}
	
	/* Cause read_thread() to stop. */
	dev->shutdown_thread = 1;
	
	/* Wake up the run thread's event loop so that the thread can exit. */
	CFRunLoopSourceSignal(dev->source);
	CFRunLoopWakeUp(dev->run_loop);
	
	/* Notify the read thread that it can shut down now. */
	pthread_barrier_wait(&dev->shutdown_barrier);

	/* Wait for read_thread() to end. */
	pthread_join(dev->thread, NULL);

	/* Close the OS handle to the device, but only if it's not
	   been unplugged. If it's been unplugged, then calling
	   IOHIDDeviceClose() will crash. */
	if (!dev->disconnected) {
		IOHIDDeviceClose(dev->device_handle, kIOHIDOptionsTypeNone);
	}
	
	/* Clear out the queue of received reports. */
	pthread_mutex_lock(&dev->mutex);
	while (dev->input_reports) {
		return_data(dev, NULL, 0);
	}
	pthread_mutex_unlock(&dev->mutex);

	free_hid_device(dev);
}
Beispiel #18
0
void yyyPacketShutdown(yInterfaceSt  *iface)
{
    
    yEnterCriticalSection(&iface->yyyCS);
    if(iface->devref!=NULL){
        IOHIDDeviceRegisterInputReportCallback( iface->devref,              // IOHIDDeviceRef for the HID device
                                            (u8*) &iface->tmprxpkt,   // pointer to the report data (uint8_t's)
                                            USB_PKT_SIZE,              // number of bytes in the report (CFIndex)
                                            NULL,   // the callback routine
                                            iface);                      // context passed to callback
        IOHIDDeviceClose(iface->devref, kIOHIDOptionsTypeNone);
        iface->devref=NULL;
    }
    yLeaveCriticalSection(&iface->yyyCS);
    yDeleteCriticalSection(&iface->yyyCS);
    yyyFreePktQueue(iface);

}
Beispiel #19
0
static void hid_manager_device_attached(void* context, IOReturn result, void* sender, IOHIDDeviceRef device)
{
   struct apple_pad_connection* connection = calloc(1, sizeof(struct apple_pad_connection));
   connection->device = device;
   connection->slot = MAX_PLAYERS;

   IOHIDDeviceOpen(device, kIOHIDOptionsTypeNone);
   IOHIDDeviceScheduleWithRunLoop(device, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
   IOHIDDeviceRegisterRemovalCallback(device, hid_device_removed, connection);

   CFStringRef device_name_ref = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
   char device_name[1024];
   CFStringGetCString(device_name_ref, device_name, sizeof(device_name), kCFStringEncodingUTF8);

   connection->slot = apple_joypad_connect(device_name, connection);
      
   if (apple_joypad_has_interface(connection->slot))
      IOHIDDeviceRegisterInputReportCallback(device, connection->data + 1, sizeof(connection->data) - 1, hid_device_report, connection);
   else
      IOHIDDeviceRegisterInputValueCallback(device, hid_device_input_callback, connection);
}
Beispiel #20
0
//! Close the HID device
void pjrc_rawhid::close(int)
{
    // Make sure any pending locks are done
    QMutexLocker lock(m_writeMutex);

    if (device_open) {
        device_open = false;
        CFRunLoopStop(the_correct_runloop);

        if (!unplugged) {
            IOHIDDeviceUnscheduleFromRunLoop(dev, the_correct_runloop, kCFRunLoopDefaultMode);
            IOHIDDeviceRegisterInputReportCallback(dev, buffer, sizeof(buffer), NULL, NULL);
            IOHIDDeviceClose(dev, kIOHIDOptionsTypeNone);
        }

        IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, NULL, NULL);
        IOHIDManagerClose(hid_manager, 0);

        dev = NULL;
        hid_manager = NULL;
    }
}
Beispiel #21
0
void CInputProviderMacOsHid::OnDeviceMatched(IOReturn result, void* sender, IOHIDDeviceRef device)
{
	m_devices.push_back(DEVICE_INFO());
	auto& deviceInfo = *m_devices.rbegin();
	deviceInfo.provider = this;
	deviceInfo.device = device;
	deviceInfo.deviceId = GetDeviceID(device);

	auto InputReportCallbackStub = GetCallback(device);
	if(InputReportCallbackStub)
	{
		uint32_t max_input_report_size = GetIntProperty(device, CFSTR(kIOHIDMaxInputReportSizeKey));
		uint8_t* report_buffer = static_cast<uint8_t*>(calloc(max_input_report_size, sizeof(uint8_t)));
		IOHIDDeviceRegisterInputReportCallback(device, report_buffer, max_input_report_size, InputReportCallbackStub, &deviceInfo);
	}
	else
	{
		if(OnInput)
		{
			SetInitialBindValues(device);
		}
		IOHIDDeviceRegisterInputValueCallback(device, &InputValueCallbackStub, &deviceInfo);
	}
}
Beispiel #22
0
hid_device * HID_API_EXPORT hid_open_path(const char *path)
{
  	int i;
	hid_device *dev = NULL;
	CFIndex num_devices;
	
	dev = new_hid_device();

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

	CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);
	
	num_devices = CFSetGetCount(device_set);
	IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef));
	CFSetGetValues(device_set, (const void **) device_array);	
	for (i = 0; i < num_devices; i++) {
		char cbuf[BUF_LEN];
		size_t len;
		IOHIDDeviceRef os_dev = device_array[i];
		
		len = make_path(os_dev, cbuf, sizeof(cbuf));
		if (!strcmp(cbuf, path)) {
			// Matched Paths. Open this Device.
			IOReturn ret = IOHIDDeviceOpen(os_dev, kIOHIDOptionsTypeNone);
			if (ret == kIOReturnSuccess) {
				char str[32];

				free(device_array);
				CFRelease(device_set);
				dev->device_handle = os_dev;
				
				/* Create the buffers for receiving data */
				dev->max_input_report_len = (CFIndex) get_max_report_length(os_dev);
				dev->input_report_buf = calloc(dev->max_input_report_len, sizeof(uint8_t));
				
				/* Create the Run Loop Mode for this device.
				   printing the reference seems to work. */
				sprintf(str, "HIDAPI_%p", os_dev);
				dev->run_loop_mode = 
					CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII);
				
				/* Attach the device to a Run Loop */
				IOHIDDeviceRegisterInputReportCallback(
					os_dev, dev->input_report_buf, dev->max_input_report_len,
					&hid_report_callback, dev);
				IOHIDManagerRegisterDeviceRemovalCallback(hid_mgr, hid_device_removal_callback, NULL);
				
				/* Start the read thread */
				pthread_create(&dev->thread, NULL, read_thread, dev);

				/* Wait here for the read thread to be initialized. */
				pthread_barrier_wait(&dev->barrier);
				
				return dev;
			}
			else {
				goto return_error;
			}
		}
	}

return_error:
	free(device_array);
	CFRelease(device_set);
	free_hid_device(dev);
	return NULL;
}
Beispiel #23
0
static void iohidmanager_hid_device_add(void *data, IOReturn result,
      void* sender, IOHIDDeviceRef device)
{
   int i;
   IOReturn ret;
   uint16_t dev_vid, dev_pid;
   CFArrayRef elements_raw;
   int count;
   CFMutableArrayRef elements;
   CFRange range;
   bool found_axis[6] =
   { false, false, false, false, false, false };
   apple_input_rec_t *tmp                   = NULL;
   apple_input_rec_t *tmpButtons            = NULL;
   apple_input_rec_t *tmpAxes               = NULL;
   iohidmanager_hid_t                  *hid = (iohidmanager_hid_t*)
      hid_driver_get_data();
   struct iohidmanager_hid_adapter *adapter = (struct iohidmanager_hid_adapter*)
      calloc(1, sizeof(*adapter));

   if (!adapter)
      return;
   if (!hid)
      goto error;

   adapter->handle        = device;

   ret = IOHIDDeviceOpen(device, kIOHIDOptionsTypeNone);

   if (ret != kIOReturnSuccess)
      goto error;

   /* Move the device's run loop to this thread. */
   IOHIDDeviceScheduleWithRunLoop(device, CFRunLoopGetCurrent(),
         kCFRunLoopCommonModes);
   IOHIDDeviceRegisterRemovalCallback(device,
         iohidmanager_hid_device_remove, adapter);

#ifndef IOS
   iohidmanager_hid_device_get_product_string(device, adapter->name,
         sizeof(adapter->name));
#endif

   dev_vid = iohidmanager_hid_device_get_vendor_id  (device);
   dev_pid = iohidmanager_hid_device_get_product_id (device);

   adapter->slot = pad_connection_pad_init(hid->slots,
         adapter->name, dev_vid, dev_pid, adapter,
         &iohidmanager_hid);

   if (adapter->slot == -1)
      goto error;

   if (pad_connection_has_interface(hid->slots, adapter->slot))
      IOHIDDeviceRegisterInputReportCallback(device,
            adapter->data + 1, sizeof(adapter->data) - 1,
            iohidmanager_hid_device_report, adapter);
   else
      IOHIDDeviceRegisterInputValueCallback(device,
            iohidmanager_hid_device_input_callback, adapter);

   if (string_is_empty(adapter->name))
      goto error;

   /* scan for buttons, axis, hats */
   elements_raw = IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone);
   count        = (int)CFArrayGetCount(elements_raw);
   elements     = CFArrayCreateMutableCopy(
         kCFAllocatorDefault,(CFIndex)count,elements_raw);
   range        = CFRangeMake(0,count);

   CFArraySortValues(elements,
         range, iohidmanager_sort_elements, NULL);

   for (i = 0; i < count; i++)
   {
      IOHIDElementRef element = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, i);

      if (!element)
         continue;

      IOHIDElementType type = IOHIDElementGetType(element);
      uint32_t page         = (uint32_t)IOHIDElementGetUsagePage(element);
      uint32_t use          = (uint32_t)IOHIDElementGetUsage(element);
      uint32_t cookie       = (uint32_t)IOHIDElementGetCookie(element);

      int detected_button = 0;

      switch (page)
      {
         case kHIDPage_GenericDesktop:
            switch (type)
            {
               case kIOHIDElementTypeCollection:
               case kIOHIDElementTypeInput_ScanCodes:
               case kIOHIDElementTypeFeature:
               case kIOHIDElementTypeInput_Button:
               case kIOHIDElementTypeOutput:
               case kIOHIDElementTypeInput_Axis:
                  /* TODO/FIXME */
                  break;
               case kIOHIDElementTypeInput_Misc:
                  switch (use)
                  {
                     case kHIDUsage_GD_Hatswitch:
                        {
                           /* as far as I can tell, OSX only reports one Hat */
                           apple_input_rec_t *hat = (apple_input_rec_t *)malloc(sizeof(apple_input_rec_t));
                           hat->id                = 0;
                           hat->cookie            = (IOHIDElementCookie)cookie;
                           hat->next              = NULL;
                           adapter->hats          = hat;
                        }
                        break;
                     default:
                        {
                           uint32_t i = 0;
                           static const uint32_t axis_use_ids[6] =
                           { 48, 49, 51, 52, 50, 53 };

                           while (i < 6 && axis_use_ids[i] != use)
                              i++;

                           if (i < 6)
                           {

                              apple_input_rec_t *axis = (apple_input_rec_t *)malloc(sizeof(apple_input_rec_t));
                              axis->id                = i;
                              axis->cookie            = (IOHIDElementCookie)cookie;
                              axis->next              = NULL;

                              if(iohidmanager_check_for_id(adapter->axes,i))
                              {
                                 /* axis ID already exists, save to tmp for appending later */
                                 if(tmpAxes)
                                    iohidmanager_append_record(tmpAxes, axis);
                                 else
                                    tmpAxes = axis;
                              }
                              else
                              {
                                 found_axis[axis->id] = true;
                                 if(adapter->axes)
                                    iohidmanager_append_record(adapter->axes, axis);
                                 else
                                    adapter->axes = axis;
                              }
                           }
                           else
                              detected_button = 1;
                        }
                        break;
                  }
                  break;
            }
            break;
         case kHIDPage_Consumer:
         case kHIDPage_Button:
            switch (type)
            {
               case kIOHIDElementTypeCollection:
               case kIOHIDElementTypeFeature:
               case kIOHIDElementTypeInput_ScanCodes:
               case kIOHIDElementTypeInput_Axis:
               case kIOHIDElementTypeOutput:
                  /* TODO/FIXME */
                  break;
               case kIOHIDElementTypeInput_Misc:
               case kIOHIDElementTypeInput_Button:
                  detected_button = 1;
                  break;
            }
            break;
      }

      if (detected_button)
      {
         apple_input_rec_t *btn = (apple_input_rec_t *)malloc(sizeof(apple_input_rec_t));
         btn->id                = (uint32_t)use;
         btn->cookie            = (IOHIDElementCookie)cookie;
         btn->next              = NULL;

         if(iohidmanager_check_for_id(adapter->buttons,btn->id))
         {
            if(tmpButtons)
               iohidmanager_append_record_ordered(&tmpButtons, btn);
            else
               tmpButtons = btn;
         }
         else
         {
            if(adapter->buttons)
               iohidmanager_append_record_ordered(&adapter->buttons, btn);
            else
               adapter->buttons = btn;
         }
      }
   }

   /* take care of buttons/axes with duplicate 'use' values */
   for (i = 0; i < 6; i++)
   {
      if(found_axis[i] == false && tmpAxes)
      {
         apple_input_rec_t *next = tmpAxes->next;
         tmpAxes->id             = i;
         tmpAxes->next           = NULL;
         iohidmanager_append_record(adapter->axes, tmpAxes);
         tmpAxes = next;
      }
   }

   tmp = adapter->buttons;

   if (tmp)
   {
      while(tmp->next)
         tmp = tmp->next;
   }

   while(tmpButtons)
   {
      apple_input_rec_t *next = tmpButtons->next;

      tmpButtons->id          = tmp->id;
      tmpButtons->next        = NULL;
      tmp->next               = tmpButtons;

      tmp                     = tmp->next;
      tmpButtons              = next;
   }


   iohidmanager_hid_device_add_autodetect(adapter->slot,
         adapter->name, iohidmanager_hid.ident, dev_vid, dev_pid);

   return;

error:
   {
      apple_input_rec_t *tmp = NULL;
      while(adapter->hats != NULL)
      {
         tmp           = adapter->hats;
         adapter->hats = adapter->hats->next;
         free(tmp);
      }
      while(adapter->axes != NULL)
      {
         tmp           = adapter->axes;
         adapter->axes = adapter->axes->next;
         free(tmp);
      }
      while(adapter->buttons != NULL)
      {
         tmp              = adapter->buttons;
         adapter->buttons = adapter->buttons->next;
         free(tmp);
      }
      while(tmpAxes != NULL)
      {
         tmp     = tmpAxes;
         tmpAxes = tmpAxes->next;
         free(tmp);
      }
      while(tmpButtons != NULL)
      {
         tmp        = tmpButtons;
         tmpButtons = tmpButtons->next;
         free(tmp);
      }
      free(adapter);
   }
}
Beispiel #24
0
/* hid_open_path()
 *
 * path must be a valid path to an IOHIDDevice in the IOService plane
 * Example: "IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/EHC1@1D,7/AppleUSBEHCI/PLAYSTATION(R)3 Controller@fd120000/IOUSBInterface@0/IOUSBHIDDriver"
 */
hid_device * HID_API_EXPORT hid_open_path(const char *path)
{
	hid_device *dev = NULL;
	io_registry_entry_t entry = MACH_PORT_NULL;

	dev = new_hid_device();

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

	/* Get the IORegistry entry for the given path */
	entry = IORegistryEntryFromPath(kIOMasterPortDefault, path);
	if (entry == MACH_PORT_NULL) {
		/* Path wasn't valid (maybe device was removed?) */
		goto return_error;
	}

	/* Create an IOHIDDevice for the entry */
	dev->device_handle = IOHIDDeviceCreate(kCFAllocatorDefault, entry);
	if (dev->device_handle == NULL) {
		/* Error creating the HID device */
		goto return_error;
	}

	/* Open the IOHIDDevice */
	IOReturn ret = IOHIDDeviceOpen(dev->device_handle, kIOHIDOptionsTypeSeizeDevice);
	if (ret == kIOReturnSuccess) {
		char str[32];

		/* Create the buffers for receiving data */
		dev->max_input_report_len = (CFIndex) get_max_report_length(dev->device_handle);
		dev->input_report_buf = calloc(dev->max_input_report_len, sizeof(uint8_t));

		/* Create the Run Loop Mode for this device.
		   printing the reference seems to work. */
		sprintf(str, "HIDAPI_%p", dev->device_handle);
		dev->run_loop_mode = 
			CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII);
		
		/* Attach the device to a Run Loop */
		IOHIDDeviceRegisterInputReportCallback(
			dev->device_handle, dev->input_report_buf, dev->max_input_report_len,
			&hid_report_callback, dev);
		IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev);

		/* Start the read thread */
		pthread_create(&dev->thread, NULL, read_thread, dev);

		/* Wait here for the read thread to be initialized. */
		pthread_barrier_wait(&dev->barrier);
		
		IOObjectRelease(entry);
		return dev;
	}
	else {
		goto return_error;
	}

return_error:
	if (dev->device_handle != NULL)
		CFRelease(dev->device_handle);

	if (entry != MACH_PORT_NULL)
		IOObjectRelease(entry);

	free_hid_device(dev);
	return NULL;
}
Beispiel #25
0
int yyySetup(yInterfaceSt *iface,char *errmsg)
{
    char str[32];
    int i;
    CFIndex deviceCount;
    IOHIDDeviceRef *dev_refs;


    if (yContext->osx_flags & YCTX_OSX_MULTIPLES_HID) {
        if (YISERR(setupHIDManager(yContext, &iface->hid,errmsg))) {
            return YAPI_IO_ERROR;
        }
        // get all device detected by the OSX
        dev_refs = getDevRef(&iface->hid, &deviceCount);
    } else {
        dev_refs = getDevRef(&yContext->hid, &deviceCount);
    }
    if(dev_refs == NULL) {
        return YERRMSG(YAPI_IO_ERROR,"Device disapear before yyySetup");
    }


    for(i=0 ; i < deviceCount ;i++){
        u16 vendorid;
        u16 deviceid;
        IOHIDDeviceRef dev = dev_refs[i];
        vendorid = get_int_property(dev,CFSTR(kIOHIDVendorIDKey));
        deviceid = get_int_property(dev,CFSTR(kIOHIDProductIDKey));
        if (iface->vendorid == vendorid && iface->deviceid == deviceid){
            char serial[YOCTO_SERIAL_LEN * 2];
            memset(serial, 0, YOCTO_SERIAL_LEN * 2);
            get_txt_property(dev,serial,YOCTO_SERIAL_LEN * 2, CFSTR(kIOHIDSerialNumberKey));
            if (YSTRCMP(serial, iface->serial) == 0){
                HALLOG("right Interface detected (%x:%x:%s)\n",vendorid,deviceid,iface->serial);
                iface->devref = dev;
                break;
            }
        }
    }
    yFree(dev_refs);
    if (i == deviceCount) {
        return YERRMSG(YAPI_IO_ERROR,"Unable to match device detected");
    }

    IOReturn ret = IOHIDDeviceOpen(iface->devref, kIOHIDOptionsTypeNone);
    if (ret != kIOReturnSuccess) {
        YSPRINTF(str,32,"Unable to open device (0x%x)",ret);
        return YERRMSG(YAPI_IO_ERROR,str);
    }

    yPktQueueInit(&iface->rxQueue);
	yPktQueueInit(&iface->txQueue);


    /* Create the Run Loop Mode for this device. printing the reference seems to work. */
    sprintf(str, "yocto_%p", iface->devref);
    iface->run_loop_mode = CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII);
    /* Attach the device to a Run Loop */
    IOHIDDeviceScheduleWithRunLoop(iface->devref, yContext->usb_run_loop, iface->run_loop_mode);
    IOHIDDeviceRegisterInputReportCallback( iface->devref,              // IOHIDDeviceRef for the HID device
                                           (u8*) &iface->tmprxpkt,     // pointer to the report data
                                           USB_PKT_SIZE,               // number of bytes in the report (CFIndex)
                                           &Handle_IOHIDDeviceIOHIDReportCallback,   // the callback routine
                                           iface);                     // context passed to callback

    // save setuped iface pointer in context in order
    // to retreive it durring unplugcallback
    for (i=0; i< SETUPED_IFACE_CACHE_SIZE ; i++) {
        if(yContext->setupedIfaceCache[i]==NULL){
            yContext->setupedIfaceCache[i] = iface;
            break;
        }
    }
    if (i==SETUPED_IFACE_CACHE_SIZE) {
        return YERRMSG(YAPI_IO_ERROR,"Too many setuped USB interfaces");
    }
    iface->flags.yyySetupDone = 1;
    return 0;
}
Beispiel #26
0
  void
  osxHIDInputDevice::AddDevice(void *context,
			       IOReturn /*result*/, void */*sender*/, IOHIDDeviceRef device) {
    osxHIDInputDevice *self = (osxHIDInputDevice*)context ;

    URI devUri = hidDeviceURI(device) ;

    // std::cerr << std::endl << self->uri.asString() << std::endl << devUri.asString() << std::endl << std::endl ;

    bool match = self->theDevice==0 && (self->uri.isEmpty() || self->uri.scheme=="any" || self->uri.resemble(devUri)) ;
    if (self->debugLevel>0) {
      std::cerr << (match?"+ ":"  ") ;
      hidDebugDevice(device, std::cerr) ;
      std::cerr << std::endl ;
    }
    if (!match) return ;

    self->theDevice = new __device(device) ;
    self->uri = devUri ;

    CFDataRef descriptor = (CFDataRef)IOHIDDeviceGetProperty(self->theDevice->device, CFSTR(kIOHIDReportDescriptorKey)) ;
    if (descriptor) {
      const UInt8 *bytes = CFDataGetBytePtr(descriptor) ;
      CFIndex length = CFDataGetLength(descriptor) ;
      if (self->inputreport_callback && !self->parser->setDescriptor(bytes, length))
        std::cerr << "osxHIDInputDevice::AddDevice: unable to parse the HID report descriptor" << std::endl;
      if (self->debugLevel > 1) {
        std::cerr << "    HID report descriptor: [ " << std::flush ;
        for (int i=0; i<length; ++i)
          std::cerr << std::hex << std::setfill('0') << std::setw(2) << (int)bytes[i] << " " ;
        std::cerr << "]" << std::endl ;
      }
    }

#if DEBUG_MODE
      std::cerr << "Setting up callbacks" << std::endl ;
#endif

    // ----------------------------------------------------------------
    
    if (self->inputreport_callback) {
#if DEBUG_MODE
      std::cerr << "Setting up report callback" << std::endl ;
#endif
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
      IOHIDDeviceRegisterInputReportWithTimeStampCallback(device,
					     self->theDevice->report, sizeof(self->theDevice->report),
					     self->inputreport_callback, self->inputreport_context) ;
#else
      IOHIDDeviceRegisterInputReportCallback(device,
					     self->theDevice->report, sizeof(self->theDevice->report),
					     self->inputreport_callback, self->inputreport_context) ;
#endif
    }

    // ----------------------------------------------------------------
    
    if (self->value_callback) {
#if DEBUG_MODE
      std::cerr << "Setting up value callback" << std::endl ;
#endif     
      IOHIDDeviceSetInputValueMatchingMultiple(device, self->elements_match) ; 
      IOHIDDeviceRegisterInputValueCallback(device, self->value_callback, self->value_context) ;
    }

    // ----------------------------------------------------------------
    
    if (self->queue_callback) {
#if DEBUG_MODE
      std::cerr << "Setting up queue callback" << std::endl ;
#endif
      self->theDevice->queue = IOHIDQueueCreate(kCFAllocatorDefault, device, queueSize, kIOHIDOptionsTypeNone) ;
      if (self->elements_match) {
#if DEBUG && DEBUG_MATCHING_ELEMENTS	
	std::cerr << "Queue, elements_match" << std::endl ;
#endif
	CFIndex mcount = CFArrayGetCount(self->elements_match) ;
	for (CFIndex mindex=0; mindex<mcount; ++mindex) {
	  CFDictionaryRef matching = (CFDictionaryRef)CFArrayGetValueAtIndex(self->elements_match, mindex) ;
	  CFArrayRef elements = IOHIDDeviceCopyMatchingElements(device, matching, kIOHIDOptionsTypeNone) ;
	  if (!elements) continue ;
	  CFIndex ecount = CFArrayGetCount(elements) ;
	  for (CFIndex eindex=0; eindex<ecount; ++eindex) {
	    IOHIDElementRef e = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, eindex) ;
	    IOHIDQueueAddElement(self->theDevice->queue, e) ;
#if DEBUG && DEBUG_MATCHING_ELEMENTS
	    std::cerr << "elements_match EINDEX: " << eindex
		      << ", usagepage: " << IOHIDElementGetUsagePage(e)
		      << ", usage: " << IOHIDElementGetUsage(e)
		      << std::endl ;
#endif
	  }
	}
      } else {
#if DEBUG && DEBUG_MATCHING_ELEMENTS	
	std::cerr << "Queue, no elements_match" << std::endl ;
#endif
	CFArrayRef elements = IOHIDDeviceCopyMatchingElements(device, 0, kIOHIDOptionsTypeNone) ;
	if (elements) {
	  CFIndex ecount = CFArrayGetCount(elements) ;
	  for (CFIndex eindex=0; eindex<ecount; ++eindex) {
	    IOHIDElementRef e = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, eindex) ;
	    IOHIDQueueAddElement(self->theDevice->queue, e) ;
#if DEBUG && DEBUG_MATCHING_ELEMENTS
	    std::cerr << "!elements_match EINDEX: " << eindex
		      << ", usagepage: " << IOHIDElementGetUsagePage(e)
		      << ", usage: " << IOHIDElementGetUsage(e)
		      << std::endl ;
#endif
	  }
	}
      }
      IOHIDQueueRegisterValueAvailableCallback(self->theDevice->queue, self->queue_callback, self->queue_context) ;
      IOHIDQueueScheduleWithRunLoop(self->theDevice->queue, CFRunLoopGetMain(), kCFRunLoopDefaultMode) ;
      IOHIDQueueStart(self->theDevice->queue) ;
    }

    // ----------------------------------------------------------------
  }
Beispiel #27
0
bool HIDDevice::openDevice()
{
    
    // Have to iterate through devices again to generate paths.
	CFSetRef deviceSet = IOHIDManagerCopyDevices(HIDManager->HIDManager);
	CFIndex deviceCount = CFSetGetCount(deviceSet);
    
    // Allocate a block of memory and read the set into it.
    IOHIDDeviceRef* devices = (IOHIDDeviceRef*) OVR_ALLOC(sizeof(IOHIDDeviceRef) * deviceCount);
    CFSetGetValues(deviceSet, (const void **) devices);
    
    
    // Iterate over devices.
    IOHIDDeviceRef device = NULL;

    for (CFIndex deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++)
    {
        IOHIDDeviceRef tmpDevice = devices[deviceIndex];
        
        if (!tmpDevice)
        {
            continue;
        }
        
        String path;
        if (!HIDManager->getPath(tmpDevice, &path))
        {
            continue;
        }
        
        if (path == DevDesc.Path)
        {
            device = tmpDevice;
            break;
        }
    }
    
    
    OVR_FREE(devices);
    
    if (!device)
    {
        CFRelease(deviceSet);
        return false;
    }
    
    // Attempt to open device.
    if (IOHIDDeviceOpen(device, kIOHIDOptionsTypeSeizeDevice)
        != kIOReturnSuccess)
    {
        CFRelease(deviceSet);
        return false;
    }

    // Retain the device before we release the set.
    CFRetain(device);
    CFRelease(deviceSet);
    
    
    Device = device;

    
    if (!initInfo())
    {
        IOHIDDeviceClose(Device, kIOHIDOptionsTypeSeizeDevice);
        CFRelease(Device);
        Device = NULL;
        return false;
    }
    
    
    // Setup the Run Loop and callbacks.
    IOHIDDeviceScheduleWithRunLoop(Device,
                                   HIDManager->getRunLoop(),
                                   kCFRunLoopDefaultMode);
    
    IOHIDDeviceRegisterInputReportCallback(Device,
                                           ReadBuffer,
                                           ReadBufferSize,
                                           staticHIDReportCallback,
                                           this);

    IOHIDDeviceRegisterRemovalCallback(Device,
                                       staticDeviceRemovedCallback,
                                       this);
    
    return true;
}