Sinowealth detector cleaned and broken down to atomic units

This commit is contained in:
Dmitry K 2023-08-21 05:16:23 +00:00 committed by Adam Honse
parent f3763a1b5c
commit c98464d9df

View file

@ -52,17 +52,17 @@ struct expected_report
expected_report(unsigned int id, unsigned size, unsigned char* cmd_buf, unsigned int cmd_size) : id(id), size(size), cmd_buf(cmd_buf), cmd_size(cmd_size) {}
};
typedef std::vector<expected_report*> expected_reports;
typedef std::vector<expected_report> expected_reports;
int GetDeviceCount(hid_device_info* info, unsigned int &device_count_total, unsigned int device_count_expected)
static int GetDeviceCount(hid_device_info* info, unsigned int &device_count_total, unsigned int device_count_expected)
{
hid_device_info* info_temp = info;
while(info_temp)
{
if (info_temp->vendor_id == info->vendor_id // constant SINOWEALTH_VID
&& info_temp->product_id == info->product_id // NON-constant
&& info_temp->usage_page == info->usage_page) // constant 0xFF00
if(info_temp->vendor_id == info->vendor_id // constant SINOWEALTH_VID
&& info_temp->product_id == info->product_id // NON-constant
&& info_temp->usage_page == info->usage_page) // constant 0xFF00
{
device_count_total++;
}
@ -80,7 +80,7 @@ int GetDeviceCount(hid_device_info* info, unsigned int &device_count_total, unsi
return false;
}
bool DetectUsages(hid_device_info* info, std::string name, unsigned int device_count_expected, expected_reports& reports)
static bool DetectUsages(hid_device_info* info, std::string name, unsigned int device_count_expected, expected_reports& reports)
{
hid_device_info* info_temp = info;
hid_device* device = nullptr;
@ -116,9 +116,9 @@ bool DetectUsages(hid_device_info* info, std::string name, unsigned int device_c
/*----------------------------------------------------------------*\
| If it's still our device |
\*----------------------------------------------------------------*/
if(info_temp->vendor_id == info->vendor_id // constant SINOWEALTH_VID
&& info_temp->product_id == info->product_id // NON-constant
&& info_temp->usage_page == info->usage_page) // constant 0xFF00
if(info_temp->vendor_id == info->vendor_id // constant SINOWEALTH_VID
&& info_temp->product_id == info->product_id // NON-constant
&& info_temp->usage_page == info->usage_page) // constant 0xFF00
{
/*----------------------------------------------------------*\
| Open current device to check if it has expected report IDs |
@ -133,44 +133,47 @@ bool DetectUsages(hid_device_info* info, std::string name, unsigned int device_c
return false;
}
for (expected_report* report: reports)
for(expected_report& report: reports)
{
/*-----------------------------------------------------------*\
| We shouldn't do any checks if device is already found |
\*-----------------------------------------------------------*/
if(report->device != nullptr) continue;
if(report.device != nullptr)
{
continue;
}
memset(tmp_buf, 0x00, sizeof(tmp_buf));
tmp_buf[0] = report->id;
tmp_buf[0] = report.id;
/*--------------------------------------------------------------------------------------*\
| If we need to send a command before requesting data, send it and flag the report |
| (DON'T TRY TO CREATE MORE THAN 1 EXPECTED REPORT SENDING COMMANDS) |
\*--------------------------------------------------------------------------------------*/
if(report->cmd_buf != nullptr && report->cmd_device == nullptr)
if(report.cmd_buf != nullptr && report.cmd_device == nullptr)
{
if (hid_send_feature_report(device, report->cmd_buf, report->cmd_size) > -1)
if(hid_send_feature_report(device, report.cmd_buf, report.cmd_size) > -1)
{
restart_flag = true; // Because Windows
report->cmd_device = device;
LOG_TRACE("[%s] Successfully sent command for ReportId 0x%02X to device at location \"HID: %s\", handle: %08X", name.c_str(), report->id, info_temp->path, device);
report.cmd_device = device;
LOG_TRACE("[%s] Successfully sent command for ReportId 0x%02X to device at location \"HID: %s\", handle: %08X", name.c_str(), report.id, info_temp->path, device);
}
}
/*------------------------------------------------------*\
| Now we try to request data for expected feature report |
\*------------------------------------------------------*/
if(report->cmd_buf == nullptr || report->cmd_device != nullptr)
if(report.cmd_buf == nullptr || report.cmd_device != nullptr)
{
/*---------------------------------------------------------------------------*\
| If device actually responds to expected report ID, set a flag |
\*---------------------------------------------------------------------------*/
if(hid_get_feature_report(device, tmp_buf, report->size) > -1)
if(hid_get_feature_report(device, tmp_buf, report.size) > -1)
{
device_count++;
report_found = true;
report->device = device;
LOG_TRACE("[%s] Successfully requested feature ReportId 0x%02X from device at location \"HID: %s\", handle: %08X", name.c_str(), report->id, info_temp->path, device);
report.device = device;
LOG_TRACE("[%s] Successfully requested feature ReportId 0x%02X from device at location \"HID: %s\", handle: %08X", name.c_str(), report.id, info_temp->path, device);
}
}
}
@ -199,11 +202,11 @@ bool DetectUsages(hid_device_info* info, std::string name, unsigned int device_c
\*-----------------------------------------------------------*/
if(device_count < reports.size())
{
for (expected_report* report: reports)
for(expected_report& report: reports)
{
if(report->device != nullptr)
if(report.device != nullptr)
{
hid_close(report->device);
hid_close(report.device);
}
}
@ -214,28 +217,71 @@ bool DetectUsages(hid_device_info* info, std::string name, unsigned int device_c
return true;
}
void DetectSinowealthMouse(hid_device_info* info, const std::string& name)
static void DetectZetFuryPro(hid_device_info* info, const std::string& name)
{
unsigned int pid = info->product_id;
#ifdef USE_HID_USAGE
/*-------------------------------------------------------------------------------------------------*\
| Sinowealth devices use 3 (or more) different Report IDs on the same Usage Page. |
| The 4 on 0xFF00 is for RGB, 7 is Unknown and 5 (or 8, or whatever...) is for Commands. |
\*-------------------------------------------------------------------------------------------------*/
expected_reports* reports = new expected_reports();
RGBController *rgb_controller;
if(pid == ZET_FURY_PRO_PID)
expected_reports reports{expected_report(0x04, 59)};
if(!DetectUsages(info, name, 5, reports))
{
reports->emplace_back(new expected_report(0x04, 59));
if(!DetectUsages(info, name, 5, *reports)) return;
SinowealthController1007* controller = new SinowealthController1007(reports->at(0)->device, info->path);
rgb_controller = new RGBController_Sinowealth1007(controller);
return;
}
hid_device* dev = reports.at(0).device;
#else
hid_device* dev = hid_open_path(info->path);
#endif
if(dev)
{
SinowealthController1007* controller = new SinowealthController1007(dev, info->path);
RGBController *rgb_controller = new RGBController_Sinowealth1007(controller);
rgb_controller->name = name;
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
static void DetectSinowealthMouse(hid_device_info* info, const std::string& name)
{
#ifdef USE_HID_USAGE
unsigned char command[6] = {0x05, 0x11, 0x00, 0x00, 0x00, 0x00};
expected_reports reports{expected_report(0x04, 520, command, sizeof(command))};
if(!DetectUsages(info, name, 3, reports))
{
return;
}
hid_device *dev = reports.at(0).device;
hid_device *dev_cmd = reports.at(0).cmd_device;
#else
hid_device* dev = hid_open_path(info->path);
hid_device* dev_cmd = dev;
#endif
if(dev && dev_cmd)
{
SinowealthController* controller = new SinowealthController(dev, dev_cmd, info->path);
RGBController* rgb_controller = new RGBController_Sinowealth(controller);
rgb_controller->name = name;
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
static void DetectGMOW_Cable(hid_device_info* info, const std::string& name)
{
LOG_DEBUG("[%s] Detected connection via USB cable", name.c_str());
hid_device *dev = hid_open_path(info->path);
if(dev)
{
SinowealthGMOWController* controller = new SinowealthGMOWController(dev, info->path, GMOW_CABLE_CONNECTED);
RGBController* rgb_controller = new RGBController_GMOW(controller);
rgb_controller->name = name;
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
static void DetectGMOW_Dongle(hid_device_info* info, const std::string& name)
{
/*-------------------------------------------------------------------------*\
| When the GMOW is connected only via the wireless dongle, only one |
| device shows up (PID=2022), and RGB packets go to that device. |
@ -243,167 +289,100 @@ void DetectSinowealthMouse(hid_device_info* info, const std::string& name)
| the device is PID=2011). However, when both are plugged in, packets |
| should only go to the cable connected device |
\*-------------------------------------------------------------------------*/
else if(pid == Glorious_Model_OW_PID1 || pid == Glorious_Model_DW_PID1) // if dongle
LOG_DEBUG("[%s] Detected connection via wireless dongle", name.c_str());
hid_device_info* start = hid_enumerate(SINOWEALTH_VID,0);
hid_device_info* curr = start;
while(curr)
{
LOG_DEBUG("[%s] Detected connection via wireless dongle", name.c_str());
hid_device_info* start = hid_enumerate(SINOWEALTH_VID,0);
hid_device_info* curr = start;
while(curr)
if(curr->product_id == Glorious_Model_OW_PID2 || curr->product_id == Glorious_Model_DW_PID2)
{
if(curr->product_id == Glorious_Model_OW_PID2 || curr->product_id == Glorious_Model_DW_PID2)
{
delete reports;
return;
}
curr = curr->next;
return;
}
curr = curr->next;
}
hid_free_enumeration(start);
hid_device *dev = hid_open_path(info->path);
hid_device *dev = hid_open_path(info->path);
if(dev)
{
SinowealthGMOWController* controller = new SinowealthGMOWController(dev, info->path, GMOW_DONGLE_CONNECTED);
rgb_controller = new RGBController_GMOW(controller);
}
else if(pid == Glorious_Model_OW_PID2 || pid == Glorious_Model_DW_PID2)
{
LOG_DEBUG("[%s] Detected connection via USB cable", name.c_str());
hid_device *dev = hid_open_path(info->path);
SinowealthGMOWController* controller = new SinowealthGMOWController(dev, info->path, GMOW_CABLE_CONNECTED);
rgb_controller = new RGBController_GMOW(controller);
}
else
{
unsigned char command[6] = {0x05, 0x11, 0x00, 0x00, 0x00, 0x00};
reports->emplace_back(new expected_report(0x04, 520, command, sizeof(command)));
if(!DetectUsages(info, name, 3, *reports)) return;
SinowealthController* controller = new SinowealthController(reports->at(0)->device, reports->at(0)->cmd_device, info->path);
rgb_controller = new RGBController_Sinowealth(controller);
}
rgb_controller->name = name;
ResourceManager::get()->RegisterRGBController(rgb_controller);
reports->clear();
#else
hid_device* dev = hid_open_path(info->path);
if(dev)
{
RGBController *rgb_controller;
if(pid == ZET_FURY_PRO_PID)
{
SinowealthController1007* controller = new SinowealthController1007(dev, info->path);
rgb_controller = new RGBController_Sinowealth1007(controller);
}
/*-------------------------------------------------------------------------*\
| See above where USE_HID_USAGE is true for explanation of the detection |
| process for the GMOW |
\*-------------------------------------------------------------------------*/
else if(pid == Glorious_Model_OW_PID1 || pid == Glorious_Model_DW_PID1) // if dongle
{
LOG_DEBUG("[%s] Detected connection via wireless dongle", name.c_str());
hid_device_info* start = hid_enumerate(SINOWEALTH_VID,0);
hid_device_info* curr = start;
while(curr)
{
if(curr->product_id == Glorious_Model_OW_PID2 || curr->product_id == Glorious_Model_DW_PID2)
{
return;
}
curr = curr->next;
}
hid_device *dev = hid_open_path(info->path);
SinowealthGMOWController* controller = new SinowealthGMOWController(dev, info->path, GMOW_DONGLE_CONNECTED);
rgb_controller = new RGBController_GMOW(controller);
}
else if(pid == Glorious_Model_OW_PID2 || pid == Glorious_Model_DW_PID2)
{
LOG_DEBUG("[%s] Detected connection via USB cable", name.c_str());
hid_device *dev = hid_open_path(info->path);
SinowealthGMOWController* controller = new SinowealthGMOWController(dev, info->path, GMOW_CABLE_CONNECTED);
rgb_controller = new RGBController_GMOW(controller);
}
else
{
SinowealthController* controller = new SinowealthController(dev, dev, info->path);
rgb_controller = new RGBController_Sinowealth(controller);
}
rgb_controller->name = name;
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
#endif
}
void DetectSinowealthKeyboard(hid_device_info* info, const std::string& name)
{
unsigned int pid = info->product_id;
#ifdef USE_HID_USAGE
expected_reports* reports = new expected_reports();
RGBController *rgb_controller;
if(pid == RGB_KEYBOARD_0016PID)
{
unsigned char command[6] = {0x05, 0x83, 0x00, 0x00, 0x00, 0x00};
reports->emplace_back(new expected_report(0x06, 1032, command, sizeof(command)));
if(!DetectUsages(info, name, 3, *reports)) return;
SinowealthKeyboard16Controller* controller = new SinowealthKeyboard16Controller(reports->at(0)->cmd_device, reports->at(0)->device, info->path, name);
rgb_controller = new RGBController_SinowealthKeyboard16(controller);
}
else
{
unsigned char command[6] = {0x05, 0x83, 0xB6, 0x00, 0x00, 0x00};
reports->emplace_back(new expected_report(0x06, 1032, command, sizeof(command)));
if(!DetectUsages(info, name, 3, *reports)) return;
SinowealthKeyboardController* controller = new SinowealthKeyboardController(reports->at(0)->cmd_device, reports->at(0)->device, info->path);
rgb_controller = new RGBController_SinowealthKeyboard(controller);
}
rgb_controller->name = name;
ResourceManager::get()->RegisterRGBController(rgb_controller);
reports->clear();
#else
hid_device* dev = hid_open_path(info->path);
if(dev)
{
RGBController *rgb_controller;
if(pid == RGB_KEYBOARD_0016PID)
{
SinowealthKeyboard16Controller* controller = new SinowealthKeyboard16Controller(dev, dev, info->path, name);
rgb_controller = new RGBController_SinowealthKeyboard16(controller);
}
else
{
SinowealthController* controller = new SinowealthController(dev, dev, info->path);
rgb_controller = new RGBController_Sinowealth(controller);
}
RGBController *rgb_controller = new RGBController_GMOW(controller);
rgb_controller->name = name;
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
static void DetectSinowealthKeyboard16(hid_device_info* info, const std::string& name)
{
#ifdef USE_HID_USAGE
unsigned char command[6] = {0x05, 0x83, 0x00, 0x00, 0x00, 0x00};
expected_reports reports{expected_report(0x06, 1032, command, sizeof(command))};
if(!DetectUsages(info, name, 3, reports))
{
return;
}
hid_device *dev = reports.at(0).device;
hid_device *dev_cmd = reports.at(0).cmd_device;
#else
hid_device* dev = hid_open_path(info->path);
hid_device* dev_cmd = dev;
#endif
if(dev && dev_cmd)
{
SinowealthKeyboard16Controller* controller = new SinowealthKeyboard16Controller(dev_cmd, dev, info->path, name);
RGBController *rgb_controller = new RGBController_SinowealthKeyboard16(controller);
rgb_controller->name = name;
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
static void DetectSinowealthKeyboard(hid_device_info* info, const std::string& name)
{
#ifdef USE_HID_USAGE
unsigned char command[6] = {0x05, 0x83, 0xB6, 0x00, 0x00, 0x00};
expected_reports reports{expected_report(0x06, 1032, command, sizeof(command))};
if(!DetectUsages(info, name, 3, reports))
{
return;
}
hid_device *dev = reports.at(0).device;
hid_device *dev_cmd = reports.at(0).cmd_device;
if(dev && dev_cmd)
{
SinowealthKeyboardController* controller = new SinowealthKeyboardController(dev_cmd, dev, info->path);
RGBController* rgb_controller = new RGBController_SinowealthKeyboard(controller);
rgb_controller->name = name;
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
#else
// It is unknown why this code used the MOUSE controller here; could it be the reason why it was disabled?
hid_device* dev = hid_open_path(info->path);
if(dev)
{
SinowealthController* controller = new SinowealthController(dev, dev, info->path);
RGBController* rgb_controller = new RGBController_Sinowealth(controller);
rgb_controller->name = name;
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
#endif
}
void DetectSinowealthGenesisKeyboard(hid_device_info* info, const std::string& name)
static void DetectSinowealthGenesisKeyboard(hid_device_info* info, const std::string& name)
{
unsigned int pid = info->product_id;
hid_device* dev = hid_open_path(info->path);
if(dev)
{
if(pid == GENESIS_THOR_300_PID)
{
SinowealthKeyboard90Controller* controller = new SinowealthKeyboard90Controller(dev, info->path, pid);
RGBController_SinowealthKeyboard90* rgb_controller = new RGBController_SinowealthKeyboard90(controller);
rgb_controller->name = name;
SinowealthKeyboard90Controller* controller = new SinowealthKeyboard90Controller(dev, info->path, pid);
RGBController_SinowealthKeyboard90* rgb_controller = new RGBController_SinowealthKeyboard90(controller);
rgb_controller->name = name;
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
@ -411,26 +390,28 @@ void DetectSinowealthGenesisKeyboard(hid_device_info* info, const std::string& n
REGISTER_HID_DETECTOR_P("Glorious Model O / O-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_O_PID, 0xFF00);
REGISTER_HID_DETECTOR_P("Glorious Model D / D-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_D_PID, 0xFF00);
REGISTER_HID_DETECTOR_P("Everest GT-100 RGB", DetectSinowealthMouse, SINOWEALTH_VID, Everest_GT100_PID, 0xFF00);
REGISTER_HID_DETECTOR_IPU("ZET Fury Pro", DetectSinowealthMouse, SINOWEALTH_VID, ZET_FURY_PRO_PID, 1, 0xFF00, 1);
REGISTER_HID_DETECTOR_PU("Glorious Model O / O- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_OW_PID1, 0xFFFF, 1);
REGISTER_HID_DETECTOR_PU("Glorious Model O / O- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_OW_PID2, 0xFFFF, 0x0000);
REGISTER_HID_DETECTOR_PU("Glorious Model D / D- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_DW_PID1, 0xFFFF, 0x0000);
REGISTER_HID_DETECTOR_PU("Glorious Model D / D- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_DW_PID2, 0xFFFF, 0x0000);
REGISTER_HID_DETECTOR_IPU("ZET Fury Pro", DetectZetFuryPro, SINOWEALTH_VID, ZET_FURY_PRO_PID, 1, 0xFF00, 1);
REGISTER_HID_DETECTOR_PU("Glorious Model O / O- Wireless", DetectGMOW_Dongle, SINOWEALTH_VID, Glorious_Model_OW_PID1, 0xFFFF, 1);
REGISTER_HID_DETECTOR_PU("Glorious Model O / O- Wireless", DetectGMOW_Cable, SINOWEALTH_VID, Glorious_Model_OW_PID2, 0xFFFF, 0x0000);
REGISTER_HID_DETECTOR_PU("Glorious Model D / D- Wireless", DetectGMOW_Dongle, SINOWEALTH_VID, Glorious_Model_DW_PID1, 0xFFFF, 0x0000);
REGISTER_HID_DETECTOR_PU("Glorious Model D / D- Wireless", DetectGMOW_Cable, SINOWEALTH_VID, Glorious_Model_DW_PID2, 0xFFFF, 0x0000);
REGISTER_HID_DETECTOR_IPU("Genesis Thor 300", DetectSinowealthGenesisKeyboard, SINOWEALTH_VID, GENESIS_THOR_300_PID, 1, 0xFF00, 1);
// Sinowealth keyboards are disabled due to VID/PID pairs being reused from Redragon keyboards, which ended up in bricking the latter
//REGISTER_HID_DETECTOR_P("FL ESPORTS F11", DetectSinowealthKeyboard, SINOWEALTH_VID, Fl_Esports_F11_PID, 0xFF00);
//REGISTER_HID_DETECTOR_P("Sinowealth Keyboard", DetectSinowealthKeyboard, SINOWEALTH_VID, RGB_KEYBOARD_0016PID, 0xFF00);
//REGISTER_HID_DETECTOR_P("Sinowealth Keyboard", DetectSinowealthKeyboard16, SINOWEALTH_VID, RGB_KEYBOARD_0016PID, 0xFF00);
#else
REGISTER_HID_DETECTOR_I("Glorious Model O / O-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_O_PID, 1);
REGISTER_HID_DETECTOR_I("Glorious Model D / D-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_D_PID, 1);
REGISTER_HID_DETECTOR_I("Everest GT-100 RGB", DetectSinowealthMouse, SINOWEALTH_VID, Everest_GT100_PID, 1);
REGISTER_HID_DETECTOR_I("ZET Fury Pro", DetectSinowealthMouse, SINOWEALTH_VID, ZET_FURY_PRO_PID, 1);
REGISTER_HID_DETECTOR_I("Glorious Model O / O- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_OW_PID1, 1);
REGISTER_HID_DETECTOR_I("Glorious Model O / O- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_OW_PID2, 2);
REGISTER_HID_DETECTOR_I("Glorious Model D / D- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_DW_PID1, 2);
REGISTER_HID_DETECTOR_I("Glorious Model D / D- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_DW_PID2, 2);
REGISTER_HID_DETECTOR_I("ZET Fury Pro", DetectZetFuryPro, SINOWEALTH_VID, ZET_FURY_PRO_PID, 1);
REGISTER_HID_DETECTOR_I("Glorious Model O / O- Wireless", DetectGMOW_Dongle, SINOWEALTH_VID, Glorious_Model_OW_PID1, 1);
REGISTER_HID_DETECTOR_I("Glorious Model O / O- Wireless", DetectGMOW_Cable, SINOWEALTH_VID, Glorious_Model_OW_PID2, 2);
REGISTER_HID_DETECTOR_I("Glorious Model D / D- Wireless", DetectGMOW_Dongle, SINOWEALTH_VID, Glorious_Model_DW_PID1, 2);
REGISTER_HID_DETECTOR_I("Glorious Model D / D- Wireless", DetectGMOW_Cable, SINOWEALTH_VID, Glorious_Model_DW_PID2, 2);
REGISTER_HID_DETECTOR_I("Genesis Thor 300", DetectSinowealthGenesisKeyboard, SINOWEALTH_VID, GENESIS_THOR_300_PID, 1);
//REGISTER_HID_DETECTOR_I("FL ESPORTS F11", DetectSinowealthKeyboard, SINOWEALTH_VID, Fl_Esports_F11_PID, 1);
//REGISTER_HID_DETECTOR_I("Sinowealth Keyboard", DetectSinowealthKeyboard, SINOWEALTH_VID, RGB_KEYBOARD_0016PID, 1);
//REGISTER_HID_DETECTOR_I("Sinowealth Keyboard", DetectSinowealthKeyboard16, SINOWEALTH_VID, RGB_KEYBOARD_0016PID, 1);
#endif