Ejemplo n.º 1
0
void udevenum(){
    struct udev_enumerate* enumerator = udev_enumerate_new(udev);
    udev_enumerate_add_match_subsystem(enumerator, "usb");
    udev_enumerate_add_match_sysattr(enumerator, "idVendor", V_CORSAIR_STR);
    udev_enumerate_scan_devices(enumerator);
    struct udev_list_entry* devices, *dev_list_entry;
    devices = udev_enumerate_get_list_entry(enumerator);

    udev_list_entry_foreach(dev_list_entry, devices){
        const char* path = udev_list_entry_get_name(dev_list_entry);
        struct udev_device* dev = udev_device_new_from_syspath(udev, path);
        // If the device matches a recognized device ID, open it
        const char* product = udev_device_get_sysattr_value(dev, "idProduct");
        if(!strcmp(product, P_K70_STR)){
            pthread_mutex_lock(&kblistmutex);
            openusb(dev, 70);
            pthread_mutex_unlock(&kblistmutex);
            continue;
        }
        if(!strcmp(product, P_K95_STR)){
            pthread_mutex_lock(&kblistmutex);
            openusb(dev, 95);
            pthread_mutex_unlock(&kblistmutex);
            continue;
        }
        // Free the device if it wasn't used
        udev_device_unref(dev);
    }
    udev_enumerate_unref(enumerator);
}
Ejemplo n.º 2
0
Archivo: usb_mac.c Proyecto: jsnel/ckb
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);
}
Ejemplo n.º 3
0
void* udevmain(void* context){
    // Enumerate all currently connected devices
    udevenum();
    if(connectstatus & 2)
        // If a device failed to connect, enumerate again to make sure we reconnect it (if possible)
        udevenum();

    // Done scanning. Enter a loop to poll for device updates
    struct udev_monitor* monitor = udev_monitor_new_from_netlink(udev, "udev");
    udev_monitor_filter_add_match_subsystem_devtype(monitor, "usb", 0);
    udev_monitor_enable_receiving(monitor);
    // Get an fd for the monitor
    int fd = udev_monitor_get_fd(monitor);
    fd_set fds;
    while(udev){
        FD_ZERO(&fds);
        FD_SET(fd, &fds);
        // Block until an event is read
        if(select(fd + 1, &fds, 0, 0, 0) > 0 && FD_ISSET(fd, &fds)){
            struct udev_device* dev = udev_monitor_receive_device(monitor);
            if(dev){
                const char* action = udev_device_get_action(dev);
                if(action && !strcmp(action, "add")){
                    // Device added. Check vendor and product ID and add the device if it matches.
                    const char* vendor = udev_device_get_sysattr_value(dev, "idVendor");
                    if(vendor && !strcmp(vendor, V_CORSAIR_STR)){
                        const char* product = udev_device_get_sysattr_value(dev, "idProduct");
                        if(product && !strcmp(product, P_K70_STR)){
                            pthread_mutex_lock(&kblistmutex);
                            openusb(dev, 70);
                            pthread_mutex_unlock(&kblistmutex);
                        } else if(product && !strcmp(product, P_K95_STR)){
                            pthread_mutex_lock(&kblistmutex);
                            openusb(dev, 95);
                            pthread_mutex_unlock(&kblistmutex);
                        } else
                            // Free the device if it wasn't used
                            udev_device_unref(dev);
                    } else
                        udev_device_unref(dev);
                    // Wait a little bit and then re-enumerate devices. Sometimes the keyboard doesn't get picked up right away.
                    usleep(100000);
                    connectstatus = 0;
                    udevenum();
                    if(connectstatus & 2)
                        udevenum();
                } else if(!strcmp(action, "remove")){
                    // Device removed. Look for it in our list of keyboards
                    pthread_mutex_lock(&kblistmutex);
                    const char* path = udev_device_get_syspath(dev);
                    for(int i = 1; i < DEV_MAX; i++){
                        if(keyboard[i].udev && !strcmp(path, udev_device_get_syspath(keyboard[i].udev))){
                            pthread_mutex_lock(&keyboard[i].mutex);
                            closeusb(i);
                            break;
                        }
                    }
                    pthread_mutex_unlock(&kblistmutex);
                }
            }
        }
    }
    udev_monitor_unref(monitor);
    return 0;
}
Ejemplo n.º 4
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);
}