Esempio n. 1
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;
}
Esempio n. 2
0
void HIDGamepad::getCurrentValueForElement(const HIDGamepadElement& gamepadElement)
{
    IOHIDElementRef element = gamepadElement.iohidElement.get();
    IOHIDValueRef value;
    if (IOHIDDeviceGetValue(IOHIDElementGetDevice(element), element, &value) == kIOReturnSuccess)
        valueChanged(value);
}
Esempio n. 3
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;
}
Esempio n. 4
0
// *************************************************************************
//
// 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
Esempio n. 5
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");
}
Esempio n. 6
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;
}
Esempio n. 7
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;
    }
}
Esempio n. 8
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;
		}
	}
}
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
Esempio n. 11
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;
}
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
Esempio n. 13
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);
            }
        }
    }
}
Esempio n. 14
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);
            }
        }
    }
}
Esempio n. 15
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;
}
Esempio n. 16
0
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);
}