Пример #1
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);
}
Пример #2
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);
}