#include "g-wolves.h" #define DEVICE_WIRELESS(handle) (is_connection_wireless(handle)) static int send_command(libusb_device_handle* hand, uint8_t command, uint8_t size, void* report, bool wireless) { report_header_t* head = report; head->report_size = size; head->command = command; if(wireless) head->wireless = 0x1; // Send command int res = libusb_control_transfer(hand, 0x21, // request type 0x09, // request (SET_REPORT) 0x300, // wValue (FEATURE << 8 | REPORT(0)) 0x2, // wIndex = 0x2 : interface report, REPORT_MAX_SIZE, // wLength = 64 0 /* timeout*/); if(res <= 0) return res; // Wait for mouse if necessary if(wireless) usleep(100000); // Get response report res = libusb_control_transfer(hand, 0xa1, // request type 0x01, // request (GET_REPORT) 0x300, // wValue (FEATURE << 8 | REPORT(0)) 0x2, // wIndex = 0x2 : interface report, REPORT_MAX_SIZE, // wLength = 64 0); return res; } void driver_init(void) {} uint32_t driver_getkey(void) { static int count = 0; count++; // Register ALL G-Wolves compatible devices uint16_t id = 0; switch(count) { case 1: id = HTX_4K_PRODUCT_ID_WIRED; break; case 2: id = HTX_4K_PRODUCT_ID_WIRELESS; break; case 3: id = HTS_PLUS_4K_PRODUCT_ID_WIRED; break; case 4: id = HTS_PLUS_4K_PRODUCT_ID_WIRELESS; break; case 5: id = HSK_PRO_ACE_PRODUCT_ID_WIRED; break; case 6: id = HSK_PRO_ACE_PRODUCT_ID_WIRELESS; break; default: id = 0; } if(id == 0) return 0; return (VENDOR_ID << 16) | id; } device_capacity_t driver_get_capacity(void* handle) { libusb_device* dev = handle; struct libusb_device_descriptor desc; libusb_get_device_descriptor(dev, &desc); uint8_t wireless = 0; switch(desc.idProduct) { case HTX_4K_PRODUCT_ID_WIRED: case HTX_4K_PRODUCT_ID_WIRELESS: case HTS_PLUS_4K_PRODUCT_ID_WIRED: case HTS_PLUS_4K_PRODUCT_ID_WIRELESS: case HSK_PRO_ACE_PRODUCT_ID_WIRED: case HSK_PRO_ACE_PRODUCT_ID_WIRELESS: wireless = DEVICE_CAPACITY_WIRELESS; break; } return DEVICE_CAPACITY_MOUSE | wireless; } char* driver_get_manufacturer(void* handle) { return MANUFACTURER_NAME; } char* driver_get_name(void* handle) { libusb_device* dev = handle; struct libusb_device_descriptor desc; libusb_get_device_descriptor(dev, &desc); switch(desc.idProduct) { case HTX_4K_PRODUCT_ID_WIRED: case HTX_4K_PRODUCT_ID_WIRELESS: return HTX_4K_PRODUCT_NAME; case HTS_PLUS_4K_PRODUCT_ID_WIRED: case HTS_PLUS_4K_PRODUCT_ID_WIRELESS: return HTS_PLUS_4K_PRODUCT_NAME; case HSK_PRO_ACE_PRODUCT_ID_WIRED: case HSK_PRO_ACE_PRODUCT_ID_WIRELESS: return HSK_PRO_ACE_PRODUCT_NAME; default: return "Unknown G-Wolves mice"; } } char* driver_get_image(void* handle) { libusb_device* dev = handle; struct libusb_device_descriptor desc; libusb_get_device_descriptor(dev, &desc); switch(desc.idProduct) { case HTX_4K_PRODUCT_ID_WIRED: case HTX_4K_PRODUCT_ID_WIRELESS: return HTX_IMAGE; case HTS_PLUS_4K_PRODUCT_ID_WIRED: case HTS_PLUS_4K_PRODUCT_ID_WIRELESS: return HTS_PLUS_IMAGE; case HSK_PRO_ACE_PRODUCT_ID_WIRED: case HSK_PRO_ACE_PRODUCT_ID_WIRELESS: return HSK_PRO_IMAGE; default: return ""; } } static bool is_connection_wireless(void* handle) { libusb_device* dev = handle; struct libusb_device_descriptor desc; libusb_get_device_descriptor(dev, &desc); switch(desc.idProduct) { case HTX_4K_PRODUCT_ID_WIRELESS: case HTS_PLUS_4K_PRODUCT_ID_WIRELESS: case HSK_PRO_ACE_PRODUCT_ID_WIRELESS: return true; } return false; } int driver_mouse_dpi_get(void* handle, struct MOUSE_DPI_LEVELS* output) { libusb_device* dev = handle; // Prepare usb device for transfer libusb_device_handle* hand; int openres = libusb_open(dev, &hand); if(openres) return -1; libusb_detach_kernel_driver(hand, 0x2); // Send command struct REPORT_DPI_SETTINGS report = {0}; int res = send_command(hand, COMMAND_DPI_SETTINGS, REPORT_DPI_SETTINGS_SIZE, &report, DEVICE_WIRELESS(handle)); if(res <= 0) return -1; // Format 'output' packet output->max_level_count = 5; output->level_count = report.level_count; output->level_current = report.level_current - 1; output->led_available = true; output->xy_available = false; for(size_t i = 0; i < report.level_count; i++) { output->level[i].dpi_x = report.levels[i].dpi_x_high << 8 | report.levels[i].dpi_x_low; output->level[i].dpi_y = report.levels[i].dpi_y_high << 8 | report.levels[i].dpi_y_low; output->level[i].r = report.levels[i].led_r; output->level[i].g = report.levels[i].led_g; output->level[i].b = report.levels[i].led_b; } libusb_attach_kernel_driver(hand, 0x2); libusb_close(hand); return 0; } int driver_mouse_motion_sync_get(void* handle, bool* output) { libusb_device* dev = handle; // Prepare usb device for transfer libusb_device_handle* hand; int openres = libusb_open(dev, &hand); if(openres) return -1; libusb_detach_kernel_driver(hand, 0x2); // Send command struct REPORT_MOTION_SYNC report = {0}; int res = send_command(hand, COMMAND_MOTION_SYNC, REPORT_MOTION_SYNC_SIZE, &report, DEVICE_WIRELESS(handle)); if(res <= 0) return -1; // Format output boolean *output = report.motion_sync; // Close and return libusb_attach_kernel_driver(hand, 0x2); libusb_close(hand); return 0; } int driver_mouse_angle_snap_get(void* handle, bool* output) { libusb_device* dev = handle; // Prepare usb device for transfer libusb_device_handle* hand; int openres = libusb_open(dev, &hand); if(openres) return -1; libusb_detach_kernel_driver(hand, 0x2); // Send command struct REPORT_ANGLE_SNAP report = {0}; int res = send_command(hand, COMMAND_ANGLE_SNAP, REPORT_ANGLE_SNAP_SIZE, &report, DEVICE_WIRELESS(handle)); if(res <= 0) return -1; // Format output boolean *output = report.angle_snap; // Close and return libusb_attach_kernel_driver(hand, 0x2); libusb_close(hand); return 0; } int driver_wireless_connection_type_get(void* handle, bool* output) { *output = is_connection_wireless(handle); return 0; } int driver_wireless_battery_state_get(void* handle, int* battery_level, bool* charging) { libusb_device* dev = handle; // Prepare usb device for transfer libusb_device_handle* hand; int openres = libusb_open(dev, &hand); if(openres) return -1; libusb_detach_kernel_driver(hand, 0x2); // Send command struct REPORT_BATTERY report = {0}; int res = send_command(hand, COMMAND_BATTERY, REPORT_BATTERY_SIZE, &report, DEVICE_WIRELESS(handle)); if(res <= 0) return -1; // Format output values *battery_level = report.battery_level; *charging = report.battery_status; // Close and return libusb_attach_kernel_driver(hand, 0x2); libusb_close(hand); return 0; }