Пример #1
0
int os_resetusb(usbdevice* kb, const char* file, int line){
    TEST_RESET(usbunclaim(kb, 1, HAS_FEATURES(kb, FEAT_RGB)));
    TEST_RESET(ioctl(kb->handle, USBDEVFS_RESET));
    TEST_RESET(usbclaim(kb, HAS_FEATURES(kb, FEAT_RGB)));
    // Success!
    return 0;
}
Пример #2
0
void os_closeusb(usbdevice* kb){
    usbunclaim(kb, 0, HAS_FEATURES(kb, FEAT_RGB));
    close(kb->handle);
    udev_device_unref(kb->udev);
    kb->handle = 0;
    kb->udev = 0;
    kbsyspath[INDEX_OF(kb, keyboard)][0] = 0;
}
Пример #3
0
Файл: usb.c Проект: gtjoseph/ckb
int revertusb(usbdevice* kb){
    if(NEEDS_FW_UPDATE(kb))
        return 0;
    if(!HAS_FEATURES(kb, FEAT_RGB)){
        nk95cmd(kb, NK95_HWON);
        return 0;
    }
    if(setactive(kb, 0))
        return -1;
    return 0;
}
Пример #4
0
int _usbinput(usbdevice* kb, uchar* message, const char* file, int line){
    if(!IS_CONNECTED(kb) || !HAS_FEATURES(kb, FEAT_RGB))
        return -1;
    CFIndex length = MSG_SIZE;
    IOReturn res = IOHIDDeviceGetReport(kb->handle, kIOHIDReportTypeFeature, 0, message, &length);
    kb->lastError = res;
    if(res != kIOReturnSuccess && res != 0xe0004051){
        printf("usbinput (%s:%d): Got return value 0x%x\n", file, line, res);
        return 0;
    }
    if(length != MSG_SIZE)
        printf("usbinput (%s:%d): Read %d bytes (expected %d)\n", file, line, (int)length, MSG_SIZE);
    return length;
}
Пример #5
0
int _usbdequeue(usbdevice* kb, const char* file, int line){
    if(kb->queuecount == 0 || !kb->handle || !HAS_FEATURES(kb, FEAT_RGB))
        return -1;
    IOReturn res = IOHIDDeviceSetReport(kb->handle, kIOHIDReportTypeFeature, 0, kb->queue[0], MSG_SIZE);
    // Rotate queue
    uchar* first = kb->queue[0];
    for(int i = 1; i < QUEUE_LEN; i++)
        kb->queue[i - 1] = kb->queue[i];
    kb->queue[QUEUE_LEN - 1] = first;
    kb->queuecount--;
    kb->lastError = res;
    if(res != kIOReturnSuccess && res != 0xe0004051){   // Can't find e0004051 documented, but it seems to be a harmless error, so ignore it.
        printf("usbdequeue (%s:%d): Got return value 0x%x\n", file, line, res);
        return 0;
    }
    return MSG_SIZE;
}
Пример #6
0
void reportcallback(void* context, IOReturn result, void* sender, IOHIDReportType reporttype, uint32_t reportid, uint8_t* data, CFIndex length){
    usbdevice* kb = context;
    if(HAS_FEATURES(kb, FEAT_RGB)){
        switch(length){
        case 8:
            // RGB EP 1: 6KRO (BIOS mode) input
            hid_translate(kb->kbinput, -1, 8, kb->urbinput);
            inputupdate(kb);
            break;
        case 21:
        case 5:
            // RGB EP 2: NKRO (non-BIOS) input. Accept only if keyboard is inactive
            if(!kb->active){
                hid_translate(kb->kbinput, -2, 21, kb->urbinput + 8);
                inputupdate(kb);
            }
            break;
        case MSG_SIZE:
            // RGB EP 3: Corsair input
            inputupdate(kb);
            break;
        }
    } else {
        switch(length){
        case 8:
            // Non-RGB EP 1: 6KRO input
            hid_translate(kb->kbinput, 1, 8, kb->urbinput);
            inputupdate(kb);
            break;
        case 4:
            // Non-RGB EP 2: media keys
            hid_translate(kb->kbinput, 2, 4, kb->urbinput + 8);
            inputupdate(kb);
            break;
        case 15:
            // Non-RGB EP 3: NKRO input
            hid_translate(kb->kbinput, 3, 15, kb->urbinput + 8 + 4);
            inputupdate(kb);
            break;
        }
    }
}
Пример #7
0
static void intreport(void* context, IOReturn result, void* sender, IOHIDReportType reporttype, uint32_t reportid, uint8_t* data, CFIndex length){
    usbdevice* kb = context;
    pthread_mutex_lock(imutex(kb));
    if(IS_MOUSE(kb->vendor, kb->product)){
        if(length == 10)
            hid_mouse_translate(kb->input.keys, &kb->input.rel_x, &kb->input.rel_y, -2, length, data);
    } else if(HAS_FEATURES(kb, FEAT_RGB)){
        switch(length){
        case 8:
            // RGB EP 1: 6KRO (BIOS mode) input
            hid_kb_translate(kb->input.keys, -1, length, data);
            break;
        case 21:
        case 5:
            // RGB EP 2: NKRO (non-BIOS) input. Accept only if keyboard is inactive
            if(!kb->active)
                hid_kb_translate(kb->input.keys, -2, length, data);
            break;
        case MSG_SIZE:
            // RGB EP 3: Corsair input
            memcpy(kb->input.keys, data, N_KEYBYTES_KB);
            break;
        }
    } else {
        switch(length){
        case 8:
            // Non-RGB EP 1: 6KRO input
            hid_kb_translate(kb->input.keys, 1, length, data);
            break;
        case 4:
            // Non-RGB EP 2: media keys
            hid_kb_translate(kb->input.keys, 2, length, data);
            break;
        case 15:
            // Non-RGB EP 3: NKRO input
            hid_kb_translate(kb->input.keys, 3, length, data);
            break;
        }
    }
    inputupdate(kb);
    pthread_mutex_unlock(imutex(kb));
}
Пример #8
0
int usbunclaim(usbdevice* kb, int resetting){
    int handle = kb->handle - 1;
    int count = kb->epcount;
    for(int i = 0; i < count; i++)
        ioctl(handle, USBDEVFS_RELEASEINTERFACE, &i);
    // For RGB keyboards, the kernel driver should only be reconnected to interfaces 0 and 1 (HID), and only if we're not about to do a USB reset.
    // Reconnecting any of the others causes trouble.
    if(!resetting){
        struct usbdevfs_ioctl ctl = { 0, USBDEVFS_CONNECT, 0 };
        ioctl(handle, USBDEVFS_IOCTL, &ctl);
        ctl.ifno = 1;
        ioctl(handle, USBDEVFS_IOCTL, &ctl);
        // Also reconnect iface #2 (HID) for non-RGB keyboards
        if(!HAS_FEATURES(kb, FEAT_RGB)){
            ctl.ifno = 2;
            ioctl(handle, USBDEVFS_IOCTL, &ctl);
        }
    }
    return 0;
}
Пример #9
0
int os_setupusb(usbdevice* kb){
    // Copy device description and serial
    struct udev_device* dev = kb->udev;
    const char* name = udev_device_get_sysattr_value(dev, "product");
    if(name)
        strncpy(kb->name, name, KB_NAME_LEN);
    const char* serial = udev_device_get_sysattr_value(dev, "serial");
    if(serial)
        strncpy(kb->serial, serial, SERIAL_LEN);
    // Copy firmware version (needed to determine USB protocol)
    const char* firmware = udev_device_get_sysattr_value(dev, "bcdDevice");
    if(firmware)
        sscanf(firmware, "%hx", &kb->fwversion);
    else
        kb->fwversion = 0;
    ckb_info("Connecting %s (S/N: %s)\n", kb->name, kb->serial);

    // Claim the USB interfaces
    if(usbclaim(kb, HAS_FEATURES(kb, FEAT_RGB))){
        ckb_err("Failed to claim interface: %s\n", strerror(errno));
        return -1;
    }
    return 0;
}
Пример #10
0
int os_setupusb(usbdevice* kb){
    // Copy device description and serial
    struct udev_device* dev = kb->udev;
    const char* name = udev_device_get_sysattr_value(dev, "product");
    if(name)
        strncpy(kb->name, name, KB_NAME_LEN);
    strtrim(kb->name);
    const char* serial = udev_device_get_sysattr_value(dev, "serial");
    if(serial)
        strncpy(kb->serial, serial, SERIAL_LEN);
    strtrim(kb->serial);
    // Copy firmware version (needed to determine USB protocol)
    const char* firmware = udev_device_get_sysattr_value(dev, "bcdDevice");
    if(firmware)
        sscanf(firmware, "%hx", &kb->fwversion);
    else
        kb->fwversion = 0;
    int index = INDEX_OF(kb, keyboard);
    ckb_info("Connecting %s at %s%d\n", kb->name, devpath, index);

    // Claim the USB interfaces
    const char* ep_str = udev_device_get_sysattr_value(dev, "bNumInterfaces");
    kb->epcount = 0;
    if(ep_str)
        sscanf(ep_str, "%d", &kb->epcount);
    if(kb->epcount == 0){
        // This shouldn't happen, but if it does, assume EP count based on what the device is supposed to have
        kb->epcount = (HAS_FEATURES(kb, FEAT_RGB) ? 4 : 3);
        ckb_warn("Unable to read endpoint count from udev, assuming %d...\n", kb->epcount);
    }
    if(usbclaim(kb)){
        ckb_err("Failed to claim interfaces: %s\n", strerror(errno));
        return -1;
    }
    return 0;
}
Пример #11
0
void os_keypress(usbdevice* kb, int scancode, int down){
    if(scancode & SCAN_MOUSE){
        if(scancode == BTN_WHEELUP){
            if(down)
                postevent_wheel(kb->event, !!(kb->features & FEAT_MOUSEACCEL), 1);
            return;
        } else if(scancode == BTN_WHEELDOWN){
            if(down)
                postevent_wheel(kb->event, !!(kb->features & FEAT_MOUSEACCEL), -1);
            return;
        }
        int button = scancode & ~SCAN_MOUSE;
        // Reverse or collapse left/right buttons if the system preferences say so
        int mode;
        if(IOHIDGetMouseButtonMode(kb->event, &mode) == kIOReturnSuccess){
            if(mode == kIOHIDButtonMode_ReverseLeftRightClicks && button == 0)
                button = 1;
            else if(mode != kIOHIDButtonMode_EnableRightClick && button == 1)
                button = 0;
        }
        postevent_mb(kb->event, button, down);
        if(down)
            kb->mousestate |= (1 << button);
        else
            kb->mousestate &= ~(1 << button);
        return;
    }
    // Some boneheaded Apple engineers decided to reverse kVK_ANSI_Grave and kVK_ISO_Section on the 105-key layouts...
    if(!HAS_ANY_FEATURE(kb, FEAT_LMASK)){
        // If the layout hasn't been set yet, it can be auto-detected from certain keys
        if(scancode == KEY_BACKSLASH_ISO || scancode == KEY_102ND)
            kb->features |= FEAT_ISO;
        else if(scancode == KEY_BACKSLASH)
            kb->features |= FEAT_ANSI;
    }
    if(scancode == KEY_BACKSLASH_ISO)
        scancode = KEY_BACKSLASH;
    if(HAS_FEATURES(kb, FEAT_ISO)){
        // Compensate for key reversal
        if(scancode == KEY_GRAVE)
            scancode = KEY_102ND;
        else if(scancode == KEY_102ND)
            scancode = KEY_GRAVE;
    }
    // Check for modifier keys and update flags
    int isMod = 0;
    IOOptionBits mod = 0;
    if(scancode == KEY_CAPSLOCK){
        if(down)
            kb->modifiers ^= NX_ALPHASHIFTMASK;
        isMod = 1;
    }
    else if(scancode == KEY_LEFTSHIFT) mod = NX_DEVICELSHIFTKEYMASK;
    else if(scancode == KEY_RIGHTSHIFT) mod = NX_DEVICERSHIFTKEYMASK;
    else if(scancode == KEY_LEFTCTRL) mod = NX_DEVICELCTLKEYMASK;
    else if(scancode == KEY_RIGHTCTRL) mod = NX_DEVICERCTLKEYMASK;
    else if(scancode == KEY_LEFTMETA) mod = NX_DEVICELCMDKEYMASK;
    else if(scancode == KEY_RIGHTMETA) mod = NX_DEVICERCMDKEYMASK;
    else if(scancode == KEY_LEFTALT) mod = NX_DEVICELALTKEYMASK;
    else if(scancode == KEY_RIGHTALT) mod = NX_DEVICERALTKEYMASK;
    if(mod){
        // Update global modifiers
        if(down)
            mod |= kb->modifiers;
        else
            mod = kb->modifiers & ~mod;
        if((mod & NX_DEVICELSHIFTKEYMASK) || (mod & NX_DEVICERSHIFTKEYMASK)) mod |= NX_SHIFTMASK; else mod &= ~NX_SHIFTMASK;
        if((mod & NX_DEVICELCTLKEYMASK) || (mod & NX_DEVICERCTLKEYMASK)) mod |= NX_CONTROLMASK; else mod &= ~NX_CONTROLMASK;
        if((mod & NX_DEVICELCMDKEYMASK) || (mod & NX_DEVICERCMDKEYMASK)) mod |= NX_COMMANDMASK; else mod &= ~NX_COMMANDMASK;
        if((mod & NX_DEVICELALTKEYMASK) || (mod & NX_DEVICERALTKEYMASK)) mod |= NX_ALTERNATEMASK; else mod &= ~NX_ALTERNATEMASK;
        kb->modifiers = mod;
        kb->lastkeypress = KEY_NONE;
        isMod = 1;
    } else if(!isMod){
        // For any other key, trigger key repeat
        if(down){
            long repeat = repeattime(kb->event, 1);
            if(repeat > 0){
                kb->lastkeypress = scancode;
                clock_gettime(CLOCK_MONOTONIC, &kb->keyrepeat);
                timespec_add(&kb->keyrepeat, repeat);
            } else
                kb->lastkeypress = KEY_NONE;
        } else
            kb->lastkeypress = KEY_NONE;
    }

    postevent_kp(kb->event, kb->modifiers, scancode, down, isMod, 0);
}