static void *read_thread(void *param) { hid_device *dev = param; /* Move the device's run loop to this thread. */ IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode); /* Create the RunLoopSource which is used to signal the event loop to stop when hid_close() is called. */ CFRunLoopSourceContext ctx; memset(&ctx, 0, sizeof(ctx)); ctx.version = 0; ctx.info = dev; ctx.perform = &perform_signal_callback; dev->source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0/*order*/, &ctx); CFRunLoopAddSource(CFRunLoopGetCurrent(), dev->source, dev->run_loop_mode); /* Store off the Run Loop so it can be stopped from hid_close() and on device disconnection. */ dev->run_loop = CFRunLoopGetCurrent(); /* Notify the main thread that the read thread is up and running. */ pthread_barrier_wait(&dev->barrier); /* Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input reports into the hid_report_callback(). */ SInt32 code; while (!dev->shutdown_thread && !dev->disconnected) { code = CFRunLoopRunInMode(dev->run_loop_mode, 1000/*sec*/, FALSE); /* Return if the device has been disconnected */ if (code == kCFRunLoopRunFinished) { dev->disconnected = 1; break; } /* Break if The Run Loop returns Finished or Stopped. */ if (code != kCFRunLoopRunTimedOut && code != kCFRunLoopRunHandledSource) { /* There was some kind of error. Setting shutdown seems to make sense, but there may be something else more appropriate */ dev->shutdown_thread = 1; break; } } /* Now that the read thread is stopping, Wake any threads which are waiting on data (in hid_read_timeout()). Do this under a mutex to make sure that a thread which is about to go to sleep waiting on the condition acutally will go to sleep before the condition is signaled. */ pthread_mutex_lock(&dev->mutex); pthread_cond_broadcast(&dev->condition); pthread_mutex_unlock(&dev->mutex); /* 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); } /* Wait here until hid_close() is called and makes it past the call to CFRunLoopWakeUp(). This thread still needs to be valid when that function is called on the other thread. */ pthread_barrier_wait(&dev->shutdown_barrier); return NULL; }
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 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"); } */ }
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); } }
Burger::RunQueue::eReturnCode BURGER_API Burger::Mouse::Poll(void *pData) { while (CFRunLoopRunInMode(g_BurgerMouse,0,TRUE)==kCFRunLoopRunHandledSource) { } #if 0 Word i; Mouse *pMouse = static_cast<Mouse *>(pData); DeviceStruct *pRat = pMouse->m_Mice; for (i = 0; i < pMouse->m_uMiceCount; i++) { if (pRat->m_bUnplugged) { IOHIDDeviceRef pDevice = pRat->m_pDevice; if (pDevice) { if (IOHIDDeviceOpen(pDevice,kIOHIDOptionsTypeNone) == kIOReturnSuccess) { pRat->m_bUnplugged = FALSE; // Connected! IOHIDDeviceRegisterRemovalCallback(pDevice,DisconnectionCallback,pMouse); IOHIDDeviceRegisterInputValueCallback(pDevice,InputCallback,pMouse); CFRunLoopRef pRunLoop = CFRunLoopGetCurrent(); IOHIDDeviceScheduleWithRunLoop(pDevice,pRunLoop,g_BurgerMouse); } } } ++pRat; } #endif return RunQueue::OKAY; }
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); }
static void JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDeviceRef ioHIDDeviceObject) { recDevice *device; if (res != kIOReturnSuccess) { return; } if (JoystickAlreadyKnown(ioHIDDeviceObject)) { return; /* IOKit sent us a duplicate. */ } device = (recDevice *) SDL_calloc(1, sizeof(recDevice)); if (!device) { SDL_OutOfMemory(); return; } if (!GetDeviceInfo(ioHIDDeviceObject, device)) { SDL_free(device); return; /* not a device we care about, probably. */ } /* Get notified when this device is disconnected. */ IOHIDDeviceRegisterRemovalCallback(ioHIDDeviceObject, JoystickDeviceWasRemovedCallback, device); IOHIDDeviceScheduleWithRunLoop(ioHIDDeviceObject, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE); /* Allocate an instance ID for this device */ device->instance_id = ++s_joystick_instance_id; /* We have to do some storage of the io_service_t for SDL_HapticOpenFromJoystick */ if (IOHIDDeviceGetService != NULL) { /* weak reference: available in 10.6 and later. */ const io_service_t ioservice = IOHIDDeviceGetService(ioHIDDeviceObject); if ((ioservice) && (FFIsForceFeedback(ioservice) == FF_OK)) { device->ffservice = ioservice; #if SDL_HAPTIC_IOKIT MacHaptic_MaybeAddDevice(ioservice); #endif } } device->send_open_event = 1; s_bDeviceAdded = SDL_TRUE; /* Add device to the end of the list */ if ( !gpDeviceList ) { gpDeviceList = device; } else { recDevice *curdevice; curdevice = gpDeviceList; while ( curdevice->pNext ) { curdevice = curdevice->pNext; } curdevice->pNext = device; } }
Burger::Mouse::Mouse(GameApp *pGameApp) : m_pGameApp(pGameApp), m_MouseLock(), m_pHIDManager(NULL), m_uMiceCount(0), m_uX(0), m_uY(0), m_uBoundsX(640), m_uBoundsY(480), m_iDeltaX(0), m_iDeltaY(0), m_iMouseWheelX(0), m_iMouseWheelY(0), m_uButtons(0), m_uPressedButtons(0), m_bButtonSwap(FALSE), m_uArrayStart(0), m_uArrayEnd(0) { // Back link to the game app CFMutableDictionaryRef pDictionary = Globals::CreateHIDDictionary(kHIDPage_GenericDesktop,kHIDUsage_GD_Mouse); if (pDictionary != NULL) { m_pHIDManager = IOHIDManagerCreate(kCFAllocatorDefault,kIOHIDOptionsTypeNone); if (m_pHIDManager != NULL) { CFRunLoopRef pRunLoop = CFRunLoopGetCurrent(); IOHIDManagerRegisterDeviceMatchingCallback(m_pHIDManager,EnumerationCallback,this); IOHIDManagerScheduleWithRunLoop(m_pHIDManager,pRunLoop,g_BurgerMouse); IOHIDManagerSetDeviceMatching(m_pHIDManager,pDictionary); IOHIDManagerOpen(m_pHIDManager,kIOHIDOptionsTypeNone); // Handle the run loops Poll(this); // All scanned! IOHIDManagerUnscheduleFromRunLoop(m_pHIDManager,pRunLoop,g_BurgerMouse); IOHIDManagerRegisterDeviceMatchingCallback(m_pHIDManager,NULL, NULL); // Open all the located devices Word i; DeviceStruct *pRat = m_Mice; for (i = 0; i < m_uMiceCount; i++) { IOHIDDeviceRef pDevice = pRat->m_pDevice; if (IOHIDDeviceOpen(pDevice,kIOHIDOptionsTypeNone) != kIOReturnSuccess) { pRat->m_pDevice = NULL; // Hmm. Toast it pRat->m_bUnplugged = FALSE; // Don't attempt to reconnect } else { IOHIDDeviceRegisterRemovalCallback(pDevice,DisconnectionCallback,this); IOHIDDeviceRegisterInputValueCallback(pDevice,InputCallback,this); IOHIDDeviceScheduleWithRunLoop(pDevice,pRunLoop,g_BurgerMouse); } ++pRat; } pGameApp->AddRoutine(Poll,NULL,this,RunQueue::PRIORITY_MOUSE); } CFRelease(pDictionary); } }
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); }
// send - send a packet // Inputs: // num = device to transmit to (zero based) // buf = buffer containing packet to send // len = number of bytes to transmit // timeout = time to wait, in milliseconds // Output: // number of bytes sent, or -1 on error // int pjrc_rawhid::send(int num, void *buf, int len, int timeout) { hid_t *hid; int result=-100; hid = get_hid(num); if (!hid || !hid->open) return -1; #if 1 #warning "Send timeout not implemented on MACOSX" uint8_t *report_buf = (uint8_t *) malloc(len); memcpy(&report_buf[0], buf,len); // Note: packet processing done in OS indepdent code IOReturn ret = IOHIDDeviceSetReport(hid->ref, kIOHIDReportTypeOutput, 2, (uint8_t *)report_buf, len); result = (ret == kIOReturnSuccess) ? len : -1; if (err_get_system(ret) == err_get_system(sys_iokit)) { // The error was in the I/O Kit system UInt32 codeValue = err_get_code(ret); qDebug("Returned: %x", codeValue); // Can now perform test on error code, display it to user, or whatever. usleep(1000000); } #endif #if 0 // No matter what I tried this never actually sends an output // report and output_callback never gets called. Why?? // Did I miss something? This is exactly the same params as // the sync call that works. Is it an Apple bug? // (submitted to Apple on 22-sep-2009, problem ID 7245050) // IOHIDDeviceScheduleWithRunLoop(hid->ref, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); // should already be scheduled with run loop by attach_callback, // sadly this doesn't make any difference either way // IOHIDDeviceSetReportWithCallback(hid->ref, kIOHIDReportTypeOutput, 0, buf, len, (double)timeout / 1000.0, output_callback, &result); while (1) { printf("enter run loop (send)\n"); CFRunLoopRun(); printf("leave run loop (send)\n"); if (result > -100) break; if (!hid->open) { result = -1; break; } } #endif return result; }
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); }
/** * @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 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); }
// rawhid_send - send a packet // Inputs: // num = device to transmit to (zero based) // buf = buffer containing packet to send // len = number of bytes to transmit // timeout = time to wait, in milliseconds // Output: // number of bytes sent, or -1 on error // int rawhid_send(int num, void *buf, int len, int timeout) { //fprintf(stderr,"rawhid_send num: %d\n",num); hid_t *hid; int result=-100; hid = get_hid(num); if (!hid || !hid->open) return -1; //fprintf(stderr,"rawhid_send A\n"); #if 1 #warning "Send timeout not implemented on MACOSX" IOReturn ret = IOHIDDeviceSetReport(hid->ref, kIOHIDReportTypeOutput, 0, buf, len); result = (ret == kIOReturnSuccess) ? len : -1; //fprintf(stderr,"rawhid_send B result: %d\n",result); #endif #if 0 // No matter what I tried this never actually sends an output // report and output_callback never gets called. Why?? // Did I miss something? This is exactly the same params as // the sync call that works. Is it an Apple bug? // (submitted to Apple on 22-sep-2009, problem ID 7245050) // fprintf(stderr,"rawhid_send C\n"); IOHIDDeviceScheduleWithRunLoop(hid->ref, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); // should already be scheduled with run loop by attach_callback, // sadly this doesn't make any difference either way // IOHIDDeviceSetReportWithCallback(hid->ref, kIOHIDReportTypeOutput, 0, buf, len, (double)timeout / 1000.0, output_callback, &result); //fprintf(stderr,"rawhid_send D\n"); while (1) { fprintf(stderr,"enter run loop (send)\n"); CFRunLoopRun(); fprintf(stderr,"leave run loop (send)\n"); if (result > -100) break; if (!hid->open) { result = -1; break; } } #endif fprintf(stderr,"rawhid_send result: %d\n",result); return result; }
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); }
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); }
void JoypadOSX::_device_added(IOReturn p_res, IOHIDDeviceRef p_device) { if (p_res != kIOReturnSuccess || have_device(p_device)) { return; } joypad new_joypad; if (is_joypad(p_device)) { configure_joypad(p_device, &new_joypad); #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 if (IOHIDDeviceGetService != NULL) { #endif const io_service_t ioservice = IOHIDDeviceGetService(p_device); if ((ioservice) && (FFIsForceFeedback(ioservice) == FF_OK) && new_joypad.config_force_feedback(ioservice)) { new_joypad.ffservice = ioservice; } #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 } #endif device_list.push_back(new_joypad); } IOHIDDeviceRegisterRemovalCallback(p_device, joypad_removed_callback, (void *)(intptr_t)new_joypad.id); IOHIDDeviceScheduleWithRunLoop(p_device, CFRunLoopGetCurrent(), GODOT_JOY_LOOP_RUN_MODE); }
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); } }
static void JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDeviceRef ioHIDDeviceObject) { recDevice *device; int device_index = 0; io_service_t ioservice; if (res != kIOReturnSuccess) { return; } if (JoystickAlreadyKnown(ioHIDDeviceObject)) { return; /* IOKit sent us a duplicate. */ } device = (recDevice *) SDL_calloc(1, sizeof(recDevice)); if (!device) { SDL_OutOfMemory(); return; } if (!GetDeviceInfo(ioHIDDeviceObject, device)) { SDL_free(device); return; /* not a device we care about, probably. */ } if (SDL_IsGameControllerNameAndGUID(device->product, device->guid) && SDL_ShouldIgnoreGameController(device->product, device->guid)) { SDL_free(device); return; } /* Get notified when this device is disconnected. */ IOHIDDeviceRegisterRemovalCallback(ioHIDDeviceObject, JoystickDeviceWasRemovedCallback, device); IOHIDDeviceScheduleWithRunLoop(ioHIDDeviceObject, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE); /* Allocate an instance ID for this device */ device->instance_id = ++s_joystick_instance_id; /* We have to do some storage of the io_service_t for SDL_HapticOpenFromJoystick */ ioservice = IOHIDDeviceGetService(ioHIDDeviceObject); #if SDL_HAPTIC_IOKIT if ((ioservice) && (FFIsForceFeedback(ioservice) == FF_OK)) { device->ffservice = ioservice; MacHaptic_MaybeAddDevice(ioservice); } #endif /* Add device to the end of the list */ if ( !gpDeviceList ) { gpDeviceList = device; } else { recDevice *curdevice; curdevice = gpDeviceList; while ( curdevice->pNext ) { ++device_index; curdevice = curdevice->pNext; } curdevice->pNext = device; ++device_index; /* bump by one since we counted by pNext. */ } SDL_PrivateJoystickAdded(device_index); }
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; }
static void JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDeviceRef ioHIDDeviceObject) { recDevice *device; int device_index = 0; if (res != kIOReturnSuccess) { return; } if (JoystickAlreadyKnown(ioHIDDeviceObject)) { return; /* IOKit sent us a duplicate. */ } device = (recDevice *) SDL_calloc(1, sizeof(recDevice)); if (!device) { SDL_OutOfMemory(); return; } if (!GetDeviceInfo(ioHIDDeviceObject, device)) { SDL_free(device); return; /* not a device we care about, probably. */ } /* Get notified when this device is disconnected. */ IOHIDDeviceRegisterRemovalCallback(ioHIDDeviceObject, JoystickDeviceWasRemovedCallback, device); IOHIDDeviceScheduleWithRunLoop(ioHIDDeviceObject, CFRunLoopGetCurrent(), SDL_JOYSTICK_RUNLOOP_MODE); /* Allocate an instance ID for this device */ device->instance_id = ++s_joystick_instance_id; /* We have to do some storage of the io_service_t for SDL_HapticOpenFromJoystick */ #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 if (IOHIDDeviceGetService != NULL) { /* weak reference: available in 10.6 and later. */ #endif const io_service_t ioservice = IOHIDDeviceGetService(ioHIDDeviceObject); #if SDL_HAPTIC_IOKIT if ((ioservice) && (FFIsForceFeedback(ioservice) == FF_OK)) { device->ffservice = ioservice; MacHaptic_MaybeAddDevice(ioservice); } #endif #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 } #endif /* Add device to the end of the list */ if ( !gpDeviceList ) { gpDeviceList = device; } else { recDevice *curdevice; curdevice = gpDeviceList; while ( curdevice->pNext ) { ++device_index; curdevice = curdevice->pNext; } curdevice->pNext = device; ++device_index; /* bump by one since we counted by pNext. */ } /* !!! FIXME: why isn't there an SDL_PrivateJoyDeviceAdded()? */ #if !SDL_EVENTS_DISABLED { SDL_Event event; event.type = SDL_JOYDEVICEADDED; if (SDL_GetEventState(event.type) == SDL_ENABLE) { event.jdevice.which = device_index; if ((SDL_EventOK == NULL) || (*SDL_EventOK) (SDL_EventOKParam, &event)) { SDL_PushEvent(&event); } } } #endif /* !SDL_EVENTS_DISABLED */ }
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; }
int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) { int ret_val = -1; /* Lock this function */ pthread_mutex_lock(&dev->mutex); /* There's an input report queued up. Return it. */ if (dev->input_reports) { /* Return the first one */ ret_val = return_data(dev, data, length); goto ret; } /* Return if the device has been disconnected. */ if (dev->disconnected) { ret_val = -1; goto ret; } /* There are no input reports queued up. Need to get some from the OS. */ /* Move the device's run loop to this thread. */ IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode); if (dev->blocking) { /* Run the Run Loop until it stops timing out. In other words, until something happens. This is necessary because there is no INFINITE timeout value. */ SInt32 code; while (1) { code = CFRunLoopRunInMode(dev->run_loop_mode, 1000, TRUE); /* Return if the device has been disconnected */ if (code == kCFRunLoopRunFinished) { dev->disconnected = 1; ret_val = -1; goto ret; } /* Return if some data showed up. */ if (dev->input_reports) break; /* Break if The Run Loop returns Finished or Stopped. */ if (code != kCFRunLoopRunTimedOut && code != kCFRunLoopRunHandledSource) break; } /* See if the run loop and callback gave us any reports. */ if (dev->input_reports) { ret_val = return_data(dev, data, length); goto ret; } else { dev->disconnected = 1; ret_val = -1; /* An error occured (maybe CTRL-C?). */ goto ret; } } else { /* Non-blocking. See if the OS has any reports to give. */ SInt32 code; code = CFRunLoopRunInMode(dev->run_loop_mode, 0, TRUE); if (code == kCFRunLoopRunFinished) { /* The run loop is finished, indicating an error or the device had been disconnected. */ dev->disconnected = 1; ret_val = -1; goto ret; } if (dev->input_reports) { /* Return the first one */ ret_val = return_data(dev, data, length); goto ret; } else { ret_val = 0; /* No data*/ goto ret; } } ret: /* Unlock */ pthread_mutex_unlock(&dev->mutex); return ret_val; }
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 */ if (!hid_mgr) init_hid_manager(); 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, kIOHIDOptionsTypeSeizeDevice); //IOReturn ret = IOHIDDeviceOpen(os_dev, kIOHIDOptionsTypeNone); if (ret == kIOReturnSuccess) { char str[32]; CFIndex max_input_report_len; free(device_array); CFRelease(device_set); dev->device_handle = os_dev; /* Create the buffers for receiving data */ max_input_report_len = (CFIndex) get_max_report_length(os_dev); dev->input_report_buf = calloc(max_input_report_len, sizeof(uint8_t)); /* Create the Run Loop Mode for this device. printing the reference seems to work. */ sprintf(str, "%p", os_dev); dev->run_loop_mode = CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII); /* Attach the device to a Run Loop */ IOHIDDeviceScheduleWithRunLoop(os_dev, CFRunLoopGetCurrent(), dev->run_loop_mode); IOHIDDeviceRegisterInputReportCallback( os_dev, dev->input_report_buf, max_input_report_len, &hid_report_callback, dev); IOHIDManagerRegisterDeviceRemovalCallback(hid_mgr, hid_device_removal_callback, NULL); return dev; } else { goto return_error; } } } return_error: free(device_array); CFRelease(device_set); free_hid_device(dev); return NULL; }