You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
283 lines
7.4 KiB
283 lines
7.4 KiB
#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;
|
|
}
|
|
|