示例#1
0
// NOTE: I pieced this together through trial and error, any corrections are welcome
static void hid_device_input_callback(void* context, IOReturn result, void* sender, IOHIDValueRef value)
{
   struct apple_pad_connection* connection = (struct apple_pad_connection*)context;

   IOHIDElementRef element = IOHIDValueGetElement(value);
   uint32_t type = IOHIDElementGetType(element);
   uint32_t page = IOHIDElementGetUsagePage(element);
   uint32_t use = IOHIDElementGetUsage(element);

   // Joystick handler: TODO: Can GamePad work the same?
   if (type == kIOHIDElementTypeInput_Button && page == kHIDPage_Button)
   {
      CFIndex state = IOHIDValueGetIntegerValue(value);

      if (state)  g_current_input_data.pad_buttons[connection->slot] |= (1 << (use - 1));
      else        g_current_input_data.pad_buttons[connection->slot] &= ~(1 << (use - 1));
   }
   else if (type == kIOHIDElementTypeInput_Misc && page == kHIDPage_GenericDesktop)
   {
      static const uint32_t axis_use_ids[4] = { 48, 49, 50, 53 };
      for (int i = 0; i < 4; i ++)
      {
         if (use == axis_use_ids[i])
         {
            CFIndex min = IOHIDElementGetPhysicalMin(element);
            CFIndex max = IOHIDElementGetPhysicalMax(element) - min;
            CFIndex state = IOHIDValueGetIntegerValue(value) - min;
         
            float val = (float)state / (float)max;
            g_current_input_data.pad_axis[connection->slot][i] = ((val * 2.0f) - 1.0f) * 32767.0f;
         }
      }
   }
}
  void
  osxHIDPointingDevice::hidQueueCallback(void *context, IOReturn /*result*/, void *sender) {
    // std::cerr << "osxHIDPointingDevice::hidQueueCallback" << std::endl ;
    
    osxHIDPointingDevice *self = (osxHIDPointingDevice*)context ;
    IOHIDQueueRef queue = (IOHIDQueueRef)sender ;

    while (true) {

      IOHIDValueRef hidvalue = IOHIDQueueCopyNextValueWithTimeout(queue, 0.) ;
      if (!hidvalue) break ;

#if 1
      TimeStamp::inttime uptime = AbsoluteTimeInNanoseconds(IOHIDValueGetTimeStamp(hidvalue)) ;
      TimeStamp::inttime timestamp = self->epoch + (uptime - self->epoch_mach)*TimeStamp::one_nanosecond ;
#else

      TimeStamp::inttime timestamp = TimeStamp::createAsInt() ;
#endif

      if (self->qreport.isOlderThan(timestamp)) {
	// Flush the old qreport before creating a new one
	self->report(self->qreport) ;
	self->qreport.clear() ;
      }

      IOHIDElementRef element = IOHIDValueGetElement(hidvalue) ;
      uint32_t usagepage = IOHIDElementGetUsagePage(element) ;
      uint32_t usage = IOHIDElementGetUsage(element) ;
      //std::cout << usagepage << std::endl;
      //std::cout << usage << std::endl;
      if (usagepage==kHIDPage_GenericDesktop) {
	if (usage==kHIDUsage_GD_X || usage==kHIDUsage_GD_Y) {
      // Could use IOHIDValueGetScaledValue(hidvalue, kIOHIDValueScaleTypePhysical)
      CFIndex d = IOHIDValueGetIntegerValue(hidvalue) ;

      //std::cout << IOHIDValueGetBytePtr(hidvalue) << std::endl;
      //std::cout << IOHIDValueGetLength(hidvalue) << std::endl;
      if (d) {
	    if (usage==kHIDUsage_GD_X) self->qreport.dx = (int32_t)d ; else self->qreport.dy = (int32_t)d ;
	    self->qreport.t = timestamp ;
	  }
	}
	// FIXME: GD_Z, GD_Wheel, etc.
      } else if (usagepage==kHIDPage_Button) {
	// kHIDUsage_Button_1 is 1
	self->qreport.setButton(usage-1, (uint32_t)IOHIDValueGetIntegerValue(hidvalue)) ;
	self->qreport.t = timestamp ;
      }

      CFRelease(hidvalue) ;
    }

    // Flush the qreport we were constructing, if any
    if (self->qreport.t!=TimeStamp::undef)
      self->report(self->qreport) ;
    self->qreport.clear() ;
  }
示例#3
0
static SDL_bool
GetHIDElementState(recDevice *pDevice, recElement *pElement, SInt32 *pValue)
{
    SInt32 value = 0;
    int returnValue = SDL_FALSE;

    if (pDevice && pElement) {
        IOHIDValueRef valueRef;
        if (IOHIDDeviceGetValue(pDevice->deviceRef, pElement->elementRef, &valueRef) == kIOReturnSuccess) {
            value = (SInt32) IOHIDValueGetIntegerValue(valueRef);

            /* record min and max for auto calibration */
            if (value < pElement->minReport) {
                pElement->minReport = value;
            }
            if (value > pElement->maxReport) {
                pElement->maxReport = value;
            }
            *pValue = value;

            returnValue = SDL_TRUE;
        }
    }
    return returnValue;
}
示例#4
0
    void analog_event(IOReturn result, IOHIDElementRef element, IOHIDValueRef value) {
        int int_value = IOHIDValueGetIntegerValue(value);
        uint16_t usage = IOHIDElementGetUsage(element);
        switch (usage) {
          case kHIDUsage_GD_X:
          case kHIDUsage_GD_Y:
          case kHIDUsage_GD_Rx:
          case kHIDUsage_GD_Ry:
            {
                int min = IOHIDElementGetLogicalMin(element);
                int max = IOHIDElementGetLogicalMax(element);
                double double_value = int_value;
                if (int_value < 0) {
                    double_value = -(double_value / min);
                } else {
                    double_value = (double_value / max);
                }

                usage -= kHIDUsage_GD_X;
                gamepad[usage] = double_value;
                static const int x_component[] = {0, 0, -1, 3, 3, -1};
                double x = gamepad[x_component[usage]];
                double y = gamepad[x_component[usage] + 1];
                enqueue(new GamepadStickEvent(
                            now_usecs(), kHIDUsage_GD_X + x_component[usage], x, y));
            }
            break;
          case kHIDUsage_GD_Z:
          case kHIDUsage_GD_Rz:
            button_event(result, element, value);
            break;
        }
    }
