/*---------------------------------------------------------*\ | SteelSeriesApexBaseController.cpp | | | | Driver base for SteelSeries Apex | | | | Florian Heilmann (FHeilmann) 19 Oct 2020 | | | | This file is part of the OpenRGB project | | SPDX-License-Identifier: GPL-2.0-or-later | \*---------------------------------------------------------*/ #include "SteelSeriesApexBaseController.h" SteelSeriesApexBaseController::SteelSeriesApexBaseController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; name = dev_name; } SteelSeriesApexBaseController::~SteelSeriesApexBaseController() { } std::string SteelSeriesApexBaseController::GetLocation() { return("HID: " + location); }; std::string SteelSeriesApexBaseController::GetName() { return(name); } /*---------------------------------------------------------*\ | The serial number of the keyboard is acquired by sending | | an output report to address 0xFF and reading the result. | | The HID capability table is not used. The serial number | | also contains the model number which can be used to | | determine the physical layout of different region | | keyboards throughout the product stack. | \*---------------------------------------------------------*/ std::string SteelSeriesApexBaseController::GetSerial() { std::string return_string = ""; if(proto_type == APEX) { unsigned char obuf[STEELSERIES_PACKET_OUT_SIZE]; unsigned char ibuf[STEELSERIES_PACKET_IN_SIZE]; int result; memset(obuf, 0x00, sizeof(obuf)); obuf[0x00] = 0; obuf[0x01] = 0xFF; hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE); result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 2); /*-------------------------------------------------*\ | Only the first 19 bytes are of value | \*-------------------------------------------------*/ if(result > 0) { std::string serialnum(ibuf, ibuf+19); return_string = serialnum; } } return(return_string); } std::string SteelSeriesApexBaseController::GetVersion() { std::string return_string = "Unsupported protocol"; if(proto_type == APEX) { /*-------------------------------------------------*\ | For the Apex Pro there are two firmware versions | | which can be acquired, KBD and LED. We know | | where both are located, we do not know which is | | what. For now we'll make an assumption and fix | | if proven wrong. | \*-------------------------------------------------*/ unsigned char obuf[STEELSERIES_PACKET_OUT_SIZE]; unsigned char ibuf[STEELSERIES_PACKET_IN_SIZE]; int result; memset(obuf, 0x00, sizeof(obuf)); obuf[0x00] = 0; obuf[0x01] = 0x90; hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE); result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 2); if(result > 0) { std::string fwver(ibuf, ibuf+STEELSERIES_PACKET_IN_SIZE); fwver = fwver.c_str(); /*---------------------------------------------*\ | Find 2 periods in string, if found we can | | form a X.Y.Z revision. | \*---------------------------------------------*/ std::size_t majorp = fwver.find('.'); if(majorp != std::string::npos) { std::size_t minorp = fwver.find('.', majorp+1); if(minorp != std::string::npos) { std::string major = fwver.substr(0, majorp); std::string minor = fwver.substr(majorp+1, (minorp-majorp-1)); std::string build = fwver.substr(minorp+1); return_string = "KBD: " + major + "." + minor + "." + build; } } } /*-------------------------------------------------*\ | Clear and reuse buffer | \*-------------------------------------------------*/ memset(ibuf, 0x00, sizeof(ibuf)); obuf[0x02] = 0x01; hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE); result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 10); if(result > 0) { std::string fwver(ibuf, ibuf+STEELSERIES_PACKET_IN_SIZE); fwver = fwver.c_str(); std::size_t majorp = fwver.find('.'); if(majorp != std::string::npos) { std::size_t minorp = fwver.find('.', majorp+1); if(minorp != std::string::npos) { std::string major = fwver.substr(0, majorp); std::string minor = fwver.substr(majorp+1, (minorp-majorp-1)); std::string build = fwver.substr(minorp+1); return_string = return_string + " / LED: " + major + "." + minor + "." + build; } } } } return(return_string); }