// creates a queue for a device, creates and opens device interface if required
static IOReturn HIDCreateQueue( IOHIDDeviceRef inIOHIDDeviceRef )
{
	IOReturn result = kIOReturnSuccess;
	
	if ( inIOHIDDeviceRef ) {
		assert( IOHIDDeviceGetTypeID() == CFGetTypeID( inIOHIDDeviceRef ) );
		
		// do we already have a queue?
		IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue( inIOHIDDeviceRef );
		
		if ( tIOHIDQueueRef ) { // (yes)
			assert( IOHIDQueueGetTypeID() == CFGetTypeID( tIOHIDQueueRef ) );
		} else {
			tIOHIDQueueRef = IOHIDQueueCreate( kCFAllocatorDefault, inIOHIDDeviceRef, kDeviceQueueSize, kIOHIDOptionsTypeNone );
			
			if ( tIOHIDQueueRef ) { // did that work
				HIDReportErrorNum( "Failed to create queue via create", result );
			} else {
				result = kIOReturnSuccess;
			}
		}
	} else {
		HIDReportErrorNum( "HID device ref does not exist for queue creation", result );
	}
	return result;
} /* HIDCreateQueue */
Пример #2
0
Boolean HIDIsValidDevice(IOHIDDeviceRef inIOHIDDeviceRef) {
	Boolean result = false; // assume failure (pessimist!)
	if (inIOHIDDeviceRef) {
		if (CFGetTypeID(inIOHIDDeviceRef) == IOHIDDeviceGetTypeID()) {
			result = true;
		}
	}

	return (result);
} // HIDIsValidDevice
Пример #3
0
static Boolean IOHIDDevice_GetUInt32Property(IOHIDDeviceRef inIOHIDDeviceRef, CFStringRef inKey, uint32_t *outValue) {
	Boolean result = false;
	if (inIOHIDDeviceRef) {
		assert(IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef));

		CFTypeRef tCFTypeRef = IOHIDDeviceGetProperty(inIOHIDDeviceRef, inKey);
		if (tCFTypeRef) {
			// if this is a number
			if (CFNumberGetTypeID() == CFGetTypeID(tCFTypeRef)) {
				// get it's value
				result = CFNumberGetValue((CFNumberRef) tCFTypeRef, kCFNumberSInt32Type, outValue);
			}
		}
	}

	return (result);
} // IOHIDDevice_GetUInt32Property
// ---------------------------------
// removes element for queue, if last element in queue will release queue and closes device interface
int  HIDDequeueElement( IOHIDDeviceRef inIOHIDDeviceRef, IOHIDElementRef inIOHIDElementRef )
{
	IOReturn result = kIOReturnSuccess;
	
	if ( inIOHIDDeviceRef ) {
		assert( IOHIDDeviceGetTypeID() == CFGetTypeID( inIOHIDDeviceRef ) );
		if ( inIOHIDElementRef ) {
			assert( IOHIDElementGetTypeID() == CFGetTypeID( inIOHIDElementRef ) );
			IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue( inIOHIDDeviceRef );
			if ( tIOHIDQueueRef ) {
				// stop queue
				IOHIDQueueStop( tIOHIDQueueRef );
				
				// de-queue element
				if ( IOHIDQueueContainsElement( tIOHIDQueueRef, inIOHIDElementRef ) ) {
					IOHIDQueueRemoveElement( tIOHIDQueueRef, inIOHIDElementRef );
				}
				
				// release device queue and close interface if queue empty
				if ( HIDIsDeviceQueueEmpty( inIOHIDDeviceRef ) ) {
					result = HIDDisposeReleaseQueue( inIOHIDDeviceRef );
					
					if ( kIOReturnSuccess != result ) {
						HIDReportErrorNum( "Failed to dispose and release queue.", result );
					}
				} else { // not empty so restart queue
					IOHIDQueueStart( tIOHIDQueueRef );
				}
			} else {
				HIDReportError( "No queue for device passed to HIDDequeueElement." );
				if ( kIOReturnSuccess == result ) {
					result = kIOReturnError;
				}
			}
		} else {
			HIDReportError( "NULL element passed to HIDDequeueElement." );
			result = kIOReturnBadArgument;
		}
	} else {
		HIDReportError( "NULL device passed to HIDDequeueElement." );
		result = kIOReturnBadArgument;
	}
	return result;
} /* HIDDequeueElement */
// queues specific element, performing any device queue set up required
// queue is started and ready to return events on exit from this function
int  HIDQueueElement( IOHIDDeviceRef inIOHIDDeviceRef, IOHIDElementRef inIOHIDElementRef )
{
	IOReturn result = kIOReturnSuccess;
	
	if ( inIOHIDDeviceRef ) {
		assert( IOHIDDeviceGetTypeID() == CFGetTypeID( inIOHIDDeviceRef ) );
		if ( inIOHIDElementRef ) {
			assert( IOHIDElementGetTypeID() == CFGetTypeID( inIOHIDElementRef ) );
			IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue( inIOHIDDeviceRef );
			if ( !tIOHIDQueueRef ) {         // if no queue create queue
				result = HIDCreateQueue( inIOHIDDeviceRef );
				if ( kIOReturnSuccess == result ) {
					tIOHIDQueueRef = IOHIDDevice_GetQueue( inIOHIDDeviceRef );
				}
			}
			if ( tIOHIDQueueRef ) {
				
				// stop queue
				IOHIDQueueStop( tIOHIDQueueRef );
				
				// queue element
				if ( !IOHIDQueueContainsElement( tIOHIDQueueRef, inIOHIDElementRef ) ) {
					IOHIDQueueAddElement( tIOHIDQueueRef, inIOHIDElementRef );
				}
				
				// restart queue
				IOHIDQueueStart( tIOHIDQueueRef );
			} else {
				HIDReportError( "No queue for device passed to HIDQueueElement." );
				if ( kIOReturnSuccess == result ) {
					result = kIOReturnError;
				}
			}
		} else {
			HIDReportError( "NULL element passed to HIDQueueElement." );
			result = kIOReturnBadArgument;
		}
	} else {
		HIDReportError( "NULL device passed to HIDQueueElement." );
		result = kIOReturnBadArgument;
	}
	return result;
} /* HIDQueueElement */
Пример #6
0
static Boolean IOHIDDevice_GetPtrProperty(IOHIDDeviceRef inIOHIDDeviceRef, CFStringRef inKey, void **outValue) {
	Boolean result = false;
	if (inIOHIDDeviceRef) {
		assert(IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef));

		CFTypeRef tCFTypeRef = IOHIDDeviceGetProperty(inIOHIDDeviceRef, inKey);
		if (tCFTypeRef) {
			// if this is a number
			if (CFNumberGetTypeID() == CFGetTypeID(tCFTypeRef)) {
				// get it's value
#ifdef __LP64__
				result = CFNumberGetValue((CFNumberRef) tCFTypeRef, kCFNumberSInt64Type, outValue);
#else
				result = CFNumberGetValue((CFNumberRef) tCFTypeRef, kCFNumberSInt32Type, outValue);
#endif // ifdef __LP64__
			}
		}
	}

	return (result);
} // IOHIDDevice_GetPtrProperty
// ---------------------------------
// returns true if queue is empty false otherwise
// error if no device, empty if no queue
static unsigned char HIDIsDeviceQueueEmpty( IOHIDDeviceRef inIOHIDDeviceRef )
{
	if ( inIOHIDDeviceRef ) { // need device and queue
		assert( IOHIDDeviceGetTypeID() == CFGetTypeID( inIOHIDDeviceRef ) );
		IOHIDQueueRef tIOHIDQueueRef = IOHIDDevice_GetQueue( inIOHIDDeviceRef );
		if ( tIOHIDQueueRef ) {
			IOHIDElementRef tIOHIDElementRef = HIDGetFirstDeviceElement( inIOHIDDeviceRef, kHIDElementTypeIO );
			while ( tIOHIDElementRef ) {
				if ( IOHIDQueueContainsElement( tIOHIDQueueRef, tIOHIDElementRef ) ) {
					return false;
				}
				tIOHIDElementRef = HIDGetNextDeviceElement( tIOHIDElementRef, kHIDElementTypeIO );
			}
		} else {
			HIDReportError( "NULL device passed to HIDIsDeviceQueueEmpty." );
		}
	} else {
		HIDReportError( "NULL device passed to HIDIsDeviceQueueEmpty." );
	}
	return true;
} /* HIDIsDeviceQueueEmpty */
Пример #8
0
void usbadd(void* context, IOReturn result, void* sender, IOHIDDeviceRef device){
    if(CFGetTypeID(device) != IOHIDDeviceGetTypeID())
        return;
    // Get the model and serial number
    long idvendor = V_CORSAIR, idproduct = usbgetvalue(device, CFSTR(kIOHIDProductIDKey));
    char serial[SERIAL_LEN];
    CFTypeRef cfserial = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDSerialNumberKey));
    if(!cfserial || CFGetTypeID(cfserial) != CFStringGetTypeID() || !CFStringGetCString(cfserial, serial, SERIAL_LEN, kCFStringEncodingASCII))
        // If the serial can't be read, make one up
        snprintf(serial, SERIAL_LEN, "%04x:%x04-NoID", (uint)idvendor, (uint)idproduct);

    // For non-RGB models, get the firmware version here as well
    long fwversion = 0;
    if(!IS_RGB(idvendor, idproduct))
        fwversion = usbgetvalue(device, CFSTR(kIOHIDVersionNumberKey));

    pthread_mutex_lock(&kblistmutex);
    // A single keyboard will generate multiple match events, so each handle has to be added to the board separately.
    // Look for any partially-set up boards matching this serial number
    int index = -1;
    for(int i = 1; i < DEV_MAX; i++){
        if(!strcmp(keyboard[i].profile.serial, serial) && keyboard[i].handle == INCOMPLETE){
            index = i;
            break;
        }
    }
    // If none was found, grab the first free device
    if(index == -1){
        for(int i = 1; i < DEV_MAX; i++){
            if(!keyboard[i].handle){
                // Mark the device as in use and print out a message
                index = i;
                keyboard[i].handle = INCOMPLETE;
                keyboard[i].fwversion = fwversion;
                strcpy(keyboard[i].profile.serial, serial);
                CFTypeRef cfname = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
                if(cfname && CFGetTypeID(cfname) == CFStringGetTypeID())
                    CFStringGetCString(cfname, keyboard[i].name, NAME_LEN, kCFStringEncodingASCII);
                printf("Connecting %s (S/N: %s)\n", keyboard[i].name, keyboard[i].profile.serial);
                break;
            }
        }
    }
    if(index == -1){
        printf("Error: No free devices\n");
        pthread_mutex_unlock(&kblistmutex);
        return;
    }
    usbdevice* kb = keyboard + index;
    // There's no direct way to tell which of the four handles this is, but there's a workaround
    // Each handle has a unique maximum packet size combination, so use that to place them
    long input = usbgetvalue(device, CFSTR(kIOHIDMaxInputReportSizeKey));
    long output = usbgetvalue(device, CFSTR(kIOHIDMaxOutputReportSizeKey));
    long feature = usbgetvalue(device, CFSTR(kIOHIDMaxFeatureReportSizeKey));

    // Handle 0 is for BIOS mode input (RGB) or non-RGB key input
    if(input == 8 && output == 1 && feature == 0)
        kb->handles[0] = device;
    // Handle 1 is for standard HID input (RGB) or media keys (non-RGB)
    else if((input == 21 && output == 1 && feature == 1)
            || (input == 4 && output == 0 && feature == 0))
        kb->handles[1] = device;
    // Handle 2 is for Corsair inputs, unused on non-RGB
    else if(((input == 64 || input == 15) && output == 0 && feature == 0)
            || (input == 64 && output == 64 && feature == 0))           // FW >= 1.20
        kb->handles[2] = device;
    // Handle 3 is for controlling the device (only exists for RGB)
    else if((input == 0 && output == 0 && feature == 64)
            || (input == 64 && output == 64 && feature == 64))          // FW >= 1.20
        kb->handles[3] = device;
    else
        printf("Warning: Got unknown handle (I: %d, O: %d, F: %d)\n", (int)input, (int)output, (int)feature);

    // If all handles have been set up, finish initializing the keyboard
    if(kb->handles[0] && kb->handles[1] && kb->handles[2]
            && (kb->handles[3] || !IS_RGB(idvendor, idproduct)))
        openusb(kb, (short)idvendor, (short)idproduct);
    pthread_mutex_unlock(&kblistmutex);
}
Пример #9
0
CFArrayRef IOHIDDevice_GetUsagePairs(IOHIDDeviceRef inIOHIDDeviceRef) {
    assert(IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef));
	return (IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDDeviceUsagePairsKey)));
}
Пример #10
0
CFStringRef IOHIDDevice_GetSerialNumber(IOHIDDeviceRef inIOHIDDeviceRef) {
    assert(IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef));
	return (IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDSerialNumberKey)));
}
Пример #11
0
CFStringRef IOHIDDevice_GetProduct(IOHIDDeviceRef inIOHIDDeviceRef) {
    assert(IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef));
	return (IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDProductKey)));
} // IOHIDDevice_GetProduct
Пример #12
0
CFStringRef IOHIDDevice_GetManufacturer(IOHIDDeviceRef inIOHIDDeviceRef) {
    assert(IOHIDDeviceGetTypeID() == CFGetTypeID(inIOHIDDeviceRef));
	return (IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDManufacturerKey)));
} // IOHIDDevice_GetManufacturer
Пример #13
0
void usbadd(void* context, IOReturn result, void* sender, IOHIDDeviceRef device){
    if(CFGetTypeID(device) != IOHIDDeviceGetTypeID())
        return;
    // Get the model and serial number
    long idproduct = usbgetvalue(device, CFSTR(kIOHIDProductIDKey));
    int model;
    if(idproduct == P_K70)
        model = 70;
    else if(idproduct == P_K95)
        model = 95;
    else
        return;
    char serial[SERIAL_LEN];
    CFTypeRef cfserial = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDSerialNumberKey));
    if(!cfserial || CFGetTypeID(cfserial) != CFStringGetTypeID() || !CFStringGetCString(cfserial, serial, SERIAL_LEN, kCFStringEncodingASCII))
        return;
    pthread_mutex_lock(&kblistmutex);
    // A single keyboard will generate 4 match events, so each handle has to be added to the board separately.
    // Look for any partially-set up boards matching this serial number
    int index = -1;
    for(int i = 1; i < DEV_MAX; i++){
        if(!strcmp(keyboard[i].profile.serial, serial) && keyboard[i].handle == INCOMPLETE){
            index = i;
            break;
        }
    }
    // If none was found, grab the first free device
    if(index == -1){
        for(int i = 1; i < DEV_MAX; i++){
            if(!keyboard[i].handle){
                // Mark the device as in use and print out a message
                index = i;
                keyboard[i].handle = INCOMPLETE;
                keyboard[i].model = model;
                strcpy(keyboard[i].profile.serial, serial);
                CFTypeRef cfname = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
                if(cfname && CFGetTypeID(cfname) == CFStringGetTypeID())
                    CFStringGetCString(cfname, keyboard[i].name, SERIAL_LEN, kCFStringEncodingASCII);
                printf("Connecting %s (S/N: %s)\n", keyboard[i].name, keyboard[i].profile.serial);
                break;
            }
        }
    }
    if(index == -1){
        printf("Error: No free devices\n");
        pthread_mutex_unlock(&kblistmutex);
        return;
    }
    usbdevice* kb = keyboard + index;
    // There's no direct way to tell which of the four handles this is, but there's a workaround
    // Each handle has a unique maximum packet size combination, so use that to place them
    long input = usbgetvalue(device, CFSTR(kIOHIDMaxInputReportSizeKey));
    long output = usbgetvalue(device, CFSTR(kIOHIDMaxOutputReportSizeKey));
    long feature = usbgetvalue(device, CFSTR(kIOHIDMaxFeatureReportSizeKey));

    // Handle 0 is unused
    if(input == 8 && output == 1 && feature == 0)
        kb->handles[0] = device;
    // Handle 1 is for HID inputs (ignored by ckb)
    else if(input == 21 && output == 1 && feature == 1)
        kb->handles[1] = device;
    // Handle 2 is for Corsair inputs
    else if(input == 64 && output == 0 && feature == 0)
        kb->handles[2] = device;
    // Handle 3 is for controlling the device
    else if(input == 0 && output == 0 && feature == 64)
        kb->handles[3] = device;
    else
        printf("Warning: Got unknown handle (I: %d, O: %d, F: %d)\n", (int)input, (int)output, (int)feature);

    // If all handles have been set up, finish initializing the keyboard
    if(kb->handles[0] && kb->handles[1] && kb->handles[2] && kb->handles[3])
        openusb(kb);
    pthread_mutex_unlock(&kblistmutex);
}
Пример #14
0
// get the first element of device passed in as parameter
// returns NULL if no list exists or device does not exists or is NULL
IOHIDElementRef HIDGetFirstDeviceElement( IOHIDDeviceRef inIOHIDDeviceRef, HIDElementTypeMask typeMask )
{
	IOHIDElementRef result = NULL;

	if ( inIOHIDDeviceRef ) {
		assert( IOHIDDeviceGetTypeID() == CFGetTypeID( inIOHIDDeviceRef ) );

		gElementCFArrayRef = IOHIDDeviceCopyMatchingElements( inIOHIDDeviceRef, NULL, kIOHIDOptionsTypeNone );

		if ( gElementCFArrayRef ) {
			CFIndex idx, cnt = CFArrayGetCount( gElementCFArrayRef );
			for ( idx = 0; idx < cnt; idx++ ) {
				IOHIDElementRef tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( gElementCFArrayRef, idx );

				if ( !tIOHIDElementRef ) {
					continue;
				}

				IOHIDElementType type = IOHIDElementGetType( tIOHIDElementRef );
				switch ( type ) {
					case kIOHIDElementTypeInput_Misc:
					case kIOHIDElementTypeInput_Button:
					case kIOHIDElementTypeInput_Axis:
					case kIOHIDElementTypeInput_ScanCodes:
					{
						if ( typeMask & kHIDElementTypeInput ) {
							result = tIOHIDElementRef;
						}
						break;
					}

					case kIOHIDElementTypeOutput:
					{
						if ( typeMask & kHIDElementTypeOutput ) {
							result = tIOHIDElementRef;
						}
						break;
					}

					case kIOHIDElementTypeFeature:
					{
						if ( typeMask & kHIDElementTypeFeature ) {
							result = tIOHIDElementRef;
						}
						break;
					}

					case kIOHIDElementTypeCollection:
					{
						if ( typeMask & kHIDElementTypeCollection ) {
							result = tIOHIDElementRef;
						}
						break;
					}
				}           // switch ( type )

				if ( result ) {
					break;  // DONE!
				}
			}               // next idx
			CFRelease( gElementCFArrayRef );
			gElementCFArrayRef = NULL;
		}                   // 		if ( gElementCFArrayRef )
	}                       // 	if ( inIOHIDDeviceRef )
	return result;
} /* HIDGetFirstDeviceElement */