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); }
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); }