예제 #1
0
파일: usb_mac.c 프로젝트: akosipc/ckb
int os_usbrecv(usbdevice* kb, uchar* in_msg, const char* file, int line){
    CFIndex length = MSG_SIZE;
    kern_return_t res = (*kb->handle)->getReport(kb->handle, kIOHIDReportTypeFeature, 0, in_msg, &length, 5000, 0, 0, 0);
    kb->lastresult = res;
    if(IS_TEMP_FAILURE(res)){
        ckb_warn_fn("Got return value 0x%x (continuing)\n", file, line, res);
        return -1;
    } else if(res != kIOReturnSuccess){
        ckb_err_fn("Got return value 0x%x\n", file, line, res);
        return 0;
    }
    if(length != MSG_SIZE)
        ckb_err_fn("Read %d bytes (expected %d)\n", file, line, (int)length, MSG_SIZE);
    return length;
}
예제 #2
0
int os_usbrecv(usbdevice* kb, uchar* in_msg, const char* file, int line){
    DELAY_MEDIUM(kb);
    int res;
    if(kb->fwversion >= 0x130){
        struct usbdevfs_bulktransfer transfer;
        memset(&transfer, 0, sizeof(transfer));
        transfer.ep = 0x84;
        transfer.len = MSG_SIZE;
        transfer.timeout = 5000;
        transfer.data = in_msg;
        res = ioctl(kb->handle, USBDEVFS_BULK, &transfer);
    } else {
        struct usbdevfs_ctrltransfer transfer = { 0xa1, 0x01, 0x0300, 0x03, MSG_SIZE, 5000, in_msg };
        res = ioctl(kb->handle, USBDEVFS_CONTROL, &transfer);
    }
    if(res <= 0){
        if(res == -1 && errno == ETIMEDOUT){
            ckb_warn_fn("%s (continuing)\n", file, line, strerror(errno));
            return -1;
        }
        ckb_err_fn("%s\n", file, line, res ? strerror(errno) : "No data read");
        return 0;
    } else if(res != MSG_SIZE)
        ckb_warn_fn("Read %d bytes (expected %d)\n", file, line, res, MSG_SIZE);
    return res;
}
예제 #3
0
int os_usbsend(usbdevice* kb, const uchar* out_msg, int is_recv, const char* file, int line){
    int res;
    if(kb->fwversion >= 0x120){
        struct usbdevfs_bulktransfer transfer;
        memset(&transfer, 0, sizeof(transfer));
        transfer.ep = (kb->fwversion >= 0x130) ? 4 : 3;
        transfer.len = MSG_SIZE;
        transfer.timeout = 5000;
        transfer.data = (void*)out_msg;
        res = ioctl(kb->handle, USBDEVFS_BULK, &transfer);
    } else {
        struct usbdevfs_ctrltransfer transfer = { 0x21, 0x09, 0x0300, 0x03, MSG_SIZE, 5000, (void*)out_msg };
        res = ioctl(kb->handle, USBDEVFS_CONTROL, &transfer);
    }
    if(res <= 0){
        if(res == -1 && errno == ETIMEDOUT){
            ckb_warn_fn("%s (continuing)\n", file, line, strerror(errno));
            return -1;
        }
        ckb_err_fn("%s\n", file, line, res ? strerror(errno) : "No data written");
        return 0;
    } else if(res != MSG_SIZE)
        ckb_warn_fn("Wrote %d bytes (expected %d)\n", file, line, res, MSG_SIZE);
    return res;
}
예제 #4
0
파일: usb_linux.c 프로젝트: MadMartian/ckb
int os_usbrecv(usbdevice* kb, uchar* in_msg, const char* file, int line){
    int res;
    // This is what CUE does, but it doesn't seem to work on linux.
    /*if(kb->fwversion >= 0x130){
        struct usbdevfs_bulktransfer transfer;
        memset(&transfer, 0, sizeof(transfer));
        transfer.ep = 0x84;
        transfer.len = MSG_SIZE;
        transfer.timeout = 5000;
        transfer.data = in_msg;
        res = ioctl(kb->handle - 1, USBDEVFS_BULK, &transfer);
    } else {*/
        struct usbdevfs_ctrltransfer transfer = { 0xa1, 0x01, 0x0300, kb->epcount - 1, MSG_SIZE, 5000, in_msg };
        res = ioctl(kb->handle - 1, USBDEVFS_CONTROL, &transfer);
    //}
    if(res <= 0){
        ckb_err_fn("%s\n", file, line, res ? strerror(errno) : "No data read");
        if(res == -1 && errno == ETIMEDOUT)
            return -1;
        else
            return 0;
    } else if(res != MSG_SIZE)
        ckb_warn_fn("Read %d bytes (expected %d)\n", file, line, res, MSG_SIZE);
    return res;
}
예제 #5
0
파일: usb_linux.c 프로젝트: MadMartian/ckb
int os_usbsend(usbdevice* kb, const uchar* out_msg, int is_recv, const char* file, int line){
    int res;
    if(kb->fwversion >= 0x120 && !is_recv){
        struct usbdevfs_bulktransfer transfer;
        memset(&transfer, 0, sizeof(transfer));
        transfer.ep = (kb->fwversion >= 0x130 && kb->fwversion < 0x200) ? 4 : 3;
        transfer.len = MSG_SIZE;
        transfer.timeout = 5000;
        transfer.data = (void*)out_msg;
        res = ioctl(kb->handle - 1, USBDEVFS_BULK, &transfer);
    } else {
        struct usbdevfs_ctrltransfer transfer = { 0x21, 0x09, 0x0200, kb->epcount - 1, MSG_SIZE, 5000, (void*)out_msg };
        res = ioctl(kb->handle - 1, USBDEVFS_CONTROL, &transfer);
    }
    if(res <= 0){
        ckb_err_fn("%s\n", file, line, res ? strerror(errno) : "No data written");
        if(res == -1 && errno == ETIMEDOUT)
            return -1;
        else
            return 0;
    } else if(res != MSG_SIZE)
        ckb_warn_fn("Wrote %d bytes (expected %d)\n", file, line, res, MSG_SIZE);
#ifdef DEBUG_USB
    char converted[MSG_SIZE*3 + 1];
    for(int i=0;i<MSG_SIZE;i++)
        sprintf(&converted[i*3], "%02x ", out_msg[i]);
    ckb_warn_fn("Sent %s\n", file, line, converted);
#endif
    return res;
}
예제 #6
0
파일: usb.c 프로젝트: gtjoseph/ckb
int _usbrecv(usbdevice* kb, const uchar* out_msg, uchar* in_msg, const char* file, int line){
    // Try a maximum of 3 times
    for(int try = 0; try < 5; try++){
        // Send the output message
        DELAY_SHORT(kb);
        int res = os_usbsend(kb, out_msg, 1, file, line);
        if(res == 0)
            return 0;
        else if(res == -1){
            // Retry on temporary failure
            if(reset_stop)
                return 0;
            DELAY_LONG(kb);
            continue;
        }
        // Wait for the response
        DELAY_MEDIUM(kb);
        res = os_usbrecv(kb, in_msg, file, line);
        if(res == 0)
            return 0;
        else if(res != -1)
            return res;
        if(reset_stop || hwload_mode != 2)
            return 0;
        DELAY_LONG(kb);
    }
    // Give up
    ckb_err_fn("Too many send/recv failures. Dropping.\n", file, line);
    return 0;
}

int closeusb(usbdevice* kb){
    pthread_mutex_lock(imutex(kb));
    if(kb->handle){
        int index = INDEX_OF(kb, keyboard);
        ckb_info("Disconnecting %s%d\n", devpath, index);
        os_inputclose(kb);
        updateconnected();
        // Close USB device
        os_closeusb(kb);
    } else
        updateconnected();
    rmdevpath(kb);

    // Wait for thread to close
    pthread_mutex_unlock(imutex(kb));
    pthread_mutex_unlock(dmutex(kb));
    pthread_join(kb->thread, 0);
    pthread_mutex_lock(dmutex(kb));

    // Delete the profile and the control path
    if(!kb->vtable)
        return 0;
    kb->vtable->freeprofile(kb);
    memset(kb, 0, sizeof(usbdevice));
    return 0;
}
예제 #7
0
int _nk95cmd(usbdevice* kb, uchar bRequest, ushort wValue, const char* file, int line){
    if(kb->product != P_K95_NRGB)
        return 0;
    struct usbdevfs_ctrltransfer transfer = { 0x40, bRequest, wValue, 0, 0, 5000, 0 };
    int res = ioctl(kb->handle, USBDEVFS_CONTROL, &transfer);
    if(res < 0){
        ckb_err_fn("%s\n", file, line, strerror(-res));
        return 1;
    }
    return 0;
}
예제 #8
0
파일: usb_mac.c 프로젝트: akosipc/ckb
int os_usbsend(usbdevice* kb, const uchar* out_msg, int is_recv, const char* file, int line){
    // Firmware versions above 1.20 use Output instead of Feature reports for improved performance
    // It doesn't work well when receiving data, however (Not sure why...linux doesn't have that problem)
    IOHIDReportType type = (kb->fwversion >= 0x120 && !is_recv ? kIOHIDReportTypeOutput : kIOHIDReportTypeFeature);
    kern_return_t res = (*kb->handle)->setReport(kb->handle, type, 0, out_msg, MSG_SIZE, 5000, 0, 0, 0);
    kb->lastresult = res;
    if(IS_TEMP_FAILURE(res)){
        ckb_warn_fn("Got return value 0x%x (continuing)\n", file, line, res);
        return -1;
    } else if(res != kIOReturnSuccess){
        ckb_err_fn("Got return value 0x%x\n", file, line, res);
        return 0;
    }
    return MSG_SIZE;
}