示例#5
0
static void input_callback(void *ctx, IOReturn result, void *sender, IOHIDValueRef value)
{
	struct osx_mouse_data *mdata = static_cast<struct osx_mouse_data *>(ctx);
	IOHIDElementRef elem = IOHIDValueGetElement(value);
	uint32_t page = IOHIDElementGetUsagePage(elem);
	uint32_t usage = IOHIDElementGetUsage(elem);
	uint32_t val = IOHIDValueGetIntegerValue(value);

	if (page == kHIDPage_GenericDesktop) {
		switch (usage) {
			case kHIDUsage_GD_X:
				SDL_LockMutex(mdata->mouse_mutex);
				mdata->mouse_x += val;
				SDL_UnlockMutex(mdata->mouse_mutex);
				break;
			case kHIDUsage_GD_Y:
				SDL_LockMutex(mdata->mouse_mutex);
				mdata->mouse_y += val;
				SDL_UnlockMutex(mdata->mouse_mutex);
				break;
			default:
				break;
		}
	}
}
示例#6
0
bool Joystick::update()
{
  if(!p->deviceId)
    return false;

  IOHIDValueRef valueRef;

  for(int i = 0; i < numOfAxes; ++i)
    if(p->axisIds[i])
    {
      IOHIDDeviceGetValue((IOHIDDeviceRef) p->deviceId, (IOHIDElementRef) p->axisIds[i], &valueRef);
      p->axisState[i] = (int) IOHIDValueGetIntegerValue(valueRef);
    }

  unsigned newState = 0;
  for(int i = 0; i < numOfButtons; ++i)
    if(p->buttonIds[i])
    {
      IOHIDDeviceGetValue((IOHIDDeviceRef) p->deviceId, (IOHIDElementRef) p->buttonIds[i], &valueRef);
      newState |= IOHIDValueGetIntegerValue(valueRef) ? 1 << i : 0;
    }
  p->buttonEvents[0] |= p->buttonState[0] ^ newState;
  p->buttonState[0] = newState;

  if(p->hatId)
  {
    IOHIDDeviceGetValue((IOHIDDeviceRef) p->deviceId, (IOHIDElementRef) p->hatId, &valueRef);
    int dir = (int) IOHIDValueGetIntegerValue(valueRef);
    newState = !(dir & 8) ? 1 << dir : 0;
    p->buttonEvents[1] |= p->buttonState[1] ^ newState;
    p->buttonState[1] = newState;
    p->axisState[6] = p->axisState[7] = 0;
    if(!(dir & 8))
    {
      if(dir == 7 || dir <= 1)
        p->axisState[7] = p->axisMin[7];
      else if(dir >= 3 && dir <= 5)
        p->axisState[7] = p->axisMax[7];
      if(dir >= 1 && dir <= 3)
        p->axisState[6] = p->axisMax[6];
      else if(dir >= 5 && dir <= 7)
        p->axisState[6] = p->axisMin[6];
    }
  }

  return true;
}
示例#7
0
void setKeyboard(struct __IOHIDDevice *device, CFDictionaryRef keyboardDictionary, LedState changes[])
{
    CFStringRef deviceNameRef = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
    if (!deviceNameRef) return;
    
    const char * deviceName = CFStringGetCStringPtr(deviceNameRef, kCFStringEncodingUTF8);
    
    if (nameMatch && fnmatch(nameMatch, deviceName, 0) != 0)
        return;
    
    if (verbose)
        printf("\n \"%s\" ", deviceName);
    
    CFArrayRef elements = IOHIDDeviceCopyMatchingElements(device, keyboardDictionary, kIOHIDOptionsTypeNone);
    if (elements) {
        for (CFIndex elementIndex = 0; elementIndex < CFArrayGetCount(elements); elementIndex++) {
            IOHIDElementRef element = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, elementIndex);
            if (element && kHIDPage_LEDs == IOHIDElementGetUsagePage(element)) {
                uint32_t led = IOHIDElementGetUsage(element);
                
                if (led >= maxLeds) break;
                
                // Get current keyboard led status
                IOHIDValueRef currentValue = 0;
                if (IOHIDDeviceGetValue(device, element, &currentValue) == kIOReturnSuccess &&
                    IOHIDValueGetLength(currentValue) < 3) {
                    long current = IOHIDValueGetIntegerValue(currentValue);
                    CFRelease(currentValue);
                    
                    // Should we try to set the led?
                    if (changes[led] != NoChange && changes[led] != current) {
                        IOHIDValueRef newValue = IOHIDValueCreateWithIntegerValue(kCFAllocatorDefault, element, 0, changes[led]);
                        if (newValue) {
                            IOReturn changeResult = IOHIDDeviceSetValue(device, element, newValue);
                            
                            // Was the change successful?
                            if (kIOReturnSuccess == changeResult && verbose) {
                                printf("%s%s ", stateSymbol[changes[led]], ledNames[led - 1]);
                            }
                            CFRelease(newValue);
                        }
                    } else if (verbose) {
                        printf("%s%s ", stateSymbol[current], ledNames[led - 1]);
                    }
                }
            }
        }
        CFRelease(elements);
    }
    
    if (verbose)
        printf("\n");
}
示例#8
0
 void button_event(IOReturn result, IOHIDElementRef element, IOHIDValueRef value) {
     if (!antares_is_active()) {
         return;
     }
     bool down = IOHIDValueGetIntegerValue(value);
     uint16_t usage = IOHIDElementGetUsage(element);
     if (down) {
         enqueue(new GamepadButtonDownEvent(now_usecs(), usage));
     } else {
         enqueue(new GamepadButtonUpEvent(now_usecs(), usage));
     }
 }
示例#9
0
void CPH_HidMacOSX::InputValueCallback(IOHIDValueRef valueRef)
{
	IOHIDElementRef elementRef = IOHIDValueGetElement(valueRef);
	uint32 usage = IOHIDElementGetUsage(elementRef);
	uint32 usagePage = IOHIDElementGetUsagePage(elementRef);
	CFIndex state = IOHIDValueGetIntegerValue(valueRef);
	if(usagePage != kHIDPage_KeyboardOrKeypad) return;
	for(auto bindingIterator(std::begin(m_bindings));
	    bindingIterator != std::end(m_bindings); bindingIterator++)
	{
		const auto& binding = (*bindingIterator);
		if(!binding) continue;
		binding->ProcessEvent(usage, state);
	}
}
示例#10
0
HIDInputType HIDGamepad::valueChanged(IOHIDValueRef value)
{
    IOHIDElementCookie cookie = IOHIDElementGetCookie(IOHIDValueGetElement(value));
    HIDGamepadElement* element = m_elementMap.get(cookie);

    // This might be an element we don't currently handle as input so we can skip it.
    if (!element)
        return HIDInputType::NotAButtonPress;

    element->rawValue = IOHIDValueGetScaledValue(value, kIOHIDValueScaleTypePhysical);

    if (element->isButton()) {
        for (unsigned i = 0; i < m_buttons.size(); ++i) {
            if (&m_buttons[i].get() == element) {
                m_buttonValues[i] = element->normalizedValue();
                break;
            }
        }
    } else if (element->isAxis()) {
        for (unsigned i = 0; i < m_axes.size(); ++i) {
            if (&m_axes[i].get() == element) {
                m_axisValues[i] = element->normalizedValue();
                break;
            }
        }
    } else if (element->isDPad()) {
        int intValue = IOHIDValueGetIntegerValue(value) - element->min;
        for (unsigned i = 0; i < m_dPads.size(); ++i) {
            if (&m_dPads[i].get() != element)
                continue;

            // Each DPad represents 4 button values which are tacked on to the end of the values from non-DPad buttons.
            unsigned firstButtonValue = m_buttons.size() + i * 4;

            ASSERT(m_buttonValues.size() > firstButtonValue + 3);

            fillInButtonValues(intValue, m_buttonValues[firstButtonValue], m_buttonValues[firstButtonValue + 1], m_buttonValues[firstButtonValue + 2], m_buttonValues[firstButtonValue + 3]);
        }
    } else
        ASSERT_NOT_REACHED();

    m_lastUpdateTime = monotonicallyIncreasingTime();

    return element->isButton() ? HIDInputType::ButtonPress : HIDInputType::NotAButtonPress;
}
示例#11
0
    void key_event(IOReturn result, IOHIDElementRef element, IOHIDValueRef value) {
        if (!antares_is_active()) {
            return;
        }
        bool down = IOHIDValueGetIntegerValue(value);
        uint16_t scan_code = IOHIDElementGetUsage(element);
        if ((scan_code < 4) || (231 < scan_code)) {
            return;
        } else if (scan_code == Keys::CAPS_LOCK) {
            return;
        }

        if (down) {
            enqueue(new KeyDownEvent(now_usecs(), scan_code));
        } else {
            enqueue(new KeyUpEvent(now_usecs(), scan_code));
        }
    }
示例#12
0
float GamepadManager::mapAnalogAxis(IOHIDValueRef value, IOHIDElementRef element)
{
    
    CFIndex val = IOHIDValueGetIntegerValue(value);
    CFIndex min = IOHIDElementGetLogicalMin(element);
    CFIndex max = IOHIDElementGetLogicalMax(element);
    
    float v = (float) (val - min) / (float) (max - min);
    v = v * 2.0f - 1.0f;
    
    // Dead zone.
    if (v < 0.1f && v > -0.1f)
    {
        v = 0.0f;
    }
    
    return v;
}
示例#13
0
int joypad::get_hid_element_state(rec_element *p_element) const {
	int value = 0;
	if (p_element && p_element->ref) {
		IOHIDValueRef valueRef;
		if (IOHIDDeviceGetValue(device_ref, p_element->ref, &valueRef) == kIOReturnSuccess) {
			value = (SInt32)IOHIDValueGetIntegerValue(valueRef);

			/* record min and max for auto calibration */
			if (value < p_element->min) {
				p_element->min = value;
			}
			if (value > p_element->max) {
				p_element->max = value;
			}
		}
	}
	return value;
}
示例#14
0
int  joy_hidlib_get_value(joy_hid_device_t *device, 
                          joy_hid_element_t *element,
                          int *value, int phys)
{
    IOHIDValueRef value_ref;
    IOReturn result = IOHIDDeviceGetValue( device->internal_device, 
                                           element->internal_element,
                                           &value_ref );
    if(result == kIOReturnSuccess) {
        if(phys) {
            *value = (int)IOHIDValueGetScaledValue( value_ref, kIOHIDValueScaleTypePhysical );
        } else {
            *value = (int)IOHIDValueGetIntegerValue( value_ref );
        }
        return 0;
    } else {
        return -1;
    }
}
示例#15
0
void CInputProviderMacOsHid::SetInitialBindValues(IOHIDDeviceRef device)
{
	CFArrayRef elements = IOHIDDeviceCopyMatchingElements(device, nullptr, 0);

	for(int i = 0; i < CFArrayGetCount(elements); i++)
	{
		IOHIDElementRef elementRef = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, i);
		uint32 usagePage = IOHIDElementGetUsagePage(elementRef);
		if(
		    (usagePage != kHIDPage_GenericDesktop) &&
		    (usagePage != kHIDPage_Button))
		{
			continue;
		}
		IOHIDValueRef valueRef;
		if(IOHIDDeviceGetValue(device, elementRef, &valueRef) != kIOReturnSuccess)
		{
			continue;
		}

		CFIndex value = IOHIDValueGetIntegerValue(valueRef);
		IOHIDElementType type = IOHIDElementGetType(elementRef);
		uint32 usage = IOHIDElementGetUsage(elementRef);
		BINDINGTARGET tgt;
		tgt.providerId = PROVIDER_ID;
		tgt.deviceId = GetDeviceID(device);
		tgt.keyId = usage;
		tgt.keyType = GetKeyType(usage, type);
		switch(type)
		{
		case kIOHIDElementTypeInput_Misc:
		case kIOHIDElementTypeInput_Button:
		case kIOHIDElementTypeInput_Axis:
			OnInput(tgt, value);
			break;
		default:
			break;
		}
	}
}
示例#16
0
void CInputProviderMacOsHid::InputValueCallback(DEVICE_INFO* deviceInfo, IOReturn result, void* sender, IOHIDValueRef valueRef)
{
	if(!OnInput) return;

	IOHIDElementRef elementRef = IOHIDValueGetElement(valueRef);
	uint32 usagePage = IOHIDElementGetUsagePage(elementRef);
	if(
	    (usagePage != kHIDPage_GenericDesktop) &&
	    (usagePage != kHIDPage_Button))
	{
		return;
	}
	uint32 usage = IOHIDElementGetUsage(elementRef);
	CFIndex value = IOHIDValueGetIntegerValue(valueRef);
	IOHIDElementType type = IOHIDElementGetType(elementRef);
	BINDINGTARGET tgt;
	tgt.providerId = PROVIDER_ID;
	tgt.deviceId = deviceInfo->deviceId;
	tgt.keyId = usage;
	tgt.keyType = GetKeyType(usage, type);
	OnInput(tgt, value);
}
static void PsychHIDKbQueueCallbackFunction(void *target, IOReturn result, void *sender)
{
    // This routine is executed each time the queue transitions from empty to non-empty
    // The CFRunLoop of the thread in KbQueueWorkerThreadMain() is the one that executes here:
    IOHIDQueueRef queue = (IOHIDQueueRef) sender;
    IOHIDValueRef valueRef = NULL;
    int deviceIndex = (int) target;
    double timestamp;
    int eventValue;
    long keysUsage = -1;
    PsychHIDEventRecord evt;
    
    result=kIOReturnError;
    if (!queue) return; // Nothing we can do because we can't access queue, (shouldn't happen)
    
    while (1) {
        // This function only gets called when queue transitions from empty to non-empty
        // Therefore, we must process all available events in this while loop before
        // it will be possible for this function to be notified again.
        if (valueRef) {
            CFRelease(valueRef);
            valueRef = NULL;
        }
        
        // Dequeue next event from queue in a polling non-blocking fashion:
        valueRef = IOHIDQueueCopyNextValueWithTimeout(queue, 0.0);
        
        // Done? Exit, if so:
        if (!valueRef) break;
        
        // Get event value, e.g., the key state of a key or button 1 = pressed, 0 = released:
        eventValue = IOHIDValueGetIntegerValue(valueRef);
        
        // Get usage value, ie., the identity of the key:
        IOHIDElementRef element = IOHIDValueGetElement(valueRef);
        keysUsage = IOHIDElementGetUsage(element);
        
        // Get double GetSecs timestamp, computed from returned uint64 nanoseconds timestamp:
        timestamp = convertTime(IOHIDValueGetTimeStamp(valueRef));
        
        // Don't bother with keysUsage of 0 (meaningless) or 1 (ErrorRollOver) for keyboards:
        if ((queueIsAKeyboard[deviceIndex]) && (keysUsage <= 1)) continue;
        
        // Clear ringbuffer event:
        memset(&evt, 0 , sizeof(evt));
        
        // Cooked key code defaults to "unhandled", and stays that way for anything but keyboards:
        evt.cookedEventCode = -1;
        
        // For real keyboards we can compute cooked key codes: Requires OSX 10.5 or later.
        if (queueIsAKeyboard[deviceIndex]) {
            // Keyboard(ish) device. We can handle this under some conditions.
            // Init to a default of handled, but unmappable/ignored keycode:
            evt.cookedEventCode = 0;
            
            // Keypress event code available in mapping table?
            if (keysUsage < kHID2VKCSize) {
                // Yes: We try to map this to a character code:
                
                // Step 1: Map HID usage value to virtual keycode via LUT:
                uint16_t vcKey = kHID2VKC[keysUsage];
                
                // Keep track of SHIFT keys as modifier keys: Bits 0 == Command, 1 == Shift, 2 == CapsLock, 3 == Alt/Option, 4 == CTRL
                if ((vcKey == kVKC_Shift || vcKey == kVKC_rShift) && (eventValue != 0)) modifierKeyState[deviceIndex] |=  (1 << 1);
                if ((vcKey == kVKC_Shift || vcKey == kVKC_rShift) && (eventValue == 0)) modifierKeyState[deviceIndex] &= ~(1 << 1);
                
                // Keep track of ALT keys as modifier keys:
                if ((vcKey == kVKC_Option || vcKey == kVKC_rOption) && (eventValue != 0)) modifierKeyState[deviceIndex] |=  (1 << 3);
                if ((vcKey == kVKC_Option || vcKey == kVKC_rOption) && (eventValue == 0)) modifierKeyState[deviceIndex] &= ~(1 << 3);
                
                // Keep track of CTRL keys as modifier keys:
                if ((vcKey == kVKC_Control || vcKey == kVKC_rControl) && (eventValue != 0)) modifierKeyState[deviceIndex] |=  (1 << 4);
                if ((vcKey == kVKC_Control || vcKey == kVKC_rControl) && (eventValue == 0)) modifierKeyState[deviceIndex] &= ~(1 << 4);
                
                // Was this a CTRL + C interrupt request?
                if ((eventValue != 0) && (vcKey == 0x08) && (modifierKeyState[deviceIndex] & (1 << 4))) {
                    // Yes: Tell the console input helper about it, so it can send interrupt
                    // signals to the runtime and reenable keyboard input if appropriate:
                    // Note: Not sure if the mutex exclusion is needed here, but better safe than sorry.
                    PsychLockMutex(&KbQueueMutex);
                    ConsoleInputHelper(-1);
                    PsychUnlockMutex(&KbQueueMutex);
                }
                
                // Key press?
                if (eventValue != 0) {
                    // Step 2: Translate virtual key code into unicode char:
                    // Ok, this is the usual horrifying complexity of Apple's system. We use code
                    // snippets found on StackOverflow, modified to suit our needs, e.g., we track
                    // modifier keys manually, at least left and right ALT and SHIFT keys. We don't
                    // care about other modifiers.
                    TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
                    CFDataRef uchr = (CFDataRef) ((currentKeyboard) ? TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData) : NULL);
                    const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout*) ((uchr) ? CFDataGetBytePtr(uchr) : NULL);
                    
                    if (keyboardLayout) {
                        UInt32 deadKeyState = 0;
                        UniCharCount maxStringLength = 255;
                        UniCharCount actualStringLength = 0;
                        UniChar unicodeString[maxStringLength];
                        
                        OSStatus status = UCKeyTranslate(keyboardLayout,
                                                         vcKey, kUCKeyActionDown, modifierKeyState[deviceIndex],
                                                         LMGetKbdType(), 0,
                                                         &deadKeyState,
                                                         maxStringLength,
                                                         &actualStringLength, unicodeString);
                        
                        if ((actualStringLength == 0) && deadKeyState) {
                            status = UCKeyTranslate(keyboardLayout,
                                                    kVK_Space, kUCKeyActionDown, 0,
                                                    LMGetKbdType(), 0,
                                                    &deadKeyState,
                                                    maxStringLength,
                                                    &actualStringLength, unicodeString);
                        }
                        
                        if((actualStringLength > 0) && (status == noErr)) {
                            // Assign final cooked / mapped keycode:
                            evt.cookedEventCode = (int) unicodeString[0];
                            
                            // Send same keystroke character to console input helper.
                            // In kbqueue-based ListenChar(1) mode, the helper will
                            // inject/forward the character into the runtime:
                            // Note: ConsoleInputHelper() should be safe to call without
                            // mutex protection for >= 0 event codes.
                            ConsoleInputHelper(evt.cookedEventCode);
                        }
                    }
                }
            }
        }
        
        PsychLockMutex(&KbQueueMutex);

        // Update records of first and latest key presses and releases
        if (eventValue != 0) {
            if (psychHIDKbQueueFirstPress[deviceIndex]) {
                // First key press timestamp:
                if (psychHIDKbQueueFirstPress[deviceIndex][keysUsage-1] == 0) {
                    psychHIDKbQueueFirstPress[deviceIndex][keysUsage-1] = timestamp;
                }
            }

            if (psychHIDKbQueueLastPress[deviceIndex]) {
                // Last key press timestamp:
                psychHIDKbQueueLastPress[deviceIndex][keysUsage-1] = timestamp;
            }
            evt.status |= (1 << 0);
        }
        else {
            if (psychHIDKbQueueFirstRelease[deviceIndex]) {
                // First key release timestamp:
                if (psychHIDKbQueueFirstRelease[deviceIndex][keysUsage-1] == 0) psychHIDKbQueueFirstRelease[deviceIndex][keysUsage-1] = timestamp;
            }

            if (psychHIDKbQueueLastRelease[deviceIndex]) {
                // Last key release timestamp:
                psychHIDKbQueueLastRelease[deviceIndex][keysUsage-1] = timestamp;
            }
            evt.status &= ~(1 << 0);
        }

        // Update event buffer:
        evt.timestamp = timestamp;
        evt.rawEventCode = keysUsage;
        PsychHIDAddEventToEventBuffer(deviceIndex, &evt);

        // Tell waiting userspace (under KbQueueMutxex protection for better scheduling) something interesting has changed:
        PsychSignalCondition(&KbQueueCondition);

        PsychUnlockMutex(&KbQueueMutex);

        // Next while loop iteration to dequeue potentially more events:
    }
    
    // Done for this queue transition. Return to runloop.
}
示例#18
0
static void onDeviceValueChanged(void * context, IOReturn result, void * sender, IOHIDValueRef value) {
  struct Gamepad_device * deviceRecord;
  struct Gamepad_devicePrivate * hidDeviceRecord;
  IOHIDElementRef element;
  IOHIDElementCookie cookie;
  unsigned int axisIndex, buttonIndex;
  static mach_timebase_info_data_t timebaseInfo;
	
  if (timebaseInfo.denom == 0) {
    mach_timebase_info(&timebaseInfo);
  }
	
  deviceRecord = context;
  hidDeviceRecord = deviceRecord->privateData;
  element = IOHIDValueGetElement(value);
  cookie = IOHIDElementGetCookie(element);
	
  for (axisIndex = 0; axisIndex < deviceRecord->numAxes; axisIndex++) {
    if (!hidDeviceRecord->axisElements[axisIndex].isHatSwitchSecondAxis &&
        hidDeviceRecord->axisElements[axisIndex].cookie == cookie) {
      CFIndex integerValue;
			
      if (IOHIDValueGetLength(value) > 4) {
        // Workaround for a strange crash that occurs with PS3 controller; was getting lengths of 39 (!)
        continue;
      }
      integerValue = IOHIDValueGetIntegerValue(value);
			
      if (hidDeviceRecord->axisElements[axisIndex].isHatSwitch) {
        int x, y;
				
        // Fix for Saitek X52
        if (!hidDeviceRecord->axisElements[axisIndex].hasNullState) {
          if (integerValue < hidDeviceRecord->axisElements[axisIndex].logicalMin) {
            integerValue = hidDeviceRecord->axisElements[axisIndex].logicalMax - hidDeviceRecord->axisElements[axisIndex].logicalMin + 1;
          } else {
            integerValue--;
          }
        }
				
        hatValueToXY(integerValue, hidDeviceRecord->axisElements[axisIndex].logicalMax - hidDeviceRecord->axisElements[axisIndex].logicalMin + 1, &x, &y);
				
        if (x != deviceRecord->axisStates[axisIndex]) {
          queueAxisEvent(deviceRecord,
                         IOHIDValueGetTimeStamp(value) * timebaseInfo.numer / timebaseInfo.denom * 0.000000001,
                         axisIndex,
                         x,
                         deviceRecord->axisStates[axisIndex]);
					
          deviceRecord->axisStates[axisIndex] = x;
        }
				
        if (y != deviceRecord->axisStates[axisIndex + 1]) {
          queueAxisEvent(deviceRecord,
                         IOHIDValueGetTimeStamp(value) * timebaseInfo.numer / timebaseInfo.denom * 0.000000001,
                         axisIndex + 1,
                         y,
                         deviceRecord->axisStates[axisIndex + 1]);
					
          deviceRecord->axisStates[axisIndex + 1] = y;
        }
				
      } else {
        float floatValue;
				
        if (integerValue < hidDeviceRecord->axisElements[axisIndex].logicalMin) {
          hidDeviceRecord->axisElements[axisIndex].logicalMin = integerValue;
        }
        if (integerValue > hidDeviceRecord->axisElements[axisIndex].logicalMax) {
          hidDeviceRecord->axisElements[axisIndex].logicalMax = integerValue;
        }
        floatValue = (integerValue - hidDeviceRecord->axisElements[axisIndex].logicalMin) / (float) (hidDeviceRecord->axisElements[axisIndex].logicalMax - hidDeviceRecord->axisElements[axisIndex].logicalMin) * 2.0f - 1.0f;
				
        queueAxisEvent(deviceRecord,
                       IOHIDValueGetTimeStamp(value) * timebaseInfo.numer / timebaseInfo.denom * 0.000000001,
                       axisIndex,
                       floatValue,
                       deviceRecord->axisStates[axisIndex]);
				
        deviceRecord->axisStates[axisIndex] = floatValue;
      }
			
      return;
    }
  }
	
  for (buttonIndex = 0; buttonIndex < deviceRecord->numButtons; buttonIndex++) {
    if (hidDeviceRecord->buttonElements[buttonIndex].cookie == cookie) {
      bool down;
			
      down = IOHIDValueGetIntegerValue(value);
      queueButtonEvent(deviceRecord,
                       IOHIDValueGetTimeStamp(value) * timebaseInfo.numer / timebaseInfo.denom * 0.000000001,
                       buttonIndex,
                       down);
			
      deviceRecord->buttonStates[buttonIndex] = down;
			
      return;
    }
  }
}
示例#19
0
static void input_callback(void *context, IOReturn result, void *sender, IOHIDValueRef value)
{
	struct input_data *input = (struct input_data*)context;
	IOHIDElementRef elem = IOHIDValueGetElement(value);
	uint32_t page = IOHIDElementGetUsagePage(elem);
	uint32_t usage = IOHIDElementGetUsage(elem);
	uint32_t val = IOHIDValueGetIntegerValue(value);

	if (page == kHIDPage_GenericDesktop)
	{
		if (input->ignore_mouse)
		{
			return;
		}

		switch (usage)
		{
			case kHIDUsage_GD_X:
				pthread_mutex_lock(&input->mouse_mutex);
				input->mouse_x += val;
				pthread_mutex_unlock(&input->mouse_mutex);
				break;
			case kHIDUsage_GD_Y:
				pthread_mutex_lock(&input->mouse_mutex);
				input->mouse_y += val;
				pthread_mutex_unlock(&input->mouse_mutex);
				break;
			case kHIDUsage_GD_Wheel:
				if ((int32_t)val > 0)
				{
					add_to_event_queue(input, K_MWHEELUP, true);
					add_to_event_queue(input, K_MWHEELUP, false);
				}
				else if ((int32_t)val < 0)
				{
					add_to_event_queue(input, K_MWHEELDOWN, true);
					add_to_event_queue(input, K_MWHEELDOWN, false);
				}
				break;
			default:
				break;
		}
	}
	else if (page == kHIDPage_Button)
	{
		if (input->ignore_mouse)
		{
			return;
		}

		if (usage < 1 || usage > 10)
		{
			usage = 10;
		}

		add_to_event_queue(input, K_MOUSE1 + usage - 1, val ? true : false);
	}
	else if (page == kHIDPage_KeyboardOrKeypad)
	{
		if (usage == kHIDUsage_KeyboardLeftGUI)
		{
			input->left_cmd_key_active = val ? true : false;
		}
		else if (usage == kHIDUsage_KeyboardRightGUI)
		{
			input->right_cmd_key_active = val ? true : false;
		}

		if (usage < sizeof(keytable) && (input->left_cmd_key_active || input->right_cmd_key_active))
		{
			if (keytable[usage] == 'c' && val)
			{
				add_to_event_queue(input, K_COPY, true);
				add_to_event_queue(input, K_COPY, false);
			}
			else if (keytable[usage] == 'v' && val)
			{
				add_to_event_queue(input, K_PASTE, true);
				add_to_event_queue(input, K_PASTE, false);
			}

			return;
		}

		if (usage < sizeof(keytable))
		{
			add_to_event_queue(input, keytable[usage], val ? true : false);

			pthread_mutex_lock(&input->key_mutex);

			if (val)
			{
				input->repeatkey = keytable[usage];
				input->nextrepeattime = Sys_IntTime() + input->key_repeat_initial_delay;
			}
			else
			{
				input->repeatkey = 0;
				input->nextrepeattime = 0;
			}

			pthread_mutex_unlock(&input->key_mutex);
		}
	}
	else if (page == 0xFF)
	{
		if (usage == kHIDUsage_KeyboardErrorUndefined)
		{
			input->fn_key_active = val ? true : false;
		}
	}
}
示例#20
0
JoystickState JoystickImpl::update()
{
    static const JoystickState disconnectedState; // return this if joystick was disconnected
    JoystickState       state; // otherwise return that
    state.connected = true;

    // Note: free up is done in close() which is called, if required,
    //       by the joystick manager. So we don't release buttons nor axes here.

    // First, let's determine if the joystick is still connected
    Location selfLoc = m_locationIDs[m_index];

    // Get all devices
    CFSetRef devices = HIDJoystickManager::getInstance().copyJoysticks();
    if (devices == NULL)
        return disconnectedState;

    // Get a usable copy of the joysticks devices.
    CFIndex joysticksCount = CFSetGetCount(devices);
    CFTypeRef devicesArray[joysticksCount];
    CFSetGetValues(devices, devicesArray);

    // Search for it
    bool found = false;
    for (CFIndex i(0); i < joysticksCount; ++i)
    {
        IOHIDDeviceRef d = (IOHIDDeviceRef)devicesArray[i];
        if (selfLoc == HIDInputManager::getLocationID(d))
        {
            found = true;
            break; // Stop looping
        }
    }

    // Release unused stuff
    CFRelease(devices);

    // If not found we consider it disconnected
    if (!found)
        return disconnectedState;

    // Update buttons' state
    unsigned int i = 0;
    for (ButtonsVector::iterator it(m_buttons.begin()); it != m_buttons.end(); ++it, ++i)
    {
        IOHIDValueRef value = 0;
        IOHIDDeviceGetValue(IOHIDElementGetDevice(*it), *it, &value);

        // Check for plug out.
        if (!value)
        {
            // No value? Hum... Seems like the joystick is gone
            return disconnectedState;
        }

        // 1 means pressed, others mean released
        state.buttons[i] = IOHIDValueGetIntegerValue(value) == 1;
    }

    // Update axes' state
    for (AxisMap::iterator it = m_axis.begin(); it != m_axis.end(); ++it)
    {
        IOHIDValueRef value = 0;
        IOHIDDeviceGetValue(IOHIDElementGetDevice(it->second), it->second, &value);

        // Check for plug out.
        if (!value)
        {
            // No value? Hum... Seems like the joystick is gone
            return disconnectedState;
        }

        // We want to bind [physicalMin,physicalMax] to [-100=min,100=max].
        //
        // General formula to bind [a,b] to [c,d] with a linear progression:
        //
        // f: [a, b] -> [c, d]
        //        x  |->  (x-a)(d-c)/(b-a)+c
        //
        // This method might not be very accurate (the "0 position" can be
        // slightly shift with some device) but we don't care because most
        // of devices are so sensitive that this is not relevant.
        double  physicalMax   = IOHIDElementGetPhysicalMax(it->second);
        double  physicalMin   = IOHIDElementGetPhysicalMin(it->second);
        double  scaledMin     = -100;
        double  scaledMax     =  100;
        double  physicalValue = IOHIDValueGetScaledValue(value, kIOHIDValueScaleTypePhysical);
        float   scaledValue   = (((physicalValue - physicalMin) * (scaledMax - scaledMin)) / (physicalMax - physicalMin)) + scaledMin;
        state.axes[it->first] = scaledValue;
    }

    return state;
}
示例#21
0
static void poll_osx_device_state(LPDIRECTINPUTDEVICE8A iface)
{
    JoystickImpl *device = impl_from_IDirectInputDevice8A(iface);
    IOHIDElementRef tIOHIDTopElementRef;
    IOHIDDeviceRef tIOHIDDeviceRef;
    CFArrayRef gElementCFArrayRef = device->elementCFArrayRef;

    TRACE("polling device %i\n",device->id);

    if (!gCollections)
        return;

    tIOHIDTopElementRef = (IOHIDElementRef) CFArrayGetValueAtIndex(gCollections, device->id);
    tIOHIDDeviceRef = IOHIDElementGetDevice(tIOHIDTopElementRef);

    if (!tIOHIDDeviceRef)
        return;

    if (gElementCFArrayRef)
    {
        int button_idx = 0;
        int pov_idx = 0;
        int slider_idx = 0;
        int inst_id;
        CFIndex idx, cnt = CFArrayGetCount( gElementCFArrayRef );

        for ( idx = 0; idx < cnt; idx++ )
        {
            IOHIDValueRef valueRef;
            int val, oldVal, newVal;
            IOHIDElementRef tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( gElementCFArrayRef, idx );
            int eleType = IOHIDElementGetType( tIOHIDElementRef );

            switch(eleType)
            {
            case kIOHIDElementTypeInput_Button:
                if(button_idx < 128)
                {
                    IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &valueRef);
                    val = IOHIDValueGetIntegerValue(valueRef);
                    newVal = val ? 0x80 : 0x0;
                    oldVal = device->generic.js.rgbButtons[button_idx];
                    device->generic.js.rgbButtons[button_idx] = newVal;
                    if (oldVal != newVal)
                    {
                        inst_id = DIDFT_MAKEINSTANCE(button_idx) | DIDFT_PSHBUTTON;
                        queue_event(iface,inst_id,newVal,GetCurrentTime(),device->generic.base.dinput->evsequence++);
                    }
                    button_idx ++;
                }
                break;
            case kIOHIDElementTypeInput_Misc:
            {
                uint32_t usage = IOHIDElementGetUsage( tIOHIDElementRef );
                switch(usage)
                {
                case kHIDUsage_GD_Hatswitch:
                {
                    IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &valueRef);
                    val = IOHIDValueGetIntegerValue(valueRef);
                    oldVal = device->generic.js.rgdwPOV[pov_idx];
                    if (val >= 8)
                        newVal = -1;
                    else
                        newVal = val * 4500;
                    device->generic.js.rgdwPOV[pov_idx] = newVal;
                    if (oldVal != newVal)
                    {
                        inst_id = DIDFT_MAKEINSTANCE(pov_idx) | DIDFT_POV;
                        queue_event(iface,inst_id,newVal,GetCurrentTime(),device->generic.base.dinput->evsequence++);
                    }
                    pov_idx ++;
                    break;
                }
                case kHIDUsage_GD_X:
                case kHIDUsage_GD_Y:
                case kHIDUsage_GD_Z:
                case kHIDUsage_GD_Rx:
                case kHIDUsage_GD_Ry:
                case kHIDUsage_GD_Rz:
                case kHIDUsage_GD_Slider:
                {
                    int wine_obj = -1;

                    IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &valueRef);
                    val = IOHIDValueGetIntegerValue(valueRef);
                    newVal = joystick_map_axis(&device->generic.props[idx], val);
                    switch (usage)
                    {
                    case kHIDUsage_GD_X:
                        wine_obj = 0;
                        oldVal = device->generic.js.lX;
                        device->generic.js.lX = newVal;
                        break;
                    case kHIDUsage_GD_Y:
                        wine_obj = 1;
                        oldVal = device->generic.js.lY;
                        device->generic.js.lY = newVal;
                        break;
                    case kHIDUsage_GD_Z:
                        wine_obj = 2;
                        oldVal = device->generic.js.lZ;
                        device->generic.js.lZ = newVal;
                        break;
                    case kHIDUsage_GD_Rx:
                        wine_obj = 3;
                        oldVal = device->generic.js.lRx;
                        device->generic.js.lRx = newVal;
                        break;
                    case kHIDUsage_GD_Ry:
                        wine_obj = 4;
                        oldVal = device->generic.js.lRy;
                        device->generic.js.lRy = newVal;
                        break;
                    case kHIDUsage_GD_Rz:
                        wine_obj = 5;
                        oldVal = device->generic.js.lRz;
                        device->generic.js.lRz = newVal;
                        break;
                    case kHIDUsage_GD_Slider:
                        wine_obj = 6 + slider_idx;
                        oldVal = device->generic.js.rglSlider[slider_idx];
                        device->generic.js.rglSlider[slider_idx] = newVal;
                        slider_idx ++;
                        break;
                    }
                    if ((wine_obj != -1) &&
                            (oldVal != newVal))
                    {
                        inst_id = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
                        queue_event(iface,inst_id,newVal,GetCurrentTime(),device->generic.base.dinput->evsequence++);
                    }

                    break;
                }
                default:
                    FIXME("unhandled usage %i\n",usage);
                }
                break;
            }
            default:
                FIXME("Unhandled type %i\n",eleType);
            }
        }
    }
}
示例#22
0
static void poll_osx_device_state(LPDIRECTINPUTDEVICE8A iface)
{
    JoystickImpl *device = (JoystickImpl*)iface;
    IOHIDElementRef tIOHIDTopElementRef;
    IOHIDDeviceRef tIOHIDDeviceRef;
    CFArrayRef gElementCFArrayRef = device->elementCFArrayRef;

    TRACE("polling device %i\n",device->id);

    if (!gCollections)
        return;

    tIOHIDTopElementRef = (IOHIDElementRef) CFArrayGetValueAtIndex(gCollections, device->id);
    tIOHIDDeviceRef = IOHIDElementGetDevice(tIOHIDTopElementRef);

    if (!tIOHIDDeviceRef)
        return;

    if (gElementCFArrayRef)
    {
        int button_idx = 0;
        int pov_idx = 0;
        int slider_idx = 0;
        CFIndex idx, cnt = CFArrayGetCount( gElementCFArrayRef );

        for ( idx = 0; idx < cnt; idx++ )
        {
            IOHIDValueRef valueRef;
            int val;
            IOHIDElementRef tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( gElementCFArrayRef, idx );
            int eleType = IOHIDElementGetType( tIOHIDElementRef );

            switch(eleType)
            {
                case kIOHIDElementTypeInput_Button:
                    if(button_idx < 128)
                    {
                        IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &valueRef);
                        val = IOHIDValueGetIntegerValue(valueRef);
                        device->generic.js.rgbButtons[button_idx] = val ? 0x80 : 0x00;
                        button_idx ++;
                    }
                    break;
                case kIOHIDElementTypeInput_Misc:
                {
                    uint32_t usage = IOHIDElementGetUsage( tIOHIDElementRef );
                    switch(usage)
                    {
                        case kHIDUsage_GD_Hatswitch:
                        {
                            IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &valueRef);
                            val = IOHIDValueGetIntegerValue(valueRef);
                            if (val >= 8)
                                device->generic.js.rgdwPOV[pov_idx] = -1;
                            else
                                device->generic.js.rgdwPOV[pov_idx] = val * 4500;
                            pov_idx ++;
                            break;
                        }
                        case kHIDUsage_GD_X:
                        case kHIDUsage_GD_Y:
                        case kHIDUsage_GD_Z:
                        case kHIDUsage_GD_Rx:
                        case kHIDUsage_GD_Ry:
                        case kHIDUsage_GD_Rz:
                        case kHIDUsage_GD_Slider:
                        {
                            IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &valueRef);
                            val = IOHIDValueGetIntegerValue(valueRef);
                            switch (usage)
                            {
                            case kHIDUsage_GD_X:
                                device->generic.js.lX = joystick_map_axis(&device->generic.props[idx], val);
                                break;
                            case kHIDUsage_GD_Y:
                                device->generic.js.lY = joystick_map_axis(&device->generic.props[idx], val);
                                break;
                            case kHIDUsage_GD_Z:
                                device->generic.js.lZ = joystick_map_axis(&device->generic.props[idx], val);
                                break;
                            case kHIDUsage_GD_Rx:
                                device->generic.js.lRx = joystick_map_axis(&device->generic.props[idx], val);
                                break;
                            case kHIDUsage_GD_Ry:
                                device->generic.js.lRy = joystick_map_axis(&device->generic.props[idx], val);
                                break;
                            case kHIDUsage_GD_Rz:
                                device->generic.js.lRz = joystick_map_axis(&device->generic.props[idx], val);
                                break;
                            case kHIDUsage_GD_Slider:
                                device->generic.js.rglSlider[slider_idx] = joystick_map_axis(&device->generic.props[idx], val);
                                slider_idx ++;
                                break;
                            }
                            break;
                        }
                        default:
                            FIXME("unhandled usage %i\n",usage);
                    }
                    break;
                }
                default:
                    FIXME("Unhandled type %i\n",eleType);
            }
        }
    }
}
示例#23
0
void GamepadManager::onDeviceValueChanged(IOHIDValueRef value)
{
    
    IOHIDElementRef element = IOHIDValueGetElement(value);
    IOHIDDeviceRef device = IOHIDElementGetDevice(element);

    int vendorID = getIntDeviceProperty(device, CFSTR(kIOHIDVendorIDKey));
    int productID = getIntDeviceProperty(device, CFSTR(kIOHIDProductIDKey));
    
    uint32_t usagePage = IOHIDElementGetUsagePage(element);
    uint32_t usage = IOHIDElementGetUsage(element);

    // The following controller mapping is based on the Logitech F710, however we use it for
    // all Logitech devices on the assumption that they're likely to share the same mapping.
    if (vendorID == Logitech_F710_VendorID)
    {
        // Logitech F710 mapping.
        if (usagePage == kHIDPage_Button)
        {
            bool buttonState = IOHIDValueGetIntegerValue(value);

            switch(usage)
            {
                case kHIDUsage_Button_1:
                    manipulateBitField(State.Buttons, Gamepad_X, buttonState);
                    break;
                case kHIDUsage_Button_2:
                    manipulateBitField(State.Buttons, Gamepad_A, buttonState);
                    break;
                case kHIDUsage_Button_3:
                    manipulateBitField(State.Buttons, Gamepad_B, buttonState);
                    break;
                case kHIDUsage_Button_4:
                    manipulateBitField(State.Buttons, Gamepad_Y, buttonState);
                    break;
                case 0x05:
                    manipulateBitField(State.Buttons, Gamepad_L1, buttonState);
                    break;
                case 0x06:
                    manipulateBitField(State.Buttons, Gamepad_R1, buttonState);
                    break;
                case 0x07:
                    State.LT = buttonState ? 1.0f:0.0f;
                    break;
                case 0x08:
                    State.RT = buttonState ? 1.0f:0.0f;
                    break;
                case 0x09:
                    manipulateBitField(State.Buttons, Gamepad_Back, buttonState);
                    break;
                case 0x0A:
                    manipulateBitField(State.Buttons, Gamepad_Start, buttonState);
                    break;
                case 0x0B:
                    manipulateBitField(State.Buttons, Gamepad_LStick, buttonState);
                    break;
                case 0x0C:
                    manipulateBitField(State.Buttons, Gamepad_RStick, buttonState);
                    break;
                default:
                    return;
            }
        }
        else if (usagePage == kHIDPage_GenericDesktop)
        {
            float v;
            switch(usage)
            {
                case kHIDUsage_GD_X:
                    v = mapAnalogAxis(value, element);
                    if (!setStateIfDifferent(State.LX, v))
                        return;
                    break;
                case kHIDUsage_GD_Y:
                    v = mapAnalogAxis(value, element);
                    if (!setStateIfDifferent(State.LY, -v))
                        return;
                    break;
                case kHIDUsage_GD_Z:
                    v = mapAnalogAxis(value, element);
                    if (!setStateIfDifferent(State.RX, v))
                        return;
                    break;
                case kHIDUsage_GD_Rz:
                    v = mapAnalogAxis(value, element);
                    if (!setStateIfDifferent(State.RY, -v))
                        return;
                    break;
                case kHIDUsage_GD_Hatswitch:
                    {
                        CFIndex integerValue = IOHIDValueGetIntegerValue(value);
                 
                        manipulateBitField(State.Buttons,
                                           Gamepad_Up,
                                           integerValue == 7 || integerValue == 0 || integerValue == 1);
                        manipulateBitField(State.Buttons,
                                           Gamepad_Down,
                                           integerValue == 3 || integerValue == 4 || integerValue == 5);
                        manipulateBitField(State.Buttons,
                                           Gamepad_Left,
                                           integerValue == 5 || integerValue == 6 || integerValue == 7);
                        manipulateBitField(State.Buttons,
                                           Gamepad_Right,
                                           integerValue == 1 || integerValue == 2 || integerValue == 3);
                    }
                    break;
                default:
                    return;
            }
        }
    }
    // The following controller mapping is based on the Sony DualShock3, however we use it for
    // all Sony devices on the assumption that they're likely to share the same mapping.
    else if (vendorID == Sony_DualShock3_VendorID)
    {
        // PS3 Controller.
        if (usagePage == kHIDPage_Button)
        {
            bool buttonState = IOHIDValueGetIntegerValue(value);
            
            switch(usage)
            {
                case kHIDUsage_Button_1:
                    manipulateBitField(State.Buttons, Gamepad_Back, buttonState);
                    break;
                case kHIDUsage_Button_2:
                    manipulateBitField(State.Buttons, Gamepad_LStick, buttonState);
                    break;
                case kHIDUsage_Button_3:
                    manipulateBitField(State.Buttons, Gamepad_RStick, buttonState);
                    break;
                case kHIDUsage_Button_4:
                    manipulateBitField(State.Buttons, Gamepad_Start, buttonState);
                    break;
                case 0x05:
                    manipulateBitField(State.Buttons, Gamepad_Up, buttonState);
                    break;
                case 0x06:
                    manipulateBitField(State.Buttons, Gamepad_Right, buttonState);
                    break;
                case 0x07:
                    manipulateBitField(State.Buttons, Gamepad_Down, buttonState);
                    break;
                case 0x08:
                    manipulateBitField(State.Buttons, Gamepad_Left, buttonState);
                    break;
                case 0x09:
                    State.LT = buttonState ? 1.0f:0.0f;
                    break;
                case 0x0A:
                    State.RT = buttonState ? 1.0f:0.0f;
                    break;
                case 0x0B:
                    manipulateBitField(State.Buttons, Gamepad_L1, buttonState);
                    break;
                case 0x0C:
                    manipulateBitField(State.Buttons, Gamepad_R1, buttonState);
                    break;
                case 0x0D:
                    // PS3 Triangle.
                    manipulateBitField(State.Buttons, Gamepad_TRIANGLE, buttonState);
                    break;
                case 0x0E:
                    // PS3 Circle
                    manipulateBitField(State.Buttons, Gamepad_CIRCLE, buttonState);
                    break;
                case 0x0F:
                    // PS3 Cross
                    manipulateBitField(State.Buttons, Gamepad_CROSS, buttonState);
                    break;
                case 0x10:
                    // PS3 Square
                    manipulateBitField(State.Buttons, Gamepad_SQUARE, buttonState);
                    break;
                default:
                    return;
            }
        }
        else if (usagePage == kHIDPage_GenericDesktop)
        {
            float v;
            switch(usage)
            {
                case kHIDUsage_GD_X:
                    v = mapAnalogAxis(value, element);
                    if (!setStateIfDifferent(State.LX, v))
                        return;
                    break;
                case kHIDUsage_GD_Y:
                    v = mapAnalogAxis(value, element);
                    if (!setStateIfDifferent(State.LY, -v))
                        return;
                    break;
                case kHIDUsage_GD_Z:
                    v = mapAnalogAxis(value, element);
                    if (!setStateIfDifferent(State.RX, v))
                        return;
                    break;
                case kHIDUsage_GD_Rz:
                    v = mapAnalogAxis(value, element);
                    if (!setStateIfDifferent(State.RY, -v))
                        return;
                    break;
                default:
                    return;
            }
        }
    }
    
    bStateChanged = true;
}
示例#24
0
void __deviceValueCallback (void * context, IOReturn result, void * sender, IOHIDValueRef value)
{
    IOHIDElementRef element = IOHIDValueGetElement(value);
    
    printf("IOHIDDeviceRef[%p]: value=%p timestamp=%lld cookie=%d usagePage=0x%02X usage=0x%02X intValue=%ld\n", sender, value, IOHIDValueGetTimeStamp(value), (uint32_t)IOHIDElementGetCookie(element), IOHIDElementGetUsagePage(element), IOHIDElementGetUsage(element), IOHIDValueGetIntegerValue(value));
}
示例#25
0
static void iohidmanager_hid_device_input_callback(void *data, IOReturn result,
      void* sender, IOHIDValueRef value)
{
   iohidmanager_hid_t *hid                  = (iohidmanager_hid_t*)hid_driver_get_data();
   struct iohidmanager_hid_adapter *adapter = (struct iohidmanager_hid_adapter*)data;
   IOHIDElementRef element                  = IOHIDValueGetElement(value);
   uint32_t type                            = (uint32_t)IOHIDElementGetType(element);
   uint32_t page                            = (uint32_t)IOHIDElementGetUsagePage(element);
   uint32_t use                             = (uint32_t)IOHIDElementGetUsage(element);
   uint32_t cookie                          = (uint32_t)IOHIDElementGetCookie(element);
   apple_input_rec_t *tmp                   = NULL;

   if (type != kIOHIDElementTypeInput_Misc)
      if (type != kIOHIDElementTypeInput_Button)
         if (type != kIOHIDElementTypeInput_Axis)
            return;

   /* Joystick handler.
    * TODO: Can GamePad work the same? */

   int pushed_button = 0;

   switch (page)
   {
      case kHIDPage_GenericDesktop:
         switch (type)
         {
            case kIOHIDElementTypeInput_Misc:
               switch (use)
               {
                  case kHIDUsage_GD_Hatswitch:
                     {
                        tmp = adapter->hats;

                        while(tmp && tmp->cookie != (IOHIDElementCookie)cookie)
                           tmp = tmp->next;

                        if(tmp->cookie == (IOHIDElementCookie)cookie)
                        {
                           CFIndex range = IOHIDElementGetLogicalMax(element) - IOHIDElementGetLogicalMin(element);
                           CFIndex val   = IOHIDValueGetIntegerValue(value);

                           if(range == 3)
                              val *= 2;

                           switch(val)
                           {
                              case 0:
                                 /* pos = up */
                                 hid->hats[adapter->slot][0] = 0;
                                 hid->hats[adapter->slot][1] = -1;
                                 break;
                              case 1:
                                 /* pos = up+right */
                                 hid->hats[adapter->slot][0] = 1;
                                 hid->hats[adapter->slot][1] = -1;
                                 break;
                              case 2:
                                 /* pos = right */
                                 hid->hats[adapter->slot][0] = 1;
                                 hid->hats[adapter->slot][1] = 0;
                                 break;
                              case 3:
                                 /* pos = down+right */
                                 hid->hats[adapter->slot][0] = 1;
                                 hid->hats[adapter->slot][1] = 1;
                                 break;
                              case 4:
                                 /* pos = down */
                                 hid->hats[adapter->slot][0] = 0;
                                 hid->hats[adapter->slot][1] = 1;
                                 break;
                              case 5:
                                 /* pos = down+left */
                                 hid->hats[adapter->slot][0] = -1;
                                 hid->hats[adapter->slot][1] = 1;
                                 break;
                              case 6:
                                 /* pos = left */
                                 hid->hats[adapter->slot][0] = -1;
                                 hid->hats[adapter->slot][1] = 0;
                                 break;
                              case 7:
                                 /* pos = up_left */
                                 hid->hats[adapter->slot][0] = -1;
                                 hid->hats[adapter->slot][1] = -1;
                                 break;
                              default:
                                 /* pos = centered */
                                 hid->hats[adapter->slot][0] = 0;
                                 hid->hats[adapter->slot][1] = 0;
                                 break;
                           }
                        }
                     }
                     break;
                  default:
                     tmp = adapter->axes;

                     while(tmp && tmp->cookie != (IOHIDElementCookie)cookie)
                        tmp = tmp->next;

                     if (tmp)
                     {
                        if(tmp->cookie == (IOHIDElementCookie)cookie)
                        {
                           CFIndex min   = IOHIDElementGetPhysicalMin(element);
                           CFIndex state = IOHIDValueGetIntegerValue(value) - min;
                           CFIndex max   = IOHIDElementGetPhysicalMax(element) - min;
                           float val     = (float)state / (float)max;

                           hid->axes[adapter->slot][tmp->id] =
                              ((val * 2.0f) - 1.0f) * 32767.0f;
                        }
                     }
                     else
                        pushed_button = 1;
                     break;
               }
               break;
         }
         break;
      case kHIDPage_Consumer:
      case kHIDPage_Button:
         switch (type)
         {
            case kIOHIDElementTypeInput_Misc:
            case kIOHIDElementTypeInput_Button:
               pushed_button = 1;
               break;
         }
         break;
   }

   if (pushed_button)
   {
      tmp = adapter->buttons;

      uint8_t bit = 0;
      while(tmp && tmp->cookie != (IOHIDElementCookie)cookie)
      {
         bit++;
         tmp = tmp->next;
      }

      if(tmp && tmp->cookie == (IOHIDElementCookie)cookie)
      {
         CFIndex state = IOHIDValueGetIntegerValue(value);
         if (state)
            BIT64_SET(hid->buttons[adapter->slot], bit);
         else
            BIT64_CLEAR(hid->buttons[adapter->slot], bit);
      }
   }
}
示例#26
0
static void apple_hid_device_input_callback(void *data, IOReturn result,
      void* sender, IOHIDValueRef value)
{
   driver_t                  *driver = driver_get_ptr();
   apple_input_data_t         *apple = (apple_input_data_t*)driver->input_data;
   struct apple_hid_adapter *adapter = (struct apple_hid_adapter*)data;
   IOHIDElementRef element           = IOHIDValueGetElement(value);
   uint32_t type                     = IOHIDElementGetType(element);
   uint32_t page                     = IOHIDElementGetUsagePage(element);
   uint32_t use                      = IOHIDElementGetUsage(element);

   if (type != kIOHIDElementTypeInput_Misc)
      if (type != kIOHIDElementTypeInput_Button)
         if (type != kIOHIDElementTypeInput_Axis)
            return;

   /* Joystick handler.
    * TODO: Can GamePad work the same? */

   switch (page)
   {
      case kHIDPage_GenericDesktop:
         switch (type)
         {
            case kIOHIDElementTypeInput_Misc:
               switch (use)
               {
                  case kHIDUsage_GD_Hatswitch:
                     break;
                  default:
                     {
                        int i;
                        static const uint32_t axis_use_ids[4] = { 48, 49, 50, 53 };

                        for (i = 0; i < 4; i ++)
                        {
                           CFIndex min   = IOHIDElementGetPhysicalMin(element);
                           CFIndex max   = IOHIDElementGetPhysicalMax(element) - min;
                           CFIndex state = IOHIDValueGetIntegerValue(value) - min;
                           float val     = (float)state / (float)max;

                           if (use != axis_use_ids[i])
                              continue;

                           apple->axes[adapter->slot][i] =
                              ((val * 2.0f) - 1.0f) * 32767.0f;
                        }
                     }
                     break;
               }
               break;
         }
         break;
      case kHIDPage_Button:
         switch (type)
         {
            case kIOHIDElementTypeInput_Button:
               {
                  CFIndex state = IOHIDValueGetIntegerValue(value);
                  unsigned id = use - 1;

                  if (state)
                     BIT64_SET(apple->buttons[adapter->slot], id);
                  else
                     BIT64_CLEAR(apple->buttons[adapter->slot], id);
               }
               break;
         }
         break;
   }
}
示例#27
0
/**************************************************************************
 *                              driver_joyGetPosEx
 */
LRESULT driver_joyGetPosEx(DWORD_PTR device_id, JOYINFOEX* info)
{
    static const struct {
        DWORD flag;
        off_t offset;
    } axis_map[NUM_AXES] = {
        { JOY_RETURNX, FIELD_OFFSET(JOYINFOEX, dwXpos) },
        { JOY_RETURNY, FIELD_OFFSET(JOYINFOEX, dwYpos) },
        { JOY_RETURNZ, FIELD_OFFSET(JOYINFOEX, dwZpos) },
        { JOY_RETURNU, FIELD_OFFSET(JOYINFOEX, dwUpos) },
        { JOY_RETURNV, FIELD_OFFSET(JOYINFOEX, dwVpos) },
        { JOY_RETURNR, FIELD_OFFSET(JOYINFOEX, dwRpos) },
    };

    joystick_t* joystick;
    IOHIDDeviceRef device;
    CFIndex i, count;
    IOHIDValueRef valueRef;
    long value;

    if ((joystick = joystick_from_id(device_id)) == NULL)
        return MMSYSERR_NODRIVER;

    if (!open_joystick(joystick))
        return JOYERR_PARMS;

    device = IOHIDElementGetDevice(joystick->element);

    if (info->dwFlags & JOY_RETURNBUTTONS)
    {
        info->dwButtons = 0;
        info->dwButtonNumber = 0;

        count = CFArrayGetCount(joystick->buttons);
        for (i = 0; i < count; i++)
        {
            IOHIDElementRef button = (IOHIDElementRef)CFArrayGetValueAtIndex(joystick->buttons, i);
            IOHIDDeviceGetValue(device, button, &valueRef);
            value = IOHIDValueGetIntegerValue(valueRef);
            if (value)
            {
                info->dwButtons |= 1 << i;
                if (!info->dwButtonNumber)
                    info->dwButtonNumber = i + 1;
            }
        }
    }

    for (i = 0; i < NUM_AXES; i++)
    {
        if (info->dwFlags & axis_map[i].flag)
        {
            DWORD* field = (DWORD*)((char*)info + axis_map[i].offset);
            if (joystick->axes[i].element)
            {
                IOHIDDeviceGetValue(device, joystick->axes[i].element, &valueRef);
                value = IOHIDValueGetIntegerValue(valueRef) - joystick->axes[i].min_value;
                *field = MulDiv(value, 0xFFFF, joystick->axes[i].max_value - joystick->axes[i].min_value);
            }
            else
            {
                *field = 0;
                info->dwFlags &= ~axis_map[i].flag;
            }
        }
    }

    if (info->dwFlags & JOY_RETURNPOV)
    {
        if (joystick->hatswitch)
        {
            IOHIDDeviceGetValue(device, joystick->hatswitch, &valueRef);
            value = IOHIDValueGetIntegerValue(valueRef);
            if (value >= 8)
                info->dwPOV = JOY_POVCENTERED;
            else
                info->dwPOV = value * 4500;
        }
        else
        {
            info->dwPOV = 0;
            info->dwFlags &= ~JOY_RETURNPOV;
        }
    }

    TRACE("x: %d, y: %d, z: %d, r: %d, u: %d, v: %d, buttons: 0x%04x, pov %d, flags: 0x%04x\n",
          info->dwXpos, info->dwYpos, info->dwZpos, info->dwRpos, info->dwUpos, info->dwVpos, info->dwButtons, info->dwPOV, info->dwFlags);

    return JOYERR_NOERROR;
}
示例#28
0
void Burger::Mouse::InputCallback(void *pData, int iReturn,void * /* pSender */,IOHIDValueRef pValue)
{
	if (iReturn == kIOReturnSuccess) {
		Mouse *pMouse = static_cast<Mouse *>(pData);
		Word uCount = pMouse->m_uMiceCount;
		if (uCount) {
			IOHIDElementRef pElement = IOHIDValueGetElement(pValue);
			IOHIDDeviceRef pDevice = IOHIDElementGetDevice(pElement);
#if 0
			Word uRatNumber = BURGER_MAXUINT;
			const DeviceStruct *pRat = pMouse->m_Mice;
			do {
				if (pRat->m_pDevice == pDevice) {
					uRatNumber = pMouse->m_uMiceCount-uCount;
					break;
				}
				++pRat;
			} while (--uCount);
			if (uRatNumber==BURGER_MAXUINT) {
			}
#endif
			Word32 uTime = static_cast<Word32>(IOHIDValueGetTimeStamp(pValue));
			CFIndex iValue = IOHIDValueGetIntegerValue(pValue);
			
			uint32_t uPage = IOHIDElementGetUsagePage(pElement);
			uint32_t uUsage = IOHIDElementGetUsage(pElement);
			switch (uPage) {
			case kHIDPage_GenericDesktop:
				if (iValue) {
					switch (uUsage) {
					case kHIDUsage_GD_X:
						pMouse->PostMouseMotion(static_cast<Int32>(iValue),0,uTime);
						break;
					case kHIDUsage_GD_Y:
						pMouse->PostMouseMotion(0,static_cast<Int32>(iValue),uTime);
						break;
					case kHIDUsage_GD_Wheel:
						pMouse->PostMouseWheel(0,static_cast<Int32>(iValue),uTime);
						break;
					default:
						printf("Unknown usage %u\n",uUsage);
						break;
					}
				}
				break;
			case kHIDPage_Button:
				// iValue == down
				// Usage = which 1.2.3.4
				if (iValue) {
					pMouse->PostMouseDown(1<<(uUsage-1));
				} else {
					pMouse->PostMouseUp(1<<(uUsage-1));
				}
				break;
				// Ignore this one
			case kHIDPage_Consumer:
				break;
			default:
				printf("Unknown page found %u\n",uPage);
				break;
			}
		}
	}
}
示例#29
0
static void iohidmanager_hid_device_input_callback(void *data, IOReturn result,
      void* sender, IOHIDValueRef value)
{
   iohidmanager_hid_t *hid = (iohidmanager_hid_t*)hid_driver_get_data();
   struct iohidmanager_hid_adapter *adapter = (struct iohidmanager_hid_adapter*)data;
   IOHIDElementRef element           = IOHIDValueGetElement(value);
   uint32_t type                     = IOHIDElementGetType(element);
   uint32_t page                     = IOHIDElementGetUsagePage(element);
   uint32_t use                      = IOHIDElementGetUsage(element);

   if (type != kIOHIDElementTypeInput_Misc)
      if (type != kIOHIDElementTypeInput_Button)
         if (type != kIOHIDElementTypeInput_Axis)
            return;

   /* Joystick handler.
    * TODO: Can GamePad work the same? */

   switch (page)
   {
      case kHIDPage_GenericDesktop:
         switch (type)
         {
            case kIOHIDElementTypeInput_Misc:
               switch (use)
               {
                  case kHIDUsage_GD_Hatswitch:
                     break;
                  default:
                     {
                        int i;
                        // +0/-0   =>   Left Stick Horizontal       => 48
                        // +1/-1   =>   Left Stick Vertical         => 49
                        // +2/-2   =>   Right Stick Horizontal      => 51
                        // +3/-3   =>   Right Stick Vertical        => 52
                        // +4/-4   =>   Left Trigger (if exists)    => 50
                        // +5/-5   =>   Right Trigger (if exists)   => 53
                        static const uint32_t axis_use_ids[6] = { 48, 49, 51, 52, 50, 53 };

                        for (i = 0; i < 6; i ++)
                        {
                           CFIndex min   = IOHIDElementGetPhysicalMin(element);
                           CFIndex state = IOHIDValueGetIntegerValue(value) - min;
                           CFIndex max   = IOHIDElementGetPhysicalMax(element) - min;
                           float val     = (float)state / (float)max;

                           if (use != axis_use_ids[i])
                              continue;

                           hid->axes[adapter->slot][i] =
                              ((val * 2.0f) - 1.0f) * 32767.0f;
                        }
                     }
                     break;
               }
               break;
         }
         break;
      case kHIDPage_Button:
         switch (type)
         {
            case kIOHIDElementTypeInput_Button:
               {
                  CFIndex state = IOHIDValueGetIntegerValue(value);
                  unsigned   id = use - 1;

                  if (state)
                     BIT64_SET(hid->buttons[adapter->slot], id);
                  else
                     BIT64_CLEAR(hid->buttons[adapter->slot], id);
               }
               break;
         }
         break;
   }
}