#include "DRI/Dri_Vendor.h" #include namespace { void Dri_Vendor_CloseHandle(HANDLE* p_Handle) { if ((*p_Handle != nullptr) && (*p_Handle != INVALID_HANDLE_VALUE)) { CloseHandle(*p_Handle); } *p_Handle = INVALID_HANDLE_VALUE; } bool Dri_Vendor_TryWrite( HANDLE HandleWrite, quint16 OutputLength, const QByteArray& Packet, const QString& SuccessText, const QString& ErrorPrefix, QString* p_TextStatus, QStringList* p_ErrorList) { QString TextError; if (Dri_Hid_WritePacket(HandleWrite, OutputLength, Packet, &TextError)) { if (p_TextStatus != nullptr) { *p_TextStatus = SuccessText; } return true; } if (!TextError.isEmpty()) { p_ErrorList->append(ErrorPrefix.arg(TextError)); } return false; } } // namespace void Dri_Vendor_Close(Dri_Vendor_Struct_Port* p_Port) { Dri_Hid_CloseReadPort(&p_Port->ReadPort); Dri_Vendor_CloseHandle(&p_Port->HandleWriteVendor); Dri_Vendor_CloseHandle(&p_Port->HandleWriteCommand); Dri_Vendor_CloseHandle(&p_Port->HandleWriteNkro); p_Port->VendorWriteOutputLength = 0; p_Port->CommandWriteOutputLength = 0; p_Port->NkroWriteOutputLength = 0; p_Port->IsBluetoothTransport = false; } bool Dri_Vendor_Init( Dri_Vendor_Struct_Port* p_Port, const Mid_Struct_DeviceConfig& DeviceConfig, QString* p_TextStatus) { Dri_Vendor_Close(p_Port); Mid_Struct_DeviceMatch VendorMatch; VendorMatch.VendorId = DeviceConfig.VendorId; VendorMatch.ProductId = DeviceConfig.ProductId; VendorMatch.UsagePage = MID_CONST_USAGE_PAGE_VENDOR; VendorMatch.Usage = MID_CONST_USAGE_VENDOR; QString VendorPath; QString VendorInstanceId; quint16 InputLength = 0; quint16 VendorOutputLength = 0; if (!Mid_FindHidInterface( VendorMatch, &VendorPath, &InputLength, &VendorOutputLength, &VendorInstanceId)) { if (p_TextStatus != nullptr) { *p_TextStatus = QStringLiteral("Vendor interface was not found: FF00 / 0002."); } return false; } p_Port->IsBluetoothTransport = Mid_IsBluetoothHidInstanceId(VendorInstanceId); const QString VendorPortName = p_Port->IsBluetoothTransport ? QStringLiteral("Bluetooth/HID Vendor") : QStringLiteral("Vendor"); if (!Dri_Hid_InitReadPort( &p_Port->ReadPort, VendorPath, InputLength, Mid_Enum_RawPacketSource_UsbVendorHid, VendorPortName, p_TextStatus)) { return false; } p_Port->HandleWriteVendor = Dri_Hid_OpenWriteHandle(VendorPath, nullptr); p_Port->VendorWriteOutputLength = VendorOutputLength; QString CommandPath; quint16 CommandOutputLength = 0; Mid_Struct_DeviceMatch CommandMatch; CommandMatch.VendorId = DeviceConfig.VendorId; CommandMatch.ProductId = DeviceConfig.ProductId; CommandMatch.UsagePage = MID_CONST_USAGE_PAGE_VENDOR_COMMAND; CommandMatch.Usage = MID_CONST_USAGE_VENDOR_COMMAND; if (Mid_FindHidInterface( CommandMatch, &CommandPath, nullptr, &CommandOutputLength)) { QString TextError; p_Port->HandleWriteCommand = Dri_Hid_OpenWriteHandle(CommandPath, &TextError); p_Port->CommandWriteOutputLength = CommandOutputLength; if ((p_Port->HandleWriteCommand == INVALID_HANDLE_VALUE) && (p_TextStatus != nullptr)) { *p_TextStatus = QStringLiteral("Vendor command write handle failed: %1").arg(TextError); } } else if (p_TextStatus != nullptr) { *p_TextStatus = QStringLiteral("Vendor command interface was not found: FF01 / 0005."); } QString NkroPath; quint16 NkroOutputLength = 0; Mid_Struct_DeviceMatch NkroMatch; NkroMatch.VendorId = DeviceConfig.VendorId; NkroMatch.ProductId = DeviceConfig.ProductId; NkroMatch.UsagePage = MID_CONST_USAGE_PAGE_NKRO; NkroMatch.Usage = MID_CONST_USAGE_NKRO; if (Mid_FindHidInterface( NkroMatch, &NkroPath, nullptr, &NkroOutputLength)) { QString TextError; p_Port->HandleWriteNkro = Dri_Hid_OpenWriteHandle(NkroPath, &TextError); p_Port->NkroWriteOutputLength = NkroOutputLength; if ((p_Port->HandleWriteNkro == INVALID_HANDLE_VALUE) && (p_TextStatus != nullptr)) { *p_TextStatus = QStringLiteral("NKRO write handle failed: %1").arg(TextError); } } else if (p_TextStatus != nullptr) { *p_TextStatus = QStringLiteral("NKRO write interface was not found."); } return true; } bool Dri_Vendor_Read( Dri_Vendor_Struct_Port* p_Port, Mid_Struct_RawPacket* p_Packet, QString* p_TextStatus) { return Dri_Hid_Read(&p_Port->ReadPort, p_Packet, p_TextStatus); } bool Dri_Vendor_Write( Dri_Vendor_Struct_Port* p_Port, const QByteArray& ByteArray, QString* p_TextStatus) { const QString RouteLabel = p_Port->IsBluetoothTransport ? QStringLiteral("Bluetooth Vendor") : QStringLiteral("Vendor"); if (!p_Port->ReadPort.IsOpened) { if (p_TextStatus != nullptr) { *p_TextStatus = QStringLiteral("%1 read path is not open, packet was not sent.").arg(RouteLabel); } return false; } if (ByteArray.isEmpty()) { if (p_TextStatus != nullptr) { *p_TextStatus = QStringLiteral("%1 packet is empty.").arg(RouteLabel); } return false; } QStringList ErrorList; const quint8 ReportId = static_cast(ByteArray.at(0)); if (ReportId == Mid_Enum_ReportId_VendorCommand) { if (Dri_Vendor_TryWrite( p_Port->HandleWriteCommand, p_Port->CommandWriteOutputLength, ByteArray, QStringLiteral("Packet sent to %1 command interface.").arg(RouteLabel), RouteLabel + QStringLiteral(" command write failed: %1"), p_TextStatus, &ErrorList)) { return true; } } else { if (Dri_Vendor_TryWrite( p_Port->HandleWriteNkro, p_Port->NkroWriteOutputLength, ByteArray, QStringLiteral("Packet sent to NKRO write interface."), QStringLiteral("NKRO write failed: %1"), p_TextStatus, &ErrorList)) { return true; } if (Dri_Vendor_TryWrite( p_Port->HandleWriteVendor, p_Port->VendorWriteOutputLength, ByteArray, QStringLiteral("Packet sent to %1 write interface.").arg(RouteLabel), RouteLabel + QStringLiteral(" write failed: %1"), p_TextStatus, &ErrorList)) { return true; } } if (p_TextStatus != nullptr) { *p_TextStatus = ErrorList.isEmpty() ? QStringLiteral("No writable output handle is available, packet send was skipped.") : ErrorList.join(QStringLiteral("\n")); } return false; }