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()); }
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); } }
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"); } */ }
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; }
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); } }
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); }
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(); }
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); }
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); }
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"); }
/** * @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; }
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); }
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); }
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); }
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); }
//! 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; } }
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); } }
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; }
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); } }
/* 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; }
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; }
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) ; } // ---------------------------------------------------------------- }
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; }