OSX_Gamepad.cpp
Go to the documentation of this file.
00001 /************************************************************************************
00002 
00003 Filename    :   OSX_Gamepad.cpp
00004 Content     :   OSX implementation of Gamepad functionality.
00005 Created     :   May 6, 2013
00006 Authors     :   Lee Cooper
00007 
00008 Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
00009 
00010 Licensed under the Apache License, Version 2.0 (the "License");
00011 you may not use this file except in compliance with the License.
00012 You may obtain a copy of the License at
00013 
00014 http://www.apache.org/licenses/LICENSE-2.0
00015 
00016 Unless required by applicable law or agreed to in writing, software
00017 distributed under the License is distributed on an "AS IS" BASIS,
00018 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00019 See the License for the specific language governing permissions and
00020 limitations under the License.
00021 
00022 ************************************************************************************/
00023 
00024 #include "OSX_Gamepad.h"
00025 
00026 
00027 static const UInt32 Logitech_F710_VendorID = 0x046D;
00028 static const UInt32 Logitech_F710_ProductID = 0xC219;
00029 
00030 static const UInt32 Sony_DualShock3_VendorID = 0x054C;
00031 static const UInt32 Sony_DualShock3_ProductID = 0x0268;
00032 
00033 
00034 namespace OVR { namespace Platform { namespace OSX {
00035 
00036     
00037 GamepadManager::GamepadManager()
00038  :  bStateChanged(false)
00039 {
00040     
00041     HidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
00042     IOHIDManagerOpen(HidManager, kIOHIDOptionsTypeNone);
00043     IOHIDManagerScheduleWithRunLoop(HidManager,
00044                                     CFRunLoopGetCurrent(),
00045                                     kCFRunLoopDefaultMode);
00046     
00047     
00048     // Setup device matching.
00049     CFStringRef keys[] = {  CFSTR(kIOHIDDeviceUsagePageKey),
00050                             CFSTR(kIOHIDDeviceUsageKey)};
00051     
00052     int value;
00053     CFNumberRef values[2];
00054     CFDictionaryRef dictionaries[2];
00055 
00056     // Match joysticks.
00057     value = kHIDPage_GenericDesktop;
00058     values[0] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value);
00059 
00060     value = kHIDUsage_GD_Joystick;
00061     values[1] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value);
00062 
00063     dictionaries[0] = CFDictionaryCreate(kCFAllocatorDefault,
00064                                          (const void **) keys,
00065                                          (const void **) values,
00066                                          2,
00067                                          &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
00068     CFRelease(values[0]);
00069     CFRelease(values[1]);
00070 
00071     // Match gamepads.
00072     value = kHIDPage_GenericDesktop;
00073     values[0] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value);
00074 
00075     value = kHIDUsage_GD_GamePad;
00076     values[1] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value);
00077 
00078     dictionaries[1] = CFDictionaryCreate(kCFAllocatorDefault,
00079                                          (const void **) keys,
00080                                          (const void **) values,
00081                                          2,
00082                                          &kCFTypeDictionaryKeyCallBacks,
00083                                          &kCFTypeDictionaryValueCallBacks);
00084     CFRelease(values[0]);
00085     CFRelease(values[1]);
00086 
00087     CFArrayRef array = CFArrayCreate(   kCFAllocatorDefault,
00088                                         (const void **) dictionaries,
00089                                         2,
00090                                         &kCFTypeArrayCallBacks);
00091     CFRelease(dictionaries[0]);
00092     CFRelease(dictionaries[1]);
00093 
00094     IOHIDManagerSetDeviceMatchingMultiple(HidManager, array);
00095     
00096     CFRelease(array);
00097     
00098     
00099     IOHIDManagerRegisterDeviceMatchingCallback(HidManager, staticOnDeviceMatched, this);
00100     IOHIDManagerRegisterDeviceRemovalCallback(HidManager, staticOnDeviceRemoved, this);
00101 
00102 }
00103 
00104 GamepadManager::~GamepadManager()
00105 {
00106     CFRelease(HidManager);
00107 }
00108 
00109 UInt32 GamepadManager::GetGamepadCount()
00110 {
00111     return 1;
00112 }
00113     
00114 bool GamepadManager::GetGamepadState(UInt32 index, GamepadState* pState)
00115 {
00116     // For now we just support one gamepad.
00117     OVR_UNUSED(index);
00118     
00119     if (!bStateChanged)
00120     {
00121         return false;
00122     }
00123     
00124     bStateChanged = false;
00125 //  State.Debug();
00126     
00127     *pState = State;
00128     return true;
00129 }
00130 
00131 int GamepadManager::getIntDeviceProperty(IOHIDDeviceRef device, CFStringRef key)
00132 {
00133     CFTypeRef type = IOHIDDeviceGetProperty(device, key);
00134     OVR_ASSERT(type != NULL && CFGetTypeID(type) == CFNumberGetTypeID());
00135     
00136     int value;
00137     CFNumberGetValue((CFNumberRef) type, kCFNumberSInt32Type, &value);
00138 
00139     return value;
00140 }
00141 
00142 void GamepadManager::staticOnDeviceMatched(void* context, IOReturn result, void* sender, IOHIDDeviceRef device)
00143 {
00144     GamepadManager* pManager = (GamepadManager*) context;
00145     pManager->onDeviceMatched(device);
00146 }
00147 
00148 void GamepadManager::onDeviceMatched(IOHIDDeviceRef device)
00149 {
00150     IOHIDDeviceRegisterInputValueCallback(device, staticOnDeviceValueChanged, this);
00151 }
00152 
00153 void GamepadManager::staticOnDeviceRemoved(void* context, IOReturn result, void* sender, IOHIDDeviceRef device)
00154 {
00155     GamepadManager* pManager = (GamepadManager*) context;
00156     pManager->onDeviceRemoved(device);
00157 }
00158 
00159 void GamepadManager::onDeviceRemoved(IOHIDDeviceRef device)
00160 {
00161     IOHIDDeviceRegisterInputValueCallback(device, NULL, NULL);
00162 }
00163 
00164 void GamepadManager::staticOnDeviceValueChanged(void* context, IOReturn result, void* sender, IOHIDValueRef value)
00165 {
00166     GamepadManager* pManager = (GamepadManager*) context;
00167     pManager->onDeviceValueChanged(value);
00168 }
00169     
00170 float GamepadManager::mapAnalogAxis(IOHIDValueRef value, IOHIDElementRef element)
00171 {
00172     
00173     CFIndex val = IOHIDValueGetIntegerValue(value);
00174     CFIndex min = IOHIDElementGetLogicalMin(element);
00175     CFIndex max = IOHIDElementGetLogicalMax(element);
00176     
00177     float v = (float) (val - min) / (float) (max - min);
00178     v = v * 2.0f - 1.0f;
00179     
00180     // Dead zone.
00181     if (v < 0.1f && v > -0.1f)
00182     {
00183         v = 0.0f;
00184     }
00185     
00186     return v;
00187 }
00188     
00189 bool GamepadManager::setStateIfDifferent(float& state, float newState)
00190 {
00191     if (state == newState)
00192         return false;
00193     
00194     state = newState;
00195     
00196     return true;    
00197 }
00198     
00199 void GamepadManager::onDeviceValueChanged(IOHIDValueRef value)
00200 {
00201     
00202     IOHIDElementRef element = IOHIDValueGetElement(value);
00203     IOHIDDeviceRef device = IOHIDElementGetDevice(element);
00204 
00205     int vendorID = getIntDeviceProperty(device, CFSTR(kIOHIDVendorIDKey));
00206     int productID = getIntDeviceProperty(device, CFSTR(kIOHIDProductIDKey));
00207     OVR_UNUSED(productID);
00208     
00209     uint32_t usagePage = IOHIDElementGetUsagePage(element);
00210     uint32_t usage = IOHIDElementGetUsage(element);
00211 
00212     // The following controller mapping is based on the Logitech F710, however we use it for
00213     // all Logitech devices on the assumption that they're likely to share the same mapping.
00214     if (vendorID == Logitech_F710_VendorID)
00215     {
00216         // Logitech F710 mapping.
00217         if (usagePage == kHIDPage_Button)
00218         {
00219             bool buttonState = IOHIDValueGetIntegerValue(value);
00220 
00221             switch(usage)
00222             {
00223                 case kHIDUsage_Button_1:
00224                     manipulateBitField(State.Buttons, Gamepad_X, buttonState);
00225                     break;
00226                 case kHIDUsage_Button_2:
00227                     manipulateBitField(State.Buttons, Gamepad_A, buttonState);
00228                     break;
00229                 case kHIDUsage_Button_3:
00230                     manipulateBitField(State.Buttons, Gamepad_B, buttonState);
00231                     break;
00232                 case kHIDUsage_Button_4:
00233                     manipulateBitField(State.Buttons, Gamepad_Y, buttonState);
00234                     break;
00235                 case 0x05:
00236                     manipulateBitField(State.Buttons, Gamepad_L1, buttonState);
00237                     break;
00238                 case 0x06:
00239                     manipulateBitField(State.Buttons, Gamepad_R1, buttonState);
00240                     break;
00241                 case 0x07:
00242                     State.LT = buttonState ? 1.0f:0.0f;
00243                     break;
00244                 case 0x08:
00245                     State.RT = buttonState ? 1.0f:0.0f;
00246                     break;
00247                 case 0x09:
00248                     manipulateBitField(State.Buttons, Gamepad_Back, buttonState);
00249                     break;
00250                 case 0x0A:
00251                     manipulateBitField(State.Buttons, Gamepad_Start, buttonState);
00252                     break;
00253                 case 0x0B:
00254                     manipulateBitField(State.Buttons, Gamepad_LStick, buttonState);
00255                     break;
00256                 case 0x0C:
00257                     manipulateBitField(State.Buttons, Gamepad_RStick, buttonState);
00258                     break;
00259                 default:
00260                     return;
00261             }
00262         }
00263         else if (usagePage == kHIDPage_GenericDesktop)
00264         {
00265             float v;
00266             switch(usage)
00267             {
00268                 case kHIDUsage_GD_X:
00269                     v = mapAnalogAxis(value, element);
00270                     if (!setStateIfDifferent(State.LX, v))
00271                         return;
00272                     break;
00273                 case kHIDUsage_GD_Y:
00274                     v = mapAnalogAxis(value, element);
00275                     if (!setStateIfDifferent(State.LY, -v))
00276                         return;
00277                     break;
00278                 case kHIDUsage_GD_Z:
00279                     v = mapAnalogAxis(value, element);
00280                     if (!setStateIfDifferent(State.RX, v))
00281                         return;
00282                     break;
00283                 case kHIDUsage_GD_Rz:
00284                     v = mapAnalogAxis(value, element);
00285                     if (!setStateIfDifferent(State.RY, -v))
00286                         return;
00287                     break;
00288                 case kHIDUsage_GD_Hatswitch:
00289                     {
00290                         CFIndex integerValue = IOHIDValueGetIntegerValue(value);
00291                  
00292                         manipulateBitField(State.Buttons,
00293                                            Gamepad_Up,
00294                                            integerValue == 7 || integerValue == 0 || integerValue == 1);
00295                         manipulateBitField(State.Buttons,
00296                                            Gamepad_Down,
00297                                            integerValue == 3 || integerValue == 4 || integerValue == 5);
00298                         manipulateBitField(State.Buttons,
00299                                            Gamepad_Left,
00300                                            integerValue == 5 || integerValue == 6 || integerValue == 7);
00301                         manipulateBitField(State.Buttons,
00302                                            Gamepad_Right,
00303                                            integerValue == 1 || integerValue == 2 || integerValue == 3);
00304                     }
00305                     break;
00306                 default:
00307                     return;
00308             }
00309         }
00310     }
00311     // The following controller mapping is based on the Sony DualShock3, however we use it for
00312     // all Sony devices on the assumption that they're likely to share the same mapping.
00313     else if (vendorID == Sony_DualShock3_VendorID)
00314     {
00315         // PS3 Controller.
00316         if (usagePage == kHIDPage_Button)
00317         {
00318             bool buttonState = IOHIDValueGetIntegerValue(value);
00319             
00320             switch(usage)
00321             {
00322                 case kHIDUsage_Button_1:
00323                     manipulateBitField(State.Buttons, Gamepad_Back, buttonState);
00324                     break;
00325                 case kHIDUsage_Button_2:
00326                     manipulateBitField(State.Buttons, Gamepad_LStick, buttonState);
00327                     break;
00328                 case kHIDUsage_Button_3:
00329                     manipulateBitField(State.Buttons, Gamepad_RStick, buttonState);
00330                     break;
00331                 case kHIDUsage_Button_4:
00332                     manipulateBitField(State.Buttons, Gamepad_Start, buttonState);
00333                     break;
00334                 case 0x05:
00335                     manipulateBitField(State.Buttons, Gamepad_Up, buttonState);
00336                     break;
00337                 case 0x06:
00338                     manipulateBitField(State.Buttons, Gamepad_Right, buttonState);
00339                     break;
00340                 case 0x07:
00341                     manipulateBitField(State.Buttons, Gamepad_Down, buttonState);
00342                     break;
00343                 case 0x08:
00344                     manipulateBitField(State.Buttons, Gamepad_Left, buttonState);
00345                     break;
00346                 case 0x09:
00347                     State.LT = buttonState ? 1.0f:0.0f;
00348                     break;
00349                 case 0x0A:
00350                     State.RT = buttonState ? 1.0f:0.0f;
00351                     break;
00352                 case 0x0B:
00353                     manipulateBitField(State.Buttons, Gamepad_L1, buttonState);
00354                     break;
00355                 case 0x0C:
00356                     manipulateBitField(State.Buttons, Gamepad_R1, buttonState);
00357                     break;
00358                 case 0x0D:
00359                     // PS3 Triangle.
00360                     manipulateBitField(State.Buttons, Gamepad_TRIANGLE, buttonState);
00361                     break;
00362                 case 0x0E:
00363                     // PS3 Circle
00364                     manipulateBitField(State.Buttons, Gamepad_CIRCLE, buttonState);
00365                     break;
00366                 case 0x0F:
00367                     // PS3 Cross
00368                     manipulateBitField(State.Buttons, Gamepad_CROSS, buttonState);
00369                     break;
00370                 case 0x10:
00371                     // PS3 Square
00372                     manipulateBitField(State.Buttons, Gamepad_SQUARE, buttonState);
00373                     break;
00374                 default:
00375                     return;
00376             }
00377         }
00378         else if (usagePage == kHIDPage_GenericDesktop)
00379         {
00380             float v;
00381             switch(usage)
00382             {
00383                 case kHIDUsage_GD_X:
00384                     v = mapAnalogAxis(value, element);
00385                     if (!setStateIfDifferent(State.LX, v))
00386                         return;
00387                     break;
00388                 case kHIDUsage_GD_Y:
00389                     v = mapAnalogAxis(value, element);
00390                     if (!setStateIfDifferent(State.LY, -v))
00391                         return;
00392                     break;
00393                 case kHIDUsage_GD_Z:
00394                     v = mapAnalogAxis(value, element);
00395                     if (!setStateIfDifferent(State.RX, v))
00396                         return;
00397                     break;
00398                 case kHIDUsage_GD_Rz:
00399                     v = mapAnalogAxis(value, element);
00400                     if (!setStateIfDifferent(State.RY, -v))
00401                         return;
00402                     break;
00403                 default:
00404                     return;
00405             }
00406         }
00407     }
00408     
00409     bStateChanged = true;
00410 }
00411     
00412 void GamepadManager::manipulateBitField(unsigned int& bitfield, unsigned int mask, bool val)
00413 {
00414     if (val)
00415     {
00416         bitfield |= mask;
00417     }
00418     else
00419     {
00420         bitfield &= ~mask;
00421     }
00422 }
00423 
00424 }}} // OVR::Platform::OSX


oculus_sdk
Author(s): Tully Foote
autogenerated on Thu Jun 6 2019 20:13:48