//////////////////////////////////////////////////////////// /// Enumerate all attached joystick/gamepad controllers //////////////////////////////////////////////////////////// int JoystickSupport::EnumerateDevices(std::vector<JoystickDevice> &devices) { IOReturn ioRes = IOMasterPort(bootstrap_port, &myMasterPort); if (ioRes != kIOReturnSuccess) return 0; CFMutableDictionaryRef hidMatchDictionary = 0; io_iterator_t hidObjectIterator = 0; hidMatchDictionary = IOServiceMatching(kIOHIDDeviceKey); ioRes = IOServiceGetMatchingServices( myMasterPort, hidMatchDictionary, &hidObjectIterator ); if ((ioRes != kIOReturnSuccess) || (hidObjectIterator == nil)) { return 0; } io_object_t hidDevice; kern_return_t result; CFMutableDictionaryRef properties; CFTypeRef object; long usagePage, usage, locationID; while ((hidDevice = IOIteratorNext(hidObjectIterator))) { result = IORegistryEntryCreateCFProperties(hidDevice, &properties, kCFAllocatorDefault, kNilOptions); if ((result != KERN_SUCCESS) || (properties == nil)) continue; object = CFDictionaryGetValue(properties, CFSTR(kIOHIDPrimaryUsagePageKey)); if (object) { if (!CFNumberGetValue((CFNumberRef)object, kCFNumberLongType, &usagePage)) continue; object = CFDictionaryGetValue(properties, CFSTR(kIOHIDPrimaryUsageKey)); if (object) { if(!CFNumberGetValue((CFNumberRef)object, kCFNumberLongType, &usage)) continue; } } object = CFDictionaryGetValue(properties, CFSTR(kIOHIDLocationIDKey)); if (!object) locationID = 0; else { if(!CFNumberGetValue((CFNumberRef)object, kCFNumberLongType, &locationID)) locationID = 0; } if (usagePage == kHIDPage_GenericDesktop) { switch(usage) { case kHIDUsage_GD_Joystick : case kHIDUsage_GD_GamePad : { JoystickDevice Joystick; EnumerateElements(properties, &Joystick); if (GetDeviceInterface(&hidDevice, Joystick) == kIOReturnSuccess) { devices.push_back(Joystick); std::cout << "Device with " << Joystick.axis.size() << " axes and " << Joystick.buttons.size() << " buttons was found." << std::endl; } } break; } } CFRelease(properties); ioRes = IOObjectRelease(hidDevice); if(ioRes != kIOReturnSuccess) std::cout << "Error releasing device" << std::endl; } IOObjectRelease(hidObjectIterator); return 1; }
int main ( int argc, const char * argv[] ) { // // allocate our DMA buffers using vm_allocate // vm_address_t buffer = nil ; ::vm_allocate( mach_task_self(), & buffer, kBufferSize, true ) ; assert( buffer ) ; // // split up vm_allocated buffer into buffers we will use // in our DMA program // UInt8* buffers[3] = { (UInt8*)buffer, (UInt8*)buffer + 1024, (UInt8*)buffer + 4096 } ; // // put test data into our DMA program buffers // snprintf( reinterpret_cast<char*>(buffers[0]), 1024, "sample text in a buffer" ) ; snprintf( reinterpret_cast<char*>(buffers[1]), 3048, "<this space intentionally left blank>" ) ; snprintf( reinterpret_cast<char*>(buffers[2]), 1024, "next sample text is here" ) ; // // run test // IOReturn error = kIOReturnSuccess ; cout << i++ << "\n### SETTING UP\n" ; for( int index=0; index < 3; ++index ) cout << i << "buffers[" << index << "] " << (char*)(buffers[index]) << endl ; cout << i++ << "Getting device interface...\n" ; IOFireWireLibNubRef localNode = 0 ; IOCFPlugInInterfaceRef cfPlugInInterface ; error = GetDeviceInterface( & cfPlugInInterface, & localNode ) ; cout << i-- << "..." << _success << endl ; if ( !error ) { cout << i << "Opening...\n" ; error = (**localNode).Open( localNode ) ; } // if (!error) // { // error = (**localNode).AddCallbackDispatcherToRunLoop( localNode, ::CFRunLoopGetCurrent() ) ; // if (!error) // (**localNode).TurnOnNotification( localNode ) ; // } if ( !error ) { cout << i++ << "Adding isoch dispatcher to run loop...\n" ; error = (**localNode).AddIsochCallbackDispatcherToRunLoop( localNode, CFRunLoopGetCurrent() ) ; } IOFireWireLibDCLCommandPoolRef commandPool = 0 ; IOFireWireLibRemoteIsochPortRef remoteIsochPort = 0 ; IOFireWireLibLocalIsochPortRef localIsochPort = 0 ; IOFireWireLibIsochChannelRef isochChannel = 0 ; if ( !error ) { cout << i++ << "Creating DCL command pool...\n" ; error = CreateDCLCommandPool( localNode, & commandPool ) ; } if ( !error ) { cout << i++ << "Creating remote isochronous port...\n" ; error = CreateRemoteIsochPort( localNode, & remoteIsochPort ) ; cout << i-- << "..." << _success << endl ; } if ( !error ) { cout << i << "Creating local isoch port...\n" ; error = CreateLocalIsochPort( localNode, buffers, commandPool, & localIsochPort ) ; cout << i-- << "..." << _success << endl ; } if ( !error ) { cout << i++ << "Creating isoch channel...\n" ; error = CreateIsochChannel( localNode, & isochChannel ) ; cout << i-- << "..." << _success << endl ; } // remote is listener if ( !error ) { cout << i++ << "Adding listener to isoch channel...\n" ; error = (**isochChannel).AddListener( isochChannel, (IOFireWireLibIsochPortRef) remoteIsochPort ) ; cout << i-- << "..." << _success << endl ; } // local is talker if ( !error ) { cout << i++ << "Setting talker on isoch channel...\n" ; error = (**isochChannel).SetTalker( isochChannel, (IOFireWireLibIsochPortRef) localIsochPort ) ; cout << i-- << "..." << _success << endl ; } if ( !error ) { cout << i++ << "Allocating channel...\n" ; error = (**isochChannel).AllocateChannel( isochChannel ) ; cout << i-- << "..." << _success << endl ; } i-- ; // unindent // run for approx. 15 seconds cout << i++ << "\n### RUNNING\n" ; if ( !error ) { if ( !error ) { cout << i++ << "Starting channel...\n" ; error = (**isochChannel).Start( isochChannel ) ; cout << i-- << "..." << _success << endl ; } cout << i << "\nRunning...\n" ; SInt16 runLoopResult ; while ( kCFRunLoopRunHandledSource == ( runLoopResult = CFRunLoopRunInMode( kCFRunLoopDefaultMode, 30, false ) ) ) { } error = (**isochChannel).Stop( isochChannel ) ; cout << i-- << "done!\n" ; // clean up cout << i++ << "\n### CLEAN UP ###\n\n" ; // release all interfaces if ( isochChannel ) { cout << i++ << "releasing isoch channel.\n" ; if ( error != kIOReturnSuccess ) cout << i << _file << "error " << error << " stopping channel.\n" ; error = (**isochChannel).ReleaseChannel( isochChannel ) ; if ( error != kIOReturnSuccess ) cout << i << _file << "error " << error << " from ReleaseChannel().\n" ; (**isochChannel).Release( isochChannel ) ; i-- ; } if ( localIsochPort ) { cout << i << "releasing local port.\n" ; (**localIsochPort).Release( localIsochPort ) ; } if ( remoteIsochPort ) { cout << i << "releasing remote port.\n" ; (**remoteIsochPort).Release( remoteIsochPort ) ; } } if ( localNode ) { cout << i << "releasing local node interface.\n" ; (**localNode).Close( localNode ) ; (**localNode).Release( localNode ) ; } // // release the original CFPlugInInterface // if ( cfPlugInInterface ) { cout << i << "releasing CFPlugInInterface.\n" ; IODestroyPlugInInterface( cfPlugInInterface ) ; } // // deallocate our DMA buffers // if (buffer) { ::vm_deallocate( mach_task_self(), buffer, kBufferSize ) ; } cout << i << "### DONE\n" ; return (error == kIOReturnSuccess) ? EXIT_SUCCESS : EXIT_FAILURE ; }