diff --git a/src/ckb-daemon/keymap.c b/src/ckb-daemon/keymap.c index b4486ca0..4cb30ef7 100644 --- a/src/ckb-daemon/keymap.c +++ b/src/ckb-daemon/keymap.c @@ -388,8 +388,9 @@ void hid_kb_translate(unsigned char* kbinput, int endpoint, int length, const un #define BUTTON_HID_COUNT 5 -void hid_mouse_translate(unsigned char* kbinput, short* xaxis, short* yaxis, int endpoint, int length, const unsigned char* urbinput){ - if((endpoint != 2 && endpoint != -2) || length < 10) +void hid_mouse_translate(unsigned char* kbinput, short* xaxis, short* yaxis, int endpoint, int length, const unsigned char* urbinput, ushort fwversion){ + //The HID Input Endpoint on FWv3 is 64 bytes, so we can't check for length. + if((endpoint != 2 && endpoint != -2) || (fwversion < 0x300 && length < 10)) return; // EP 2: mouse input if(urbinput[0] != 1) diff --git a/src/ckb-daemon/keymap.h b/src/ckb-daemon/keymap.h index 5ba765e6..d06b648e 100644 --- a/src/ckb-daemon/keymap.h +++ b/src/ckb-daemon/keymap.h @@ -64,7 +64,7 @@ extern const key keymap[N_KEYS_EXTENDED]; // Translates input from HID to a ckb input bitfield. // Use positive endpoint for non-RGB keyboards, negative endpoint for RGB void hid_kb_translate(unsigned char* kbinput, int endpoint, int length, const unsigned char* urbinput); -void hid_mouse_translate(unsigned char* kbinput, short* xaxis, short* yaxis, int endpoint, int length, const unsigned char* urbinput); +void hid_mouse_translate(unsigned char* kbinput, short* xaxis, short* yaxis, int endpoint, int length, const unsigned char* urbinput, ushort fwversion); // Copies input from Corsair reports void corsair_kbcopy(unsigned char* kbinput, int endpoint, const unsigned char* urbinput); diff --git a/src/ckb-daemon/led_keyboard.c b/src/ckb-daemon/led_keyboard.c index d7b53f57..dd904897 100644 --- a/src/ckb-daemon/led_keyboard.c +++ b/src/ckb-daemon/led_keyboard.c @@ -146,7 +146,7 @@ int updatergb_kb(usbdevice* kb, int force){ } int savergb_kb(usbdevice* kb, lighting* light, int mode){ - if(kb->fwversion >= 0x0120 || IS_NEW_PROTOCOL(kb)){ + if(kb->fwversion >= 0x0120 || IS_V2_OVERRIDE(kb)){ uchar data_pkt[12][MSG_SIZE] = { // Red { 0x7f, 0x01, 60, 0 }, @@ -188,7 +188,7 @@ int savergb_kb(usbdevice* kb, lighting* light, int mode){ } int loadrgb_kb(usbdevice* kb, lighting* light, int mode){ - if(kb->fwversion >= 0x0120 || IS_NEW_PROTOCOL(kb)){ + if(kb->fwversion >= 0x0120 || IS_V2_OVERRIDE(kb)){ uchar data_pkt[12][MSG_SIZE] = { { 0x0e, 0x14, 0x03, 0x01, 0x01, mode + 1, 0x01 }, { 0xff, 0x01, 60, 0 }, diff --git a/src/ckb-daemon/usb.h b/src/ckb-daemon/usb.h index 67d500f4..f8fa4394 100644 --- a/src/ckb-daemon/usb.h +++ b/src/ckb-daemon/usb.h @@ -169,7 +169,7 @@ const char* product_str(short product); #define IS_PLATINUM(kb) ((kb)->vendor == V_CORSAIR && ((kb)->product == P_K95_PLATINUM)) /// Used when a device has a firmware with a low version number that uses the new protocol -#define IS_NEW_PROTOCOL(kb) (IS_PLATINUM(kb) || IS_K63(kb) || IS_K68(kb) || IS_HARPOON(kb) || IS_GLAIVE(kb) || (kb)->product == P_STRAFE_NRGB_2) +#define IS_V2_OVERRIDE(kb) (IS_PLATINUM(kb) || IS_K63(kb) || IS_K68(kb) || IS_HARPOON(kb) || IS_GLAIVE(kb) || (kb)->product == P_STRAFE_NRGB_2) /// USB delays for when the keyboards get picky about timing /// That was the original comment, but it is used anytime. diff --git a/src/ckb-daemon/usb_linux.c b/src/ckb-daemon/usb_linux.c index 07b1420b..27f381a6 100644 --- a/src/ckb-daemon/usb_linux.c +++ b/src/ckb-daemon/usb_linux.c @@ -67,9 +67,10 @@ static char kbsyspath[DEV_MAX][FILENAME_MAX]; /// int os_usbsend(usbdevice* kb, const uchar* out_msg, int is_recv, const char* file, int line) { int res; - if ((kb->fwversion >= 0x120 || IS_NEW_PROTOCOL(kb)) && !is_recv){ + if ((kb->fwversion >= 0x120 || IS_V2_OVERRIDE(kb)) && !is_recv){ struct usbdevfs_bulktransfer transfer = {0}; - transfer.ep = (kb->fwversion >= 0x130 && kb->fwversion < 0x200) ? 4 : 3; + // FW 2.XX uses 0x03, FW 3.XX uses 0x02 + transfer.ep = (kb->fwversion >= 0x130 && kb->fwversion < 0x200) ? 4 : (kb->fwversion >= 0x300 ? 2 : 3); transfer.len = MSG_SIZE; transfer.timeout = 5000; transfer.data = (void*)out_msg; @@ -212,7 +213,16 @@ int _nk95cmd(usbdevice* kb, uchar bRequest, ushort wValue, const char* file, int /// void os_sendindicators(usbdevice* kb) { static int countForReset = 0; - struct usbdevfs_ctrltransfer transfer = { 0x21, 0x09, 0x0200, 0x00, 1, 500, &kb->ileds }; + void *ileds; + ushort leds; + if(kb->fwversion >= 0x300) { + leds = (kb->ileds << 8) | 0x0001; + ileds = &leds; + } + else { + ileds = &kb->ileds; + } + struct usbdevfs_ctrltransfer transfer = { 0x21, 0x09, 0x0200, 0x00, (kb->fwversion >= 0x300 ? 2 : 1), 500, ileds }; int res = ioctl(kb->handle - 1, USBDEVFS_CONTROL, &transfer); if(res <= 0) { ckb_err("%s\n", res ? strerror(errno) : "No data written"); @@ -262,14 +272,14 @@ void* os_inputmain(void* context){ /// /// device | detect with macro combination | endpoint # | buffer-length /// ------ | ----------------------------- | ---------- | ------------- - /// each | none | 0 | 8 + /// each | none | 0 | 8, 64 for FW v3 /// RGB Mouse | IS_RGB && IS_MOUSE | 1 | 10 /// RGB Keyboard | IS_RGB && !IS_MOUSE | 1 | 21 /// RGB Mouse or Keyboard | IS_RGB | 2 | MSG_SIZE (64) /// non RGB Mouse or Keyboard | !IS_RGB | 1 | 4 /// non RGB Mouse or Keyboard | !IS_RGB | 2 | 15 /// - urbs[0].buffer_length = 8; + urbs[0].buffer_length = (kb->fwversion >= 0x300 ? MSG_SIZE : 8); if(urbcount > 1 && IS_RGB(vendor, product)) { if(IS_MOUSE(vendor, product)) urbs[1].buffer_length = 10; @@ -278,9 +288,9 @@ void* os_inputmain(void* context){ urbs[2].buffer_length = MSG_SIZE; if(urbcount != 3) urbs[urbcount - 1].buffer_length = MSG_SIZE; - } else { - urbs[1].buffer_length = 4; - urbs[2].buffer_length = 15; + } else if(kb->fwversion < 0x300) { + urbs[1].buffer_length = 4; + urbs[2].buffer_length = 15; } /// Now submit all the URBs via ioctl(USBDEVFS_SUBMITURB) with type USBDEVFS_URB_TYPE_INTERRUPT (the endpoints are defined as type interrupt). @@ -330,17 +340,20 @@ void* os_inputmain(void* context){ /// non RGB Keyboard | !IS_RGB && !IS_MOUSE | nA | nA | hid_kb_translate() /// pthread_mutex_lock(imutex(kb)); + // EP workaround for FWv3 + // Corsair input comes through 0x81, but case 1 in keymap.c is used for 6KRO + uchar urbendpoint = (kb->fwversion >= 0x300 ? 2 : (urb->endpoint & 0xF)); if(IS_MOUSE(vendor, product)){ switch(urb->actual_length){ case 8: case 10: case 11: // HID mouse input - hid_mouse_translate(kb->input.keys, &kb->input.rel_x, &kb->input.rel_y, -(urb->endpoint & 0xF), urb->actual_length, urb->buffer); + hid_mouse_translate(kb->input.keys, &kb->input.rel_x, &kb->input.rel_y, -urbendpoint, urb->actual_length, urb->buffer, kb->fwversion); break; case MSG_SIZE: // Corsair mouse input - corsair_mousecopy(kb->input.keys, -(urb->endpoint & 0xF), urb->buffer); + corsair_mousecopy(kb->input.keys, -urbendpoint, urb->buffer); break; } } else if(IS_RGB(vendor, product)){ @@ -357,7 +370,7 @@ void* os_inputmain(void* context){ break; case MSG_SIZE: // RGB EP 3: Corsair input - corsair_kbcopy(kb->input.keys, -(urb->endpoint & 0xF), urb->buffer); + corsair_kbcopy(kb->input.keys, -urbendpoint, urb->buffer); break; } } else { diff --git a/src/ckb-daemon/usb_mac.c b/src/ckb-daemon/usb_mac.c index 568673f8..ef73e01e 100644 --- a/src/ckb-daemon/usb_mac.c +++ b/src/ckb-daemon/usb_mac.c @@ -103,7 +103,7 @@ int os_usbsend(usbdevice* kb, const uchar* out_msg, int is_recv, const char* fil kern_return_t res = kIOReturnSuccess; /// /// \todo Be aware: This condition is exact inverted to the condition in the linux dependent os_usbsend(). It may be correct, but please check it. - if((kb->fwversion < 0x120 && !IS_NEW_PROTOCOL(kb)) || is_recv){ + if((kb->fwversion < 0x120 && !IS_V2_OVERRIDE(kb)) || is_recv){ int ep = kb->epcount; // For old devices, or for receiving data, use control transfers IOUSBDevRequestTO rq = { 0x21, 0x09, 0x0200, ep - 1, MSG_SIZE, (void*)out_msg, 0, 5000, 5000 }; @@ -119,7 +119,8 @@ int os_usbsend(usbdevice* kb, const uchar* out_msg, int is_recv, const char* fil } } else { // For newer devices, use interrupt transfers - int ep = (kb->fwversion >= 0x130 && kb->fwversion < 0x200) ? 4 : 3; + // macOS sees 4 endpoints (including ep0) for FW 3.XX + int ep = (kb->fwversion >= 0x130 && (kb->fwversion < 0x200 || kb->fwversion >= 0x300)) ? 4 : 3; usb_iface_t h_usb = kb->ifusb[ep - 1]; hid_dev_t h_hid = kb->ifhid[ep - 1]; if(h_usb) @@ -176,7 +177,16 @@ int _nk95cmd(usbdevice* kb, uchar bRequest, ushort wValue, const char* file, int } void os_sendindicators(usbdevice* kb){ - IOUSBDevRequestTO rq = { 0x21, 0x09, 0x0200, 0x00, 1, &kb->ileds, 0, 500, 500 }; + void *ileds; + ushort leds; + if(kb->fwversion >= 0x300) { + leds = (kb->ileds << 8) | 0x0001; + ileds = &leds; + } + else { + ileds = &kb->ileds; + } + IOUSBDevRequestTO rq = { 0x21, 0x09, 0x0200, 0x00, (kb->fwversion >= 0x300 ? 2 : 1), ileds, 0, 500, 500 }; kern_return_t res = (*kb->handle)->DeviceRequestTO(kb->handle, &rq); if(res == kIOReturnNotOpen){ // Handle not open - try to go through the HID system instead @@ -229,7 +239,7 @@ static void intreport(void* context, IOReturn result, void* sender, IOHIDReportT case 8: case 10: case 11: - hid_mouse_translate(kb->input.keys, &kb->input.rel_x, &kb->input.rel_y, -2, length, data); + hid_mouse_translate(kb->input.keys, &kb->input.rel_x, &kb->input.rel_y, -2, length, data, kb->fwversion); break; case MSG_SIZE: corsair_mousecopy(kb->input.keys, kb->epcount >= 4 ? -3 : -2, data); @@ -773,7 +783,9 @@ static usbdevice* add_hid(hid_dev_t handle, io_object_t** rm_notify){ long input = hidgetlong(handle, CFSTR(kIOHIDMaxInputReportSizeKey)); long output = hidgetlong(handle, CFSTR(kIOHIDMaxOutputReportSizeKey)); long feature = hidgetlong(handle, CFSTR(kIOHIDMaxFeatureReportSizeKey)); + long fwversion = hidgetlong(handle, CFSTR(kIOHIDVersionNumberKey)); int handle_idx; + // Handle 3 is for controlling the device (only exists for RGB) if(feature == 64) handle_idx = 3; @@ -785,9 +797,13 @@ static usbdevice* add_hid(hid_dev_t handle, io_object_t** rm_notify){ (input <= 1 && output == 64))) // FW >= 2.00 (Scimitar) handle_idx = 2; // Handle 0 is for BIOS mode input (RGB) or non-RGB key input - else if(output <= 1 && feature <= 1 && - (input == 8 || // Keyboards - input == 7)) // Mice + else if((output <= 1 && feature <= 1 && + (input == 8 || // Keyboards + input == 7)) || // Mice + (fwversion >= 0x300 && // FWv3 hack + input == 64 && + output <= 2 && + feature == 1)) handle_idx = 0; // Handle 1 is for standard HID input (RGB) or media keys (non-RGB) else if(output <= 1 && feature <= 1 &&