OVR_OSX_HIDDevice.cpp
Go to the documentation of this file.
00001 /************************************************************************************
00002 Filename    :   OVR_OSX_HIDDevice.cpp
00003 Content     :   OSX HID device implementation.
00004 Created     :   February 26, 2013
00005 Authors     :   Lee Cooper
00006  
00007 Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
00008  
00009 Use of this software is subject to the terms of the Oculus license
00010 agreement provided at the time of installation or download, or which
00011 otherwise accompanies this software in either electronic or hard copy form.
00012 
00013 *************************************************************************************/
00014 
00015 #include "OVR_OSX_HIDDevice.h"
00016 
00017 #include <IOKit/usb/IOUSBLib.h>
00018 
00019 namespace OVR { namespace OSX {
00020 
00021 static const UInt32 MAX_QUEUED_INPUT_REPORTS = 5;
00022     
00023 //-------------------------------------------------------------------------------------
00024 // **** OSX::DeviceManager
00025 
00026 HIDDeviceManager::HIDDeviceManager(DeviceManager* manager)
00027  :  DevManager(manager)
00028 {
00029     HIDManager = NULL;
00030 }
00031 
00032 HIDDeviceManager::~HIDDeviceManager()
00033 {
00034 }
00035 
00036 CFRunLoopRef HIDDeviceManager::getRunLoop()
00037 {
00038     if (DevManager != NULL)
00039     {
00040         return DevManager->pThread->GetRunLoop();
00041     }
00042 
00043     return CFRunLoopGetCurrent();
00044 }
00045 
00046 bool HIDDeviceManager::initializeManager()
00047 {
00048     if (HIDManager != NULL)
00049     {
00050         return true;
00051     }
00052     
00053         HIDManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
00054     
00055     if (!HIDManager)
00056     {
00057         return false;
00058     }
00059     
00060     // Create a Matching Dictionary
00061     CFMutableDictionaryRef matchDict =
00062         CFDictionaryCreateMutable(kCFAllocatorDefault,
00063                                   2,
00064                                   &kCFTypeDictionaryKeyCallBacks,
00065                                   &kCFTypeDictionaryValueCallBacks);
00066     
00067     // Specify a device manufacturer in the Matching Dictionary
00068     UInt32 vendorId = Oculus_VendorId;
00069     CFNumberRef vendorIdRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &vendorId);
00070     CFDictionarySetValue(matchDict,
00071                          CFSTR(kIOHIDVendorIDKey),
00072                          vendorIdRef);
00073     // Register the Matching Dictionary to the HID Manager
00074     IOHIDManagerSetDeviceMatching(HIDManager, matchDict);
00075     CFRelease(vendorIdRef);
00076     CFRelease(matchDict);
00077     
00078     // Register a callback for USB device detection with the HID Manager
00079     IOHIDManagerRegisterDeviceMatchingCallback(HIDManager, &staticDeviceMatchingCallback, this);
00080     
00081     IOHIDManagerScheduleWithRunLoop(HIDManager, getRunLoop(), kCFRunLoopDefaultMode);
00082 
00083     return true;
00084 }
00085     
00086 bool HIDDeviceManager::Initialize()
00087 {
00088     return initializeManager();
00089 }
00090 
00091 void HIDDeviceManager::Shutdown()
00092 {
00093     OVR_ASSERT_LOG(HIDManager, ("Should have called 'Initialize' before 'Shutdown'."));
00094     CFRelease(HIDManager);
00095     
00096     LogText("OVR::OSX::HIDDeviceManager - shutting down.\n");
00097 }
00098     
00099 bool HIDDeviceManager::getIntProperty(IOHIDDeviceRef device, CFStringRef propertyName, SInt32* pResult)
00100 {
00101     
00102     CFTypeRef ref = IOHIDDeviceGetProperty(device, propertyName);
00103 
00104     if (!ref)
00105     {
00106         return false;
00107     }
00108     
00109     if (CFGetTypeID(ref) != CFNumberGetTypeID())
00110     {
00111         return false;
00112     }
00113     
00114     CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, pResult);
00115 
00116     return true;
00117 }
00118     
00119 bool HIDDeviceManager::initVendorProductVersion(IOHIDDeviceRef device, HIDDeviceDesc* pDevDesc)
00120 {
00121     
00122     if (!getVendorId(device, &(pDevDesc->VendorId)))
00123     {
00124         return false;
00125     }
00126     
00127     if (!getProductId(device, &(pDevDesc->ProductId)))
00128     {
00129         return false;
00130     }
00131     
00132     return true;
00133 }
00134 
00135 bool HIDDeviceManager::initUsage(IOHIDDeviceRef device, HIDDeviceDesc* pDevDesc)
00136 {
00137     
00138     SInt32 result;
00139     
00140     if (!getIntProperty(device, CFSTR(kIOHIDPrimaryUsagePageKey), &result))
00141     {
00142         return false;
00143     }
00144     
00145     pDevDesc->UsagePage = result;
00146 
00147     
00148     if (!getIntProperty(device, CFSTR(kIOHIDPrimaryUsageKey), &result))
00149     {
00150         return false;
00151     }
00152     
00153     pDevDesc->Usage = result;
00154     
00155     return true;
00156 }
00157 
00158 bool HIDDeviceManager::initSerialNumber(IOHIDDeviceRef device, HIDDeviceDesc* pDevDesc)
00159 {
00160     return getSerialNumberString(device, &(pDevDesc->SerialNumber));
00161 }
00162     
00163 bool HIDDeviceManager::initStrings(IOHIDDeviceRef device, HIDDeviceDesc* pDevDesc)
00164 {
00165 
00166     // Regardless of whether they fail we'll try and get the remaining.
00167     getStringProperty(device, CFSTR(kIOHIDManufacturerKey), &(pDevDesc->Manufacturer));
00168     getStringProperty(device, CFSTR(kIOHIDProductKey), &(pDevDesc->Product));
00169     
00170     return true;
00171 }
00172 
00173 bool HIDDeviceManager::getStringProperty(IOHIDDeviceRef device,
00174                                          CFStringRef propertyName,
00175                                          String* pResult)
00176 {
00177     
00178     CFStringRef str = (CFStringRef) IOHIDDeviceGetProperty(device, propertyName);
00179     
00180     if (!str)
00181     {
00182         return false;
00183     }
00184 
00185     CFIndex length = CFStringGetLength(str);
00186     CFRange range = CFRangeMake(0, length);
00187     
00188     // Test the conversion first to get required buffer size.
00189     CFIndex bufferLength;
00190     CFIndex numberOfChars = CFStringGetBytes(str,
00191                                              range,
00192                                              kCFStringEncodingUTF8,
00193                                              (char) '?',
00194                                              FALSE,
00195                                              NULL,
00196                                              0,
00197                                              &bufferLength);
00198     
00199     if (numberOfChars == 0)
00200     {
00201         return false;
00202     }
00203     
00204     // Now allocate buffer.
00205     char* buffer = new char[bufferLength+1];
00206     
00207     numberOfChars = CFStringGetBytes(str,
00208                                      range,
00209                                      kCFStringEncodingUTF8,
00210                                      (char) '?',
00211                                      FALSE,
00212                                      (UInt8*) buffer,
00213                                      bufferLength,
00214                                      NULL);
00215     OVR_ASSERT_LOG(numberOfChars != 0, ("CFStringGetBytes failed."));
00216 
00217     buffer[bufferLength] = '\0';
00218     *pResult = String(buffer);
00219     
00220     return true;
00221 }
00222     
00223 bool HIDDeviceManager::getVendorId(IOHIDDeviceRef device, UInt16* pResult)
00224 {
00225     SInt32 result;
00226     
00227     if (!getIntProperty(device, CFSTR(kIOHIDVendorIDKey), &result))
00228     {
00229         return false;
00230     }
00231     
00232     *pResult = result;
00233 
00234     return true;
00235 }
00236     
00237 bool HIDDeviceManager::getProductId(IOHIDDeviceRef device, UInt16* pResult)
00238 {
00239     SInt32 result;
00240     
00241     if (!getIntProperty(device, CFSTR(kIOHIDProductIDKey), &result))
00242     {
00243         return false;
00244     }
00245     
00246     *pResult = result;
00247     
00248     return true;
00249 }
00250  
00251 bool HIDDeviceManager::getLocationId(IOHIDDeviceRef device, SInt32* pResult)
00252 {
00253     SInt32 result;
00254     
00255     if (!getIntProperty(device, CFSTR(kIOHIDLocationIDKey), &result))
00256     {
00257         return false;
00258     }
00259         
00260     *pResult = result;
00261         
00262     return true;
00263 }
00264     
00265 bool HIDDeviceManager::getSerialNumberString(IOHIDDeviceRef device, String* pResult)
00266 {
00267  
00268     if (!getStringProperty(device, CFSTR(kIOHIDSerialNumberKey), pResult))
00269     {
00270         return false;
00271     }
00272 
00273     return true;
00274 }
00275     
00276 bool HIDDeviceManager::getPath(IOHIDDeviceRef device, String* pPath)
00277 {
00278 
00279     String transport;
00280     if (!getStringProperty(device, CFSTR(kIOHIDTransportKey), &transport))
00281     {
00282         return false;
00283     }
00284     
00285     UInt16 vendorId;
00286     if (!getVendorId(device, &vendorId))
00287     {
00288         return false;
00289     }
00290 
00291     UInt16 productId;
00292     if (!getProductId(device, &productId))
00293     {
00294         return false;
00295     }
00296     
00297     String serialNumber;
00298         if (!getSerialNumberString(device, &serialNumber))
00299     {
00300         return false;
00301     }
00302     
00303 
00304     StringBuffer buffer;
00305     buffer.AppendFormat("%s:vid=%04hx:pid=%04hx:ser=%s",
00306                             transport.ToCStr(),
00307                             vendorId,
00308                             productId,
00309                             serialNumber.ToCStr());
00310     
00311     *pPath = String(buffer);
00312     
00313     return true;
00314 }
00315 
00316 bool HIDDeviceManager::Enumerate(HIDEnumerateVisitor* enumVisitor)
00317 {
00318     if (!initializeManager())
00319     {
00320         return false;
00321     }
00322     
00323 
00324         CFSetRef deviceSet = IOHIDManagerCopyDevices(HIDManager);
00325     if (!deviceSet)
00326         return false;
00327     
00328         CFIndex deviceCount = CFSetGetCount(deviceSet);
00329     
00330     // Allocate a block of memory and read the set into it.
00331     IOHIDDeviceRef* devices = (IOHIDDeviceRef*) OVR_ALLOC(sizeof(IOHIDDeviceRef) * deviceCount);
00332     CFSetGetValues(deviceSet, (const void **) devices);
00333     
00334 
00335     // Iterate over devices.
00336     for (CFIndex deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++)
00337     {
00338         IOHIDDeviceRef hidDev = devices[deviceIndex];
00339         
00340         if (!hidDev)
00341         {
00342             continue;
00343         }
00344         
00345         HIDDeviceDesc devDesc;
00346                 
00347         if (getPath(hidDev, &(devDesc.Path)) &&
00348             initVendorProductVersion(hidDev, &devDesc) &&
00349             enumVisitor->MatchVendorProduct(devDesc.VendorId, devDesc.ProductId) &&
00350             initUsage(hidDev, &devDesc))
00351         {
00352             initStrings(hidDev, &devDesc);
00353             initSerialNumber(hidDev, &devDesc);
00354 
00355             // Look for the device to check if it is already opened.
00356             Ptr<DeviceCreateDesc> existingDevice = DevManager->FindHIDDevice(devDesc);
00357             // if device exists and it is opened then most likely the CreateHIDFile
00358             // will fail; therefore, we just set Enumerated to 'true' and continue.
00359             if (existingDevice && existingDevice->pDevice)
00360             {
00361                 existingDevice->Enumerated = true;
00362                 continue;
00363             }
00364             
00365             // Construct minimal device that the visitor callback can get feature reports from.
00366             OSX::HIDDevice device(this, hidDev);
00367             
00368             enumVisitor->Visit(device, devDesc);
00369         }
00370     }
00371     
00372     OVR_FREE(devices);
00373     CFRelease(deviceSet);
00374     
00375     return true;
00376 }
00377 
00378 OVR::HIDDevice* HIDDeviceManager::Open(const String& path)
00379 {
00380 
00381     Ptr<OSX::HIDDevice> device = *new OSX::HIDDevice(this);
00382 
00383     if (!device->HIDInitialize(path))
00384     {
00385         return NULL;
00386     }
00387 
00388     device->AddRef();
00389     
00390     return device;
00391 }
00392     
00393 bool HIDDeviceManager::getFullDesc(IOHIDDeviceRef device, HIDDeviceDesc* desc)
00394 {
00395         
00396     if (!initVendorProductVersion(device, desc))
00397     {
00398         return false;
00399     }
00400         
00401     if (!initUsage(device, desc))
00402     {
00403         return false;
00404     }
00405     
00406     if (!initSerialNumber(device, desc))
00407     {
00408         return false;
00409     }
00410     
00411     initStrings(device, desc);
00412         
00413     return true;
00414 }
00415 
00416 // New USB device specified in the matching dictionary has been added (callback function)
00417 void HIDDeviceManager::staticDeviceMatchingCallback(void *inContext,
00418                                                     IOReturn inResult,
00419                                                     void *inSender,
00420                                                     IOHIDDeviceRef inIOHIDDeviceRef)
00421 {
00422     HIDDeviceManager* hidMgr = static_cast<HIDDeviceManager*>(inContext);
00423     HIDDeviceDesc hidDevDesc;
00424     hidMgr->getPath(inIOHIDDeviceRef, &hidDevDesc.Path);
00425     hidMgr->getFullDesc(inIOHIDDeviceRef, &hidDevDesc);
00426     
00427     hidMgr->DevManager->DetectHIDDevice(hidDevDesc);
00428 }
00429 
00430 //-------------------------------------------------------------------------------------
00431 // **** OSX::HIDDevice
00432 
00433 HIDDevice::HIDDevice(HIDDeviceManager* manager)
00434  :  HIDManager(manager), InMinimalMode(false)
00435 {
00436     Device = NULL;
00437     RepluggedNotificationPort = 0;
00438 }
00439     
00440 // This is a minimal constructor used during enumeration for us to pass
00441 // a HIDDevice to the visit function (so that it can query feature reports).
00442 HIDDevice::HIDDevice(HIDDeviceManager* manager, IOHIDDeviceRef device)
00443 :   HIDManager(manager), Device(device), InMinimalMode(true)
00444 {
00445     RepluggedNotificationPort = 0;
00446 }
00447 
00448 HIDDevice::~HIDDevice()
00449 {
00450     if (!InMinimalMode)
00451     {
00452         HIDShutdown();
00453     }
00454 }
00455 
00456 bool HIDDevice::HIDInitialize(const String& path)
00457 {
00458 
00459     DevDesc.Path = path;
00460 
00461     if (!openDevice())
00462     {
00463         LogText("OVR::OSX::HIDDevice - Failed to open HIDDevice: %s", path.ToCStr());
00464         return false;
00465     }
00466 
00467     // Setup notification for when a device is unplugged and plugged back in.
00468     if (!setupDevicePluggedInNotification())
00469     {
00470         LogText("OVR::OSX::HIDDevice - Failed to setup notification for when device plugged back in.");
00471         closeDevice(false);
00472         return false;
00473     }
00474     
00475     HIDManager->DevManager->pThread->AddTicksNotifier(this);
00476 
00477     
00478     LogText("OVR::OSX::HIDDevice - Opened '%s'\n"
00479             "                    Manufacturer:'%s'  Product:'%s'  Serial#:'%s'\n",
00480             DevDesc.Path.ToCStr(),
00481             DevDesc.Manufacturer.ToCStr(), DevDesc.Product.ToCStr(),
00482             DevDesc.SerialNumber.ToCStr());
00483     
00484     return true;
00485 }
00486 
00487 bool HIDDevice::initInfo()
00488 {
00489     // Device must have been successfully opened.
00490     OVR_ASSERT(Device);
00491     
00492     
00493     // Get report lengths.
00494     SInt32 bufferLength;
00495     bool getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxInputReportSizeKey), &bufferLength);
00496     OVR_ASSERT(getResult);
00497     InputReportBufferLength = (UInt16) bufferLength;
00498 
00499     getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxOutputReportSizeKey), &bufferLength);
00500     OVR_ASSERT(getResult);
00501     OutputReportBufferLength = (UInt16) bufferLength;
00502 
00503     getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxFeatureReportSizeKey), &bufferLength);
00504     OVR_ASSERT(getResult);
00505     FeatureReportBufferLength = (UInt16) bufferLength;
00506     
00507     
00508     if (ReadBufferSize < InputReportBufferLength)
00509     {
00510         OVR_ASSERT_LOG(false, ("Input report buffer length is bigger than read buffer."));
00511         return false;
00512     }
00513     
00514     // Get device desc.
00515     if (!HIDManager->getFullDesc(Device, &DevDesc))
00516     {
00517         OVR_ASSERT_LOG(false, ("Failed to get device desc while initializing device."));
00518         return false;
00519     }
00520     
00521     return true;
00522 }
00523 
00524 void HIDDevice::staticDeviceAddedCallback(void* pContext, io_iterator_t iterator)
00525 {
00526     HIDDevice* pDevice = (HIDDevice*) pContext;
00527     pDevice->deviceAddedCallback(iterator);
00528 }
00529 
00530 void HIDDevice::deviceAddedCallback(io_iterator_t iterator)
00531 {
00532 
00533     if (Device == NULL)
00534     {
00535         if (openDevice())
00536         {
00537             LogText("OVR::OSX::HIDDevice - Reopened device : %s", DevDesc.Path.ToCStr());
00538 
00539             Ptr<DeviceCreateDesc> existingHIDDev = HIDManager->DevManager->FindHIDDevice(DevDesc);
00540             if (existingHIDDev && existingHIDDev->pDevice)
00541             {
00542                 HIDManager->DevManager->CallOnDeviceAdded(existingHIDDev);
00543             }
00544         }
00545     }
00546 
00547     // Reset callback.
00548     while (IOIteratorNext(iterator))
00549         ;
00550 }
00551     
00552 bool HIDDevice::openDevice()
00553 {
00554     
00555     // Have to iterate through devices again to generate paths.
00556         CFSetRef deviceSet = IOHIDManagerCopyDevices(HIDManager->HIDManager);
00557         CFIndex deviceCount = CFSetGetCount(deviceSet);
00558     
00559     // Allocate a block of memory and read the set into it.
00560     IOHIDDeviceRef* devices = (IOHIDDeviceRef*) OVR_ALLOC(sizeof(IOHIDDeviceRef) * deviceCount);
00561     CFSetGetValues(deviceSet, (const void **) devices);
00562     
00563     
00564     // Iterate over devices.
00565     IOHIDDeviceRef device = NULL;
00566 
00567     for (CFIndex deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++)
00568     {
00569         IOHIDDeviceRef tmpDevice = devices[deviceIndex];
00570         
00571         if (!tmpDevice)
00572         {
00573             continue;
00574         }
00575         
00576         String path;
00577         if (!HIDManager->getPath(tmpDevice, &path))
00578         {
00579             continue;
00580         }
00581         
00582         if (path == DevDesc.Path)
00583         {
00584             device = tmpDevice;
00585             break;
00586         }
00587     }
00588     
00589     
00590     OVR_FREE(devices);
00591     
00592     if (!device)
00593     {
00594         CFRelease(deviceSet);
00595         return false;
00596     }
00597     
00598     // Attempt to open device.
00599     if (IOHIDDeviceOpen(device, kIOHIDOptionsTypeSeizeDevice)
00600         != kIOReturnSuccess)
00601     {
00602         CFRelease(deviceSet);
00603         return false;
00604     }
00605 
00606     // Retain the device before we release the set.
00607     CFRetain(device);
00608     CFRelease(deviceSet);
00609     
00610     
00611     Device = device;
00612 
00613     
00614     if (!initInfo())
00615     {
00616         IOHIDDeviceClose(Device, kIOHIDOptionsTypeSeizeDevice);
00617         CFRelease(Device);
00618         Device = NULL;
00619         return false;
00620     }
00621     
00622     
00623     // Setup the Run Loop and callbacks.
00624     IOHIDDeviceScheduleWithRunLoop(Device,
00625                                    HIDManager->getRunLoop(),
00626                                    kCFRunLoopDefaultMode);
00627     
00628     IOHIDDeviceRegisterInputReportCallback(Device,
00629                                            ReadBuffer,
00630                                            ReadBufferSize,
00631                                            staticHIDReportCallback,
00632                                            this);
00633 
00634     IOHIDDeviceRegisterRemovalCallback(Device,
00635                                        staticDeviceRemovedCallback,
00636                                        this);
00637     
00638     return true;
00639 }
00640     
00641 void HIDDevice::HIDShutdown()
00642 {
00643 
00644     HIDManager->DevManager->pThread->RemoveTicksNotifier(this);
00645     
00646     if (Device != NULL) // Device may already have been closed if unplugged.
00647     {
00648         closeDevice(false);
00649     }
00650 
00651     IOObjectRelease(RepluggedNotification);
00652     if (RepluggedNotificationPort)
00653         IONotificationPortDestroy(RepluggedNotificationPort);
00654     
00655     LogText("OVR::OSX::HIDDevice - HIDShutdown '%s'\n", DevDesc.Path.ToCStr());
00656 }
00657 
00658 bool HIDDevice::setupDevicePluggedInNotification()
00659 {
00660     
00661     // Setup notification when devices are plugged in.
00662     RepluggedNotificationPort = IONotificationPortCreate(kIOMasterPortDefault);
00663     
00664     CFRunLoopSourceRef notificationRunLoopSource =
00665         IONotificationPortGetRunLoopSource(RepluggedNotificationPort);
00666     
00667     CFRunLoopAddSource(HIDManager->getRunLoop(),
00668                        notificationRunLoopSource,
00669                        kCFRunLoopDefaultMode);
00670     
00671     CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
00672     
00673     // Have to specify vendorId and productId. Doesn't seem to accept additional
00674     // things like serial number.
00675     SInt32 vendorId = DevDesc.VendorId;
00676     CFNumberRef numberRef = CFNumberCreate(kCFAllocatorDefault,
00677                                            kCFNumberSInt32Type,
00678                                            &vendorId);
00679     CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), numberRef);
00680     CFRelease(numberRef);
00681     
00682     SInt32 deviceProductId = DevDesc.ProductId;
00683     numberRef = CFNumberCreate(kCFAllocatorDefault,
00684                                kCFNumberSInt32Type,
00685                                &deviceProductId);
00686     CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), numberRef);
00687     CFRelease(numberRef);
00688     
00689     kern_return_t result =
00690             IOServiceAddMatchingNotification(RepluggedNotificationPort,
00691                                              kIOMatchedNotification,
00692                                              matchingDict,
00693                                              staticDeviceAddedCallback,
00694                                              this,
00695                                              &RepluggedNotification);
00696     
00697     if (result != KERN_SUCCESS)
00698     {
00699         CFRelease(RepluggedNotificationPort);
00700         RepluggedNotificationPort = 0;
00701         return false;
00702     }
00703     
00704     // Iterate through to arm.
00705     while (IOIteratorNext(RepluggedNotification))
00706     {
00707         }
00708     
00709     return true;
00710 }
00711 
00712 void HIDDevice::closeDevice(bool wasUnplugged)
00713 {
00714     OVR_ASSERT(Device != NULL);
00715     
00716     if (!wasUnplugged)
00717     {
00718         // Clear the registered callbacks.
00719         IOHIDDeviceRegisterInputReportCallback(Device,
00720                                                ReadBuffer,
00721                                                InputReportBufferLength,
00722                                                NULL,
00723                                                this);
00724         
00725         IOHIDDeviceRegisterRemovalCallback(Device, NULL, this);
00726         
00727         IOHIDDeviceUnscheduleFromRunLoop(Device,
00728                                          HIDManager->getRunLoop(),
00729                                          kCFRunLoopDefaultMode);
00730         IOHIDDeviceClose(Device, kIOHIDOptionsTypeNone);
00731     }
00732     
00733         CFRelease(Device);
00734     Device = NULL;
00735         
00736     LogText("OVR::OSX::HIDDevice - HID Device Closed '%s'\n", DevDesc.Path.ToCStr());
00737 }
00738 
00739 void HIDDevice::staticHIDReportCallback(void* pContext,
00740                                         IOReturn result,
00741                                         void* pSender,
00742                                         IOHIDReportType reportType,
00743                                         uint32_t reportId,
00744                                         uint8_t* pReport,
00745                                         CFIndex reportLength)
00746 {
00747     HIDDevice* pDevice = (HIDDevice*) pContext;
00748     return pDevice->hidReportCallback(pReport, (UInt32)reportLength);
00749 }
00750 
00751 void HIDDevice::hidReportCallback(UByte* pData, UInt32 length)
00752 {
00753     
00754     // We got data.
00755     if (Handler)
00756     {
00757         Handler->OnInputReport(pData, length);
00758     }
00759 }
00760     
00761 void HIDDevice::staticDeviceRemovedCallback(void* pContext, IOReturn result, void* pSender)
00762 {
00763     HIDDevice* pDevice = (HIDDevice*) pContext;
00764     pDevice->deviceRemovedCallback();
00765 }
00766     
00767 void HIDDevice::deviceRemovedCallback()
00768 {
00769     Ptr<HIDDevice> _this(this); // prevent from release
00770     
00771     Ptr<DeviceCreateDesc> existingHIDDev = HIDManager->DevManager->FindHIDDevice(DevDesc);
00772     if (existingHIDDev && existingHIDDev->pDevice)
00773     {
00774         HIDManager->DevManager->CallOnDeviceRemoved(existingHIDDev);
00775     }
00776     closeDevice(true);
00777 }
00778 
00779 CFStringRef HIDDevice::generateRunLoopModeString(IOHIDDeviceRef device)
00780 {
00781     const UInt32 safeBuffSize = 256;
00782     char nameBuff[safeBuffSize];
00783     OVR_sprintf(nameBuff, safeBuffSize, "%016lX", device);
00784   
00785     return CFStringCreateWithCString(NULL, nameBuff, kCFStringEncodingASCII);
00786 }
00787     
00788 bool HIDDevice::SetFeatureReport(UByte* data, UInt32 length)
00789 {
00790     
00791     if (!Device)
00792         return false;
00793     
00794     UByte reportID = data[0];
00795 
00796     if (reportID == 0)
00797     {
00798         // Not using reports so remove from data packet.
00799         data++;
00800         length--;
00801     }
00802     
00803         IOReturn result = IOHIDDeviceSetReport( Device,
00804                                             kIOHIDReportTypeFeature,
00805                                             reportID,
00806                                             data,
00807                                             length);
00808     
00809     return (result == kIOReturnSuccess);
00810 }
00811 
00812 bool HIDDevice::GetFeatureReport(UByte* data, UInt32 length)
00813 {
00814     if (!Device)
00815         return false;
00816     
00817     CFIndex bufferLength = length;
00818     
00819     // Report id is in first byte of the buffer.
00820         IOReturn result = IOHIDDeviceGetReport(Device, kIOHIDReportTypeFeature, data[0], data, &bufferLength);
00821         
00822     return (result == kIOReturnSuccess);
00823 }
00824    
00825 UInt64 HIDDevice::OnTicks(UInt64 ticksMks)
00826 {
00827     
00828     if (Handler)
00829     {
00830         return Handler->OnTicks(ticksMks);
00831     }
00832     
00833     return DeviceManagerThread::Notifier::OnTicks(ticksMks);
00834 }
00835 
00836 HIDDeviceManager* HIDDeviceManager::CreateInternal(OSX::DeviceManager* devManager)
00837 {
00838         
00839     if (!System::IsInitialized())
00840     {
00841         // Use custom message, since Log is not yet installed.
00842         OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
00843                             LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); );
00844         return 0;
00845     }
00846 
00847     Ptr<OSX::HIDDeviceManager> manager = *new OSX::HIDDeviceManager(devManager);
00848 
00849     if (manager)
00850     {
00851         if (manager->Initialize())
00852         {
00853             manager->AddRef();
00854         }
00855         else
00856         {
00857             manager.Clear();
00858         }
00859     }
00860 
00861     return manager.GetPtr();
00862 }
00863     
00864 } // namespace OSX
00865 
00866 //-------------------------------------------------------------------------------------
00867 // ***** Creation
00868 
00869 // Creates a new HIDDeviceManager and initializes OVR.
00870 HIDDeviceManager* HIDDeviceManager::Create()
00871 {
00872     OVR_ASSERT_LOG(false, ("Standalone mode not implemented yet."));
00873     
00874     if (!System::IsInitialized())
00875     {
00876         // Use custom message, since Log is not yet installed.
00877         OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
00878             LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); );
00879         return 0;
00880     }
00881 
00882     Ptr<OSX::HIDDeviceManager> manager = *new OSX::HIDDeviceManager(NULL);
00883     
00884     if (manager)
00885     {
00886         if (manager->Initialize())
00887         {
00888             manager->AddRef();
00889         }
00890         else
00891         {
00892             manager.Clear();
00893         }
00894     }
00895 
00896     return manager.GetPtr();
00897 }
00898 
00899 } // namespace OVR


oculus_sdk
Author(s):
autogenerated on Mon Oct 6 2014 03:01:19