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; }
void HIDGamepad::getCurrentValueForElement(const HIDGamepadElement& gamepadElement) { IOHIDElementRef element = gamepadElement.iohidElement.get(); IOHIDValueRef value; if (IOHIDDeviceGetValue(IOHIDElementGetDevice(element), element, &value) == kIOReturnSuccess) valueChanged(value); }
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; }
// ************************************************************************* // // IOHIDElement_GetValue(inIOHIDElementRef, inIOHIDValueScaleType) // // Purpose: returns the current value for an element(polling) // // Notes: will return 0 on error conditions which should be accounted for by application // // Inputs: inIOHIDElementRef - the element // inIOHIDValueScaleType - scale type (calibrated or physical) // // Returns: double - current value for element // double IOHIDElement_GetValue(IOHIDElementRef inIOHIDElementRef, IOHIDValueScaleType inIOHIDValueScaleType) { double result = NAN; IOHIDValueRef tIOHIDValueRef; if (kIOReturnSuccess == IOHIDDeviceGetValue(IOHIDElementGetDevice(inIOHIDElementRef), inIOHIDElementRef, &tIOHIDValueRef)) { result = IOHIDValueGetScaledValue(tIOHIDValueRef, inIOHIDValueScaleType); } return (result); } // IOHIDElement_GetValue
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, ¤tValue) == 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"); }
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; }
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; } }
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; } } }
unsigned char HIDConfigureSingleDeviceAction(IOHIDDeviceRef inIOHIDDeviceRef, IOHIDElementRef * outIOHIDElementRef, double timeout) { if (!inIOHIDDeviceRef) { return (0); } if (0 == HIDHaveDeviceList()) { // if we do not have a device list return (0); // return 0 } Boolean found = false; // build list of device and elements to save current values CFIndex maxElements = HIDCountDeviceElements(inIOHIDDeviceRef, kHIDElementTypeInput); double *saveValueArray = (double *) calloc(maxElements, sizeof(double)); // 2D array to save values // store initial values on first pass / compare to initial value on subsequent passes Boolean first = true; // get all the elements from this device CFArrayRef elementCFArrayRef = IOHIDDeviceCopyMatchingElements(inIOHIDDeviceRef, NULL, kIOHIDOptionsTypeNone); // if that worked... if (elementCFArrayRef) { clock_t start = clock(), end; // poll all devices and elements while (!found) { uint32_t currElementIndex = 0; CFIndex idx, cnt = CFArrayGetCount(elementCFArrayRef); for (idx = 0; idx < cnt; idx++) { *outIOHIDElementRef = (IOHIDElementRef) CFArrayGetValueAtIndex(elementCFArrayRef, idx); if (!*outIOHIDElementRef) { continue; } // is this an input element? IOHIDElementType type = IOHIDElementGetType(*outIOHIDElementRef); switch (type) { // these types are inputs case kIOHIDElementTypeInput_Misc: case kIOHIDElementTypeInput_Button: case kIOHIDElementTypeInput_Axis: case kIOHIDElementTypeInput_ScanCodes: default: { break; } case kIOHIDElementTypeOutput: case kIOHIDElementTypeFeature: case kIOHIDElementTypeCollection: { *outIOHIDElementRef = NULL; // these types are not (Skip them) break; } } /* switch */ if (!*outIOHIDElementRef) { continue; // skip this element } // get this elements current value double value = 0; // default value is zero IOHIDValueRef tIOHIDValueRef; IOReturn ioReturn = IOHIDDeviceGetValue(inIOHIDDeviceRef, *outIOHIDElementRef, &tIOHIDValueRef); if (kIOReturnSuccess == ioReturn) { value = IOHIDValueGetScaledValue(tIOHIDValueRef, kIOHIDValueScaleTypePhysical); } if (first) { saveValueArray[currElementIndex] = value; } else { CFIndex min = IOHIDElementGetLogicalMin(*outIOHIDElementRef); CFIndex max = IOHIDElementGetLogicalMax(*outIOHIDElementRef); double initialValue = saveValueArray[currElementIndex]; double delta = (double) (max - min) * kPercentMove * 0.01f; // is the new value within +/- delta of the initial value? if (((initialValue + delta) < value) || ((initialValue - delta) > value)) { found = 1; // (yes!) mark as found break; } } // if (first) currElementIndex++; // bump element index } // next idx if (first) { first = false; // no longer the first pass } else { // are we done? end = clock(); double secs = (double) (end - start) / CLOCKS_PER_SEC; if (secs > timeout) { break; // (yes) timeout } } } // while (!found) CFRelease(elementCFArrayRef); } // if (elementCFArrayRef) if (saveValueArray) { free(saveValueArray); } // return device and element moved if (found) { return (1); } else { *outIOHIDElementRef = NULL; return (0); } } // HIDConfigureSingleDeviceAction
// ************************************************************************* // // HIDConfigureAction(outIOHIDDeviceRef, outIOHIDElementRef, inTimeout) // // Purpose: polls all devices and elements for a change greater than kPercentMove. // Times out after given time returns 1 and pointer to device and element // if found; returns 0 and NULL for both parameters if not found // // Inputs: outIOHIDDeviceRef - address where to store the device // outIOHIDElementRef - address where to store the element // inTimeout - the timeout // Returns: Boolean - if successful // outIOHIDDeviceRef - the device // outIOHIDElementRef - the element // Boolean HIDConfigureActionOfType(actionTypeMask inActionTypeMask, double inTimeout, IOHIDDeviceRef * outIOHIDDeviceRef, IOHIDElementRef * outIOHIDElementRef) { // param error? if (!outIOHIDDeviceRef || !outIOHIDElementRef) { return (false); } if (!gDeviceCFArrayRef) { // if we do not have a device list // and we can't build another list if (!HIDBuildDeviceList(0, 0) || !gDeviceCFArrayRef) { return (false); // bail } } IOHIDDeviceRef tIOHIDDeviceRef; IOHIDElementRef tIOHIDElementRef; IOHIDElementType elementType = 0; switch (inActionTypeMask) { case kActionTypeButton: { elementType = kIOHIDElementTypeInput_Button; break; } case kActionTypeAxis: { elementType = kIOHIDElementTypeInput_Misc; break; } case kActionTypeAll: default: { elementType = 0; break; } } // switch // determine the maximum number of elements CFIndex maxElements = 0; CFIndex devIndex, devCount = CFArrayGetCount(gDeviceCFArrayRef); for (devIndex = 0; devIndex < devCount; devIndex++) { tIOHIDDeviceRef = (IOHIDDeviceRef) CFArrayGetValueAtIndex(gDeviceCFArrayRef, devIndex); if (!tIOHIDDeviceRef) { continue; // skip this one } // HIDDumpDeviceInfo(tIOHIDDeviceRef); CFIndex count = HIDCountDeviceElementsOfType(tIOHIDDeviceRef, elementType); if (count > maxElements) { maxElements = count; } } if (!(devCount * maxElements)) { return (false); } #if true // NSDictionary * matchDictionary = @{@(kIOHIDElementTypeKey): @(elementType)}; const void *keys[] = {CFSTR(kIOHIDElementTypeKey)}; const void *vals[] = {CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &elementType)}; CFDictionaryRef matchingDict = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFRelease(vals[0]); #endif // if 1 // allocate an array of int's in which to store devCount * maxElements values double *saveValueArray = (double *) calloc(devCount * maxElements, sizeof(double)); // clear 2D array to save values // remember when we start; used to calculate timeout clock_t start = clock(), end; // on first pass store initial values / compare current values to initial values on subsequent passes Boolean found = false, first = true; while (!found) { double maxDeltaPercent = 0; // we want to find the one that moves the most // (percentage wise) for (devIndex = 0; devIndex < devCount; devIndex++) { tIOHIDDeviceRef = (IOHIDDeviceRef) CFArrayGetValueAtIndex(gDeviceCFArrayRef, devIndex); if (!tIOHIDDeviceRef) { continue; // skip this one } gElementCFArrayRef = IOHIDDeviceCopyMatchingElements(tIOHIDDeviceRef, matchingDict, kIOHIDOptionsTypeNone); if (gElementCFArrayRef) { CFIndex eleIndex, eleCount = CFArrayGetCount(gElementCFArrayRef); for (eleIndex = 0; eleIndex < eleCount; eleIndex++) { tIOHIDElementRef = (IOHIDElementRef) CFArrayGetValueAtIndex(gElementCFArrayRef, eleIndex); if (!tIOHIDElementRef) { continue; } IOHIDElementType tIOHIDElementType = IOHIDElementGetType(tIOHIDElementRef); // only care about inputs (no outputs or features) if (tIOHIDElementType <= kIOHIDElementTypeInput_ScanCodes) { if (IOHIDElementIsArray(tIOHIDElementRef)) { // printf("ARRAY!\n"); continue; // skip array elements } if (elementType && ((tIOHIDElementType != elementType))) { continue; } uint32_t usagePage = IOHIDElementGetUsagePage(tIOHIDElementRef); uint32_t usage = IOHIDElementGetUsage(tIOHIDElementRef); uint32_t reportCount = IOHIDElementGetReportCount(tIOHIDElementRef); #ifdef DEBUG if (first) { HIDDumpElementInfo(tIOHIDElementRef); fflush(stdout); uint32_t vendorID = IOHIDDevice_GetVendorID(tIOHIDDeviceRef); uint32_t productID = IOHIDDevice_GetProductID(tIOHIDDeviceRef); IOHIDElementCookie cookie = IOHIDElementGetCookie(tIOHIDElementRef); if ((0x054C == vendorID) && (0x0268 == productID) && (0x001E == (uint32_t) cookie)) { // printf("DING!\n"); } } #endif // ifdef DEBUG #if true // work-around for IOHIDValueGetScaledValue crash // (when element report count > 1) if (reportCount > 1) { // printf("REPORT!\n"); continue; // skip reports } #endif // if 1 // ignore PID elements and arrays if ((kHIDPage_PID != usagePage) && ((-1) != usage)) { // get this elements current value double value = 0.0; // default value is zero IOHIDValueRef tIOHIDValueRef; IOReturn ioReturn = IOHIDDeviceGetValue(tIOHIDDeviceRef, tIOHIDElementRef, &tIOHIDValueRef); if (kIOReturnSuccess == ioReturn) { value = IOHIDValueGetScaledValue(tIOHIDValueRef, kIOHIDValueScaleTypePhysical); } if (first) { saveValueArray[(devIndex * maxElements) + eleIndex] = value; } else { double initialValue = saveValueArray[(devIndex * maxElements) + eleIndex]; CFIndex valueMin = IOHIDElementGetPhysicalMin(tIOHIDElementRef); CFIndex valueMax = IOHIDElementGetPhysicalMax(tIOHIDElementRef); double deltaPercent = fabs((initialValue - value) * 100.0 / (valueMax - valueMin)); #if false // debug code useful to dump out value info for // specific (vendorID, productID, usagePage and // usage) device if (!first) { // Device: 0x13b6a0 = { Logitech Inc. - WingMan Force 3D, vendorID: 0x046D, productID: 0xC283, // usage: 0x0001:0x0004, "Generic Desktop Joystick" if ((vendorID == 0x046D) && (productID == 0xC283)) { if ((kHIDPage_GenericDesktop == usagePage) && (kHIDUsage_GD_Rz == usage)) { printf("initial: %6.2f, value: %6.2f, diff: %6.2f, delta percent: %6.2f!\n", initialValue, value, fabs(initialValue - value), deltaPercent); } } } deltaPercent = 0.0; #endif // if false if (deltaPercent >= kPercentMove) { found = true; if (deltaPercent > maxDeltaPercent) { maxDeltaPercent = deltaPercent; *outIOHIDDeviceRef = tIOHIDDeviceRef; *outIOHIDElementRef = tIOHIDElementRef; } break; } } // if first } // if usage } // if type } // for elements... CFRelease(gElementCFArrayRef); gElementCFArrayRef = NULL; } // if (gElementCFArrayRef) if (found) { // HIDDumpElementInfo(tIOHIDElementRef); break; // DONE! } } // for devices first = false; // no longer the first pass // are we done? end = clock(); double secs = (double) (end - start) / CLOCKS_PER_SEC; if (secs > inTimeout) { break; // (yes) timeout } } // while (!found) if (saveValueArray) { free(saveValueArray); } // return device and element moved if (!found) { *outIOHIDDeviceRef = NULL; *outIOHIDElementRef = NULL; } CFRelease(matchingDict); return (found); } // HIDConfigureAction
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; }
Boolean HIDConfigureAction( IOHIDDeviceRef* outIOHIDDeviceRef, IOHIDElementRef *outIOHIDElementRef, float inTimeout ) { // param error? if ( !outIOHIDDeviceRef || !outIOHIDElementRef ) { return 0; } if ( !gDeviceCFArrayRef ) { // if we do not have a device list // and we can't build another list if ( !HIDBuildDeviceList( 0, 0 ) || !gDeviceCFArrayRef ) { return FALSE; // bail } } IOHIDDeviceRef tIOHIDDeviceRef; IOHIDElementRef tIOHIDElementRef; // remember when we start; used to calculate timeout clock_t start = clock(), end; // determine the maximum number of elements CFIndex maxElements = 0; CFIndex devIndex, devCount = CFArrayGetCount( gDeviceCFArrayRef ); for ( devIndex = 0; devIndex < devCount; devIndex++ ) { tIOHIDDeviceRef = ( IOHIDDeviceRef ) CFArrayGetValueAtIndex( gDeviceCFArrayRef, devIndex ); if ( !tIOHIDDeviceRef ) { continue; // skip this one } UInt32 count = HIDCountDeviceElements( tIOHIDDeviceRef, kHIDElementTypeInput ); if ( count > maxElements ) { maxElements = count; } } // allocate an array of int's in which to store devCount * maxElements values double* saveValueArray = ( double * ) calloc( devCount * maxElements, sizeof( double ) ); // clear 2D array to save values // on first pass store initial values / compare current values to initial values on subsequent passes Boolean found = FALSE, first = TRUE; while ( !found ) { double maxDeltaPercent = 0; // we want to find the one that moves the most ( percentage wise ) for ( devIndex = 0; devIndex < devCount; devIndex++ ) { IOHIDDeviceRef tIOHIDDeviceRef = ( IOHIDDeviceRef ) CFArrayGetValueAtIndex( gDeviceCFArrayRef, devIndex ); if ( !tIOHIDDeviceRef ) { continue; // skip this one } #ifdef DEBUG long vendorID = IOHIDDevice_GetVendorID( tIOHIDDeviceRef ); long productID = IOHIDDevice_GetProductID( tIOHIDDeviceRef ); #endif gElementCFArrayRef = IOHIDDeviceCopyMatchingElements( tIOHIDDeviceRef, NULL, kIOHIDOptionsTypeNone ); if ( gElementCFArrayRef ) { CFIndex eleIndex, eleCount = CFArrayGetCount( gElementCFArrayRef ); for ( eleIndex = 0; eleIndex < eleCount; eleIndex++ ) { tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( gElementCFArrayRef, eleIndex ); if ( !tIOHIDElementRef ) { continue; } IOHIDElementType tIOHIDElementType = IOHIDElementGetType( tIOHIDElementRef ); // only care about inputs (no outputs or features) if ( tIOHIDElementType <= kIOHIDElementTypeInput_ScanCodes ) { if ( IOHIDElementIsArray( tIOHIDElementRef ) ) { //printf( "ARRAY!\n" ); continue; // skip array elements } uint32_t usagePage = IOHIDElementGetUsagePage( tIOHIDElementRef ); uint32_t usage = IOHIDElementGetUsage( tIOHIDElementRef ); uint32_t reportCount = IOHIDElementGetReportCount( tIOHIDElementRef ); #ifdef DEBUG if ( first ) { IOHIDElementCookie cookie = IOHIDElementGetCookie( tIOHIDElementRef ); printf( "%s, dev: {ref:%p, ven: 0x%08lX, pro: 0x%08lX}, ele: {ref:%p, cookie: %p, usage:%04lX:%08lX}\n", __PRETTY_FUNCTION__, tIOHIDDeviceRef, vendorID, productID, tIOHIDElementRef, cookie, (long unsigned int) usagePage, (long unsigned int) usage ); fflush( stdout ); if ( ( 0x054C == vendorID ) && ( 0x0268 == productID ) && ( 0x001E == (UInt32) cookie ) ) { //printf( "DING!\n" ); } } #endif #if 1 // work-around for IOHIDValueGetScaledValue crash (when element report count > 1) if ( reportCount > 1 ) { //printf( "REPORT!\n" ); continue; // skip reports } #endif // ignore PID elements and arrays if ( ( kHIDPage_PID != usagePage ) && ( -1 != usage ) ) { // get this elements current value double value = 0.0; // default value is zero IOHIDValueRef tIOHIDValueRef; IOReturn ioReturn = IOHIDDeviceGetValue( tIOHIDDeviceRef, tIOHIDElementRef, &tIOHIDValueRef ); if ( kIOReturnSuccess == ioReturn ) { value = IOHIDValueGetScaledValue( tIOHIDValueRef, kIOHIDValueScaleTypePhysical ); } if ( first ) { saveValueArray[( devIndex * maxElements ) + eleIndex] = value; } else { double initialValue = saveValueArray[( devIndex * maxElements ) + eleIndex]; CFIndex valueMin = IOHIDElementGetPhysicalMin( tIOHIDElementRef ); CFIndex valueMax = IOHIDElementGetPhysicalMax( tIOHIDElementRef ); double deltaPercent = fabs( ( initialValue - value ) * 100.0 / (valueMax - valueMin) ); #if 0 if ( !first ) { // Device: 0x13b6a0 = { Logitech Inc. - WingMan Force 3D, vendorID: 0x046D, productID: 0xC283, usage: 0x0001:0x0004, "Generic Desktop Joystick" if ( ( vendorID == 0x046D ) && ( productID == 0xC283 ) ) { if ( ( kHIDPage_GenericDesktop == usagePage ) && ( kHIDUsage_GD_Rz == usage ) ) { printf( "initial: %6.2f, value: %6.2f, diff: %6.2f, delta percent: %6.2f!\n", initialValue, value, fabs( initialValue - value ), deltaPercent ); } } } deltaPercent = 0.0; #endif if ( deltaPercent >= kPercentMove ) { found = TRUE; if ( deltaPercent > maxDeltaPercent ) { maxDeltaPercent = deltaPercent; *outIOHIDDeviceRef = tIOHIDDeviceRef; *outIOHIDElementRef = tIOHIDElementRef; } break; } } // if first } // if usage } // if type } // for elements... CFRelease( gElementCFArrayRef ); gElementCFArrayRef = NULL; } // if ( gElementCFArrayRef ) if ( found ) { // HIDDumpElementInfo( tIOHIDElementRef ); break; // DONE! } } // for devices first = FALSE; // no longer the first pass // are we done? end = clock(); double secs = (double)( end - start ) / CLOCKS_PER_SEC; if ( secs > inTimeout ) { break; // ( yes ) timeout } } // while ( !found ) // return device and element moved if ( !found ) { *outIOHIDDeviceRef = NULL; *outIOHIDElementRef = NULL; } return found; } // HIDConfigureAction
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); } } } }
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); } } } }
/************************************************************************** * 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; }
void GPUSB_SetBit(int bit, int val) { if (!pGPUSB) return; // no device, bail IOHIDElementRef pCurrentHIDElement = NULL; //IOHIDEventStruct HID_IOEvent; int i; static int bitarray[8]={0,0,0,0,1,1,0,0}; static unsigned char GPUSB_reg = 0x30; if (GPUSB_Model) { // Newer models - use a single byte pCurrentHIDElement = GetFirstOutputElement(pGPUSB); if(pCurrentHIDElement == NULL) { wxMessageBox(std::string(__PRETTY_FUNCTION__) + " Null element"); return; } // HIDTransactionAddElement(pGPUSB,pCurrentHIDElement); unsigned char bmask = 1; bmask = bmask << bit; if (val) { GPUSB_reg = GPUSB_reg | bmask; } else { GPUSB_reg = GPUSB_reg & ~bmask; } //HID_IOEvent.longValueSize = 0; //HID_IOEvent.longValue = nil; /*IOHIDValueRef valueToSend = IOHIDValueCreateWithBytes( kCFAllocatorDefault, pCurrentHIDElement, uint64_t inTimeStamp, &GPUSB_reg, 1); */ //IOHIDElementCookie cookie = IOHIDElementGetCookie(pCurrentHIDElement); IOHIDValueRef valueToSend; IOReturn tIOReturn = IOHIDDeviceGetValue(pGPUSB, pCurrentHIDElement, &valueToSend); if(tIOReturn != kIOReturnSuccess) { CFRelease(pCurrentHIDElement); wxMessageBox(std::string(__PRETTY_FUNCTION__) + " Cannot retrieve value (1)"); return; } assert(IOHIDValueGetLength(valueToSend) == 1); IOHIDValueRef valueToSendCopied = IOHIDValueCreateWithBytes( kCFAllocatorDefault, pCurrentHIDElement, IOHIDValueGetTimeStamp(valueToSend), &GPUSB_reg, 1); tIOReturn = IOHIDDeviceSetValue(pGPUSB, pCurrentHIDElement, valueToSendCopied); if(tIOReturn != kIOReturnSuccess) { CFRelease(pCurrentHIDElement); wxMessageBox(std::string(__PRETTY_FUNCTION__) + " Cannot send value (1)"); return; } //pGPUSB_interface->getElementValue (pGPUSB_interface, cookie, &HID_IOEvent); //HID_IOEvent.value = (SInt32) GPUSB_reg; // wxMessageBox(wxString::Format("%x - %x %x %d %d",foo,GPUSB_reg,bmask,bit,val)); // HID_IOEvent.type = (IOHIDElementType) pCurrentHIDElement->type; //HIDSetElementValue(pGPUSB,pCurrentHIDElement,&HID_IOEvent); // HIDTransactionCommit(pGPUSB); CFRelease(pCurrentHIDElement); } else { // Generic bit-set routine. For older adapters, we can't send a whole // byte and things are setup as SInt32's per bit with 8 bits total... //IOHIDEventStruct hidstruct = {kIOHIDElementTypeOutput}; IOHIDTransactionRef transaction = IOHIDTransactionCreate( kCFAllocatorDefault, pGPUSB, kIOHIDTransactionDirectionTypeOutput, kIOHIDOptionsTypeNone); if(transaction == NULL) { wxMessageBox(std::string(__PRETTY_FUNCTION__) + " Cannot create a transaction"); } bitarray[bit]=val; // std::cout << "Setting to "; for (i=0; i<8; i++) { // write // std::cout << " " << bitarray[i]; if (i==0) { pCurrentHIDElement = GetFirstOutputElement(pGPUSB); } else { pCurrentHIDElement = GetNextOutputElement(pGPUSB, pCurrentHIDElement); } IOHIDValueRef valueToSend; IOReturn tIOReturn = IOHIDDeviceGetValue(pGPUSB, pCurrentHIDElement, &valueToSend); if(tIOReturn != kIOReturnSuccess) { CFRelease(pCurrentHIDElement); wxMessageBox(std::string(__PRETTY_FUNCTION__) + " Cannot retrieve value (1)"); return; } //CFTypeID tID = IOHIDValueGetTypeID(valueToSend); /*IOHIDValueRef valueToSendCopied = IOHIDValueCreateWithBytes( kCFAllocatorDefault, pCurrentHIDElement, IOHIDValueGetTimeStamp(valueToSend), &bitarray[i], sizeof(bitarray[i])); */ IOHIDValueRef valueToSendCopied = IOHIDValueCreateWithIntegerValue( kCFAllocatorDefault, pCurrentHIDElement, IOHIDValueGetTimeStamp(valueToSend), bitarray[i]); IOHIDTransactionAddElement(transaction, pCurrentHIDElement); IOHIDTransactionSetValue(transaction, pCurrentHIDElement, valueToSendCopied, 0); //HIDTransactionAddElement(pGPUSB,pCurrentHIDElement); //hidstruct.type = (IOHIDElementType) pCurrentHIDElement->type; //hidstruct.value = (SInt32) bitarray[i]; //HIDTransactionSetElementValue(pGPUSB,pCurrentHIDElement,&hidstruct); } // std::cout << "\n"; IOHIDTransactionCommit(transaction); } // wxMilliSleep(30); }