void updateindicators(usbdevice* kb, int force){ // Set NumLock on permanently char ileds = 1; // Set Caps Lock if enabled. Unlike Linux, OSX keyboards have independent caps lock states, so // we use the last-assigned value rather than fetching it from the system if(kb->eflags & kCGEventFlagMaskAlphaShift) ileds |= 2; if(force || ileds != kb->ileds){ kb->ileds = ileds; // Set the LEDs CFArrayRef leds = IOHIDDeviceCopyMatchingElements(kb->handles[0], 0, kIOHIDOptionsTypeNone); CFIndex count = CFArrayGetCount(leds); for(CFIndex i = 0; i < count; i++){ IOHIDElementRef led = (void*)CFArrayGetValueAtIndex(leds, i); uint32_t page = IOHIDElementGetUsagePage(led); if(page != kHIDPage_LEDs) continue; uint32_t usage = IOHIDElementGetUsage(led); IOHIDValueRef value = IOHIDValueCreateWithIntegerValue(kCFAllocatorDefault, led, 0, !!(ileds & (1 << (usage - 1)))); IOHIDDeviceSetValue(kb->handles[0], led, value); CFRelease(value); } CFRelease(leds); IOHIDDeviceSetReport(kb->handles[1], kIOHIDReportTypeOutput, 0, &kb->ileds, 1); } }
void os_updateindicators(usbdevice* kb, int force){ if(!IS_CONNECTED(kb) || NEEDS_FW_UPDATE(kb)) return; // Set NumLock on permanently char ileds = 1; // Set Caps Lock if enabled. Unlike Linux, OSX keyboards have independent caps lock states, so // we use the last-assigned value rather than fetching it from the system if(kb->eventflags & kCGEventFlagMaskAlphaShift) ileds |= 2; usbmode* mode = kb->profile.currentmode; if(mode && kb->active) ileds = (ileds & ~mode->ioff) | mode->ion; if(force || ileds != kb->ileds){ kb->ileds = ileds; // Set the LEDs CFArrayRef leds = IOHIDDeviceCopyMatchingElements(kb->handles[0], 0, kIOHIDOptionsTypeNone); CFIndex count = CFArrayGetCount(leds); for(CFIndex i = 0; i < count; i++){ IOHIDElementRef led = (void*)CFArrayGetValueAtIndex(leds, i); uint32_t page = IOHIDElementGetUsagePage(led); if(page != kHIDPage_LEDs) continue; uint32_t usage = IOHIDElementGetUsage(led); IOHIDValueRef value = IOHIDValueCreateWithIntegerValue(kCFAllocatorDefault, led, 0, !!(ileds & (1 << (usage - 1)))); IOHIDDeviceSetValue(kb->handles[0], led, value); CFRelease(value); } CFRelease(leds); } }
static void __deviceReportCallback(void * context, IOReturn result, void * sender, IOHIDReportType type, uint32_t reportID, uint8_t * report, CFIndex reportLength) { int index; printf("IOHIDDeviceRef[%p]: result=0x%08x reportType=%s reportID=%d reportLength=%ld: ", sender, result, getReportTypeString(type), reportID, reportLength); for (index=0; result==kIOReturnSuccess && index<reportLength; index++) printf("%02x ", report[index]); printf("\n"); // toggle a report if ( gSend || gSendTransaction ) { CFArrayRef outputElements = NULL; outputElements = CFDictionaryGetValue(gOutputElements, sender); if ( outputElements ) { static uint8_t value = 0; IOHIDTransactionRef transaction = NULL; transaction = IOHIDTransactionCreate(kCFAllocatorDefault, (IOHIDDeviceRef)sender, kIOHIDTransactionDirectionTypeOutput, 0); if ( transaction ) { IOReturn ret; CFIndex index, count; for ( index=0, count = CFArrayGetCount(outputElements); index<count; index++) { IOHIDElementRef element = (IOHIDElementRef)CFArrayGetValueAtIndex(outputElements, index); IOHIDValueRef hidValue = 0; if ( !element ) continue; IOHIDTransactionAddElement(transaction, element); hidValue = IOHIDValueCreateWithIntegerValue(kCFAllocatorDefault, element, 0, value); if ( !hidValue ) continue; if ( gSendTransaction ) { IOHIDTransactionSetValue(transaction, element, hidValue, 0); } else { ret = IOHIDDeviceSetValue((IOHIDDeviceRef)sender, element, hidValue); printf("Attempt to send value. Ret = 0x%08x\n", ret); } CFRelease(hidValue); } if ( gSendTransaction ) { ret = IOHIDTransactionCommit(transaction); printf("Attempt to send transaction. Ret = 0x%08x\n", ret); } value = value+1 % 2; CFRelease(transaction); } } } }
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 main( int argc, const char * argv[] ) int manipulate_led( int which_led, int led_value ) { #pragma unused ( argc, argv ) IOHIDDeviceRef * tIOHIDDeviceRefs = nil; // create a IO HID Manager reference IOHIDManagerRef tIOHIDManagerRef = IOHIDManagerCreate( kCFAllocatorDefault, kIOHIDOptionsTypeNone ); require( tIOHIDManagerRef, Oops ); // Create a device matching dictionary CFDictionaryRef matchingCFDictRef = hu_CreateMatchingDictionaryUsagePageUsage( TRUE, kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard ); require( matchingCFDictRef, Oops ); // set the HID device matching dictionary IOHIDManagerSetDeviceMatching( tIOHIDManagerRef, matchingCFDictRef ); if ( matchingCFDictRef ) { CFRelease( matchingCFDictRef ); } // Now open the IO HID Manager reference IOReturn tIOReturn = IOHIDManagerOpen( tIOHIDManagerRef, kIOHIDOptionsTypeNone ); require_noerr( tIOReturn, Oops ); // and copy out its devices CFSetRef deviceCFSetRef = IOHIDManagerCopyDevices( tIOHIDManagerRef ); require( deviceCFSetRef, Oops ); // how many devices in the set? CFIndex deviceIndex, deviceCount = CFSetGetCount( deviceCFSetRef ); // allocate a block of memory to extact the device ref's from the set into tIOHIDDeviceRefs = malloc( sizeof( IOHIDDeviceRef ) * deviceCount ); if (!tIOHIDDeviceRefs) { CFRelease(deviceCFSetRef); deviceCFSetRef = NULL; goto Oops; } // now extract the device ref's from the set CFSetGetValues( deviceCFSetRef, (const void **) tIOHIDDeviceRefs ); CFRelease(deviceCFSetRef); deviceCFSetRef = NULL; // before we get into the device loop we'll setup our element matching dictionary matchingCFDictRef = hu_CreateMatchingDictionaryUsagePageUsage( FALSE, kHIDPage_LEDs, 0 ); require( matchingCFDictRef, Oops ); int pass; // do 256 passes //for ( pass = 0; pass < 256; pass++ ) { Boolean delayFlag = FALSE; // if we find an LED element we'll set this to TRUE //printf( "pass = %d.\n", pass ); for ( deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++ ) { // if this isn't a keyboard device... if ( !IOHIDDeviceConformsTo( tIOHIDDeviceRefs[deviceIndex], kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard ) ) { continue; // ...skip it } //printf( " device = %p.\n", tIOHIDDeviceRefs[deviceIndex] ); // copy all the elements CFArrayRef elementCFArrayRef = IOHIDDeviceCopyMatchingElements( tIOHIDDeviceRefs[deviceIndex], matchingCFDictRef, kIOHIDOptionsTypeNone ); require( elementCFArrayRef, next_device ); // for each device on the system these values are divided by the value ranges of all LED elements found // for example, if the first four LED element have a range of 0-1 then the four least significant bits of // this value will be sent to these first four LED elements, etc. int device_value = pass; // iterate over all the elements CFIndex elementIndex, elementCount = CFArrayGetCount( elementCFArrayRef ); for ( elementIndex = 0; elementIndex < elementCount; elementIndex++ ) { IOHIDElementRef tIOHIDElementRef = ( IOHIDElementRef ) CFArrayGetValueAtIndex( elementCFArrayRef, elementIndex ); require( tIOHIDElementRef, next_element ); uint32_t usagePage = IOHIDElementGetUsagePage( tIOHIDElementRef ); // if this isn't an LED element... if ( kHIDPage_LEDs != usagePage ) { continue; // ...skip it } uint32_t usage = IOHIDElementGetUsage( tIOHIDElementRef ); IOHIDElementType tIOHIDElementType = IOHIDElementGetType( tIOHIDElementRef ); //printf( " element = %p (page: %d, usage: %d, type: %d ).\n", // tIOHIDElementRef, usagePage, usage, tIOHIDElementType ); // get the logical mix/max for this LED element CFIndex minCFIndex = IOHIDElementGetLogicalMin( tIOHIDElementRef ); CFIndex maxCFIndex = IOHIDElementGetLogicalMax( tIOHIDElementRef ); // calculate the range CFIndex modCFIndex = maxCFIndex - minCFIndex + 1; // compute the value for this LED element //CFIndex tCFIndex = minCFIndex + ( device_value % modCFIndex ); CFIndex tCFIndex = led_value; device_value /= modCFIndex; //printf( " value = 0x%08lX.\n", tCFIndex ); uint64_t timestamp = 0; // create the IO HID Value to be sent to this LED element IOHIDValueRef tIOHIDValueRef = IOHIDValueCreateWithIntegerValue( kCFAllocatorDefault, tIOHIDElementRef, timestamp, tCFIndex ); if ( tIOHIDValueRef ) { // now set it on the device tIOReturn = IOHIDDeviceSetValue( tIOHIDDeviceRefs[deviceIndex], tIOHIDElementRef, tIOHIDValueRef ); CFRelease( tIOHIDValueRef ); require_noerr( tIOReturn, next_element ); delayFlag = TRUE; // set this TRUE so we'll delay before changing our LED values again } next_element: ; continue; } CFRelease( elementCFArrayRef ); next_device: ; continue; } // if we found an LED we'll delay before continuing //if ( delayFlag ) { // usleep( 500000 ); // sleep one half second //} // if the mouse is down… //if (GetCurrentButtonState()) { // break; // abort pass loop //} //} // next pass if ( matchingCFDictRef ) { CFRelease( matchingCFDictRef ); } Oops: ; if ( tIOHIDDeviceRefs ) { free(tIOHIDDeviceRefs); } if ( tIOHIDManagerRef ) { CFRelease( tIOHIDManagerRef ); } return 0; } /* main */
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); }