Shared SMBus Access Using Global Mutex on Windows

This commit is contained in:
Shady Nawara 2022-10-14 00:58:54 +00:00 committed by Adam Honse
parent be90ba335e
commit 6f477d6c4c
9 changed files with 252 additions and 98 deletions

View file

@ -9,8 +9,9 @@
\*-----------------------------------------*/ \*-----------------------------------------*/
#include "i2c_smbus_i801.h" #include "i2c_smbus_i801.h"
#include "ResourceManager.h"
#ifdef _WIN32 #ifdef _WIN32
#include <Windows.h>
#include "OlsApi.h" #include "OlsApi.h"
#elif _MACOSX_X86_X64 #elif _MACOSX_X86_X64
#include "macUSPCIOAccess.h" #include "macUSPCIOAccess.h"
@ -20,6 +21,33 @@
using namespace std::chrono_literals; using namespace std::chrono_literals;
i2c_smbus_i801::i2c_smbus_i801()
{
#ifdef _WIN32
json drivers_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Drivers");
bool shared_smbus_access = true;
if(drivers_settings.contains("shared_smbus_access"))
{
shared_smbus_access = drivers_settings["shared_smbus_access"].get<bool>();
}
if(shared_smbus_access)
{
global_smbus_access_handle = CreateMutexA(NULL, FALSE, GLOBAL_SMBUS_MUTEX_NAME);
}
#endif
}
i2c_smbus_i801::~i2c_smbus_i801()
{
#ifdef _WIN32
if(global_smbus_access_handle != NULL)
{
CloseHandle(global_smbus_access_handle);
}
#endif
}
/* Return negative errno on error. */ /* Return negative errno on error. */
s32 i2c_smbus_i801::i801_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data) s32 i2c_smbus_i801::i801_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data)
{ {
@ -486,7 +514,23 @@ int i2c_smbus_i801::i801_wait_intr()
s32 i2c_smbus_i801::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data) s32 i2c_smbus_i801::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data)
{ {
return i801_access(addr, read_write, command, size, data); #ifdef _WIN32
if(global_smbus_access_handle != NULL)
{
WaitForSingleObject(global_smbus_access_handle, INFINITE);
}
#endif
s32 result = i801_access(addr, read_write, command, size, data);
#ifdef _WIN32
if(global_smbus_access_handle != NULL)
{
ReleaseMutex(global_smbus_access_handle);
}
#endif
return result;
} }
s32 i2c_smbus_i801::i2c_xfer(u8 addr, char read_write, int* size, u8* data) s32 i2c_smbus_i801::i2c_xfer(u8 addr, char read_write, int* size, u8* data)

View file

@ -10,6 +10,10 @@
#include "i2c_smbus.h" #include "i2c_smbus.h"
#ifdef _WIN32
#include <Windows.h>
#endif
#pragma once #pragma once
/* BIT shifting macro */ /* BIT shifting macro */
@ -81,10 +85,16 @@
#define SMBHSTCFG 0x040 #define SMBHSTCFG 0x040
#define SMBHSTCFG_HST_EN BIT(0) #define SMBHSTCFG_HST_EN BIT(0)
#ifdef _WIN32
#define GLOBAL_SMBUS_MUTEX_NAME "Global\\Access_SMBUS.HTP.Method"
#endif
class i2c_smbus_i801 : public i2c_smbus_interface class i2c_smbus_i801 : public i2c_smbus_interface
{ {
public: public:
u16 i801_smba = 0xF000; u16 i801_smba = 0xF000;
i2c_smbus_i801();
~i2c_smbus_i801();
private: private:
s32 i801_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data); s32 i801_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data);
@ -97,4 +107,8 @@ private:
int i801_wait_intr(); int i801_wait_intr();
s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data); s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data);
s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data); s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data);
};
#ifdef _WIN32
HANDLE global_smbus_access_handle = NULL;
#endif
};

View file

@ -7,12 +7,35 @@
\*-----------------------------------------*/ \*-----------------------------------------*/
#include "i2c_smbus_nct6775.h" #include "i2c_smbus_nct6775.h"
#include <Windows.h>
#include "OlsApi.h" #include "OlsApi.h"
#include "LogManager.h" #include "LogManager.h"
#include "ResourceManager.h"
using namespace std::chrono_literals; using namespace std::chrono_literals;
i2c_smbus_nct6775::i2c_smbus_nct6775()
{
json drivers_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Drivers");
bool shared_smbus_access = true;
if(drivers_settings.contains("shared_smbus_access"))
{
shared_smbus_access = drivers_settings["shared_smbus_access"].get<bool>();
}
if(shared_smbus_access)
{
global_smbus_access_handle = CreateMutexA(NULL, FALSE, GLOBAL_SMBUS_MUTEX_NAME);
}
}
i2c_smbus_nct6775::~i2c_smbus_nct6775()
{
if(global_smbus_access_handle != NULL)
{
CloseHandle(global_smbus_access_handle);
}
}
s32 i2c_smbus_nct6775::nct6775_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data) s32 i2c_smbus_nct6775::nct6775_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data)
{ {
int i, len, status, cnt; int i, len, status, cnt;
@ -186,7 +209,19 @@ s32 i2c_smbus_nct6775::nct6775_access(u16 addr, char read_write, u8 command, int
s32 i2c_smbus_nct6775::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data) s32 i2c_smbus_nct6775::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data)
{ {
return nct6775_access(addr, read_write, command, size, data); if(global_smbus_access_handle != NULL)
{
WaitForSingleObject(global_smbus_access_handle, INFINITE);
}
s32 result = nct6775_access(addr, read_write, command, size, data);
if(global_smbus_access_handle != NULL)
{
ReleaseMutex(global_smbus_access_handle);
}
return result;
} }
s32 i2c_smbus_nct6775::i2c_xfer(u8 addr, char read_write, int* size, u8* data) s32 i2c_smbus_nct6775::i2c_xfer(u8 addr, char read_write, int* size, u8* data)

View file

@ -7,6 +7,7 @@
\*-----------------------------------------*/ \*-----------------------------------------*/
#include "i2c_smbus.h" #include "i2c_smbus.h"
#include <Windows.h>
#pragma once #pragma once
@ -44,15 +45,19 @@
/* Other settings */ /* Other settings */
#define NCT6775_MAX_RETRIES 400 #define NCT6775_MAX_RETRIES 400
#define GLOBAL_SMBUS_MUTEX_NAME "Global\\Access_SMBUS.HTP.Method"
class i2c_smbus_nct6775: public i2c_smbus_interface class i2c_smbus_nct6775: public i2c_smbus_interface
{ {
public: public:
u16 nct6775_smba = 0x0290; u16 nct6775_smba = 0x0290;
i2c_smbus_nct6775();
~i2c_smbus_nct6775();
private: private:
s32 nct6775_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data); s32 nct6775_access(u16 addr, char read_write, u8 command, int size, i2c_smbus_data *data);
s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data); s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data);
s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data); s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data);
HANDLE global_smbus_access_handle = NULL;
}; };

View file

@ -16,13 +16,12 @@
i2c_smbus_piix4::i2c_smbus_piix4() i2c_smbus_piix4::i2c_smbus_piix4()
{ {
json drivers_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Drivers"); json drivers_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Drivers");
bool amd_smbus_reduce_cpu = false;
bool amd_smbus_reduce_cpu = false;
if(drivers_settings.contains("amd_smbus_reduce_cpu")) if(drivers_settings.contains("amd_smbus_reduce_cpu"))
{ {
amd_smbus_reduce_cpu = drivers_settings["amd_smbus_reduce_cpu"].get<bool>(); amd_smbus_reduce_cpu = drivers_settings["amd_smbus_reduce_cpu"].get<bool>();
} }
if(amd_smbus_reduce_cpu) if(amd_smbus_reduce_cpu)
{ {
delay_timer = CreateWaitableTimerExW(NULL, NULL, CREATE_WAITABLE_TIMER_MANUAL_RESET | CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS); delay_timer = CreateWaitableTimerExW(NULL, NULL, CREATE_WAITABLE_TIMER_MANUAL_RESET | CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
@ -31,6 +30,16 @@ i2c_smbus_piix4::i2c_smbus_piix4()
delay_timer = CreateWaitableTimer(NULL, TRUE, NULL); // create regular timer instead delay_timer = CreateWaitableTimer(NULL, TRUE, NULL); // create regular timer instead
} }
} }
bool shared_smbus_access = true;
if(drivers_settings.contains("shared_smbus_access"))
{
shared_smbus_access = drivers_settings["shared_smbus_access"].get<bool>();
}
if(shared_smbus_access)
{
global_smbus_access_handle = CreateMutexA(NULL, FALSE, GLOBAL_SMBUS_MUTEX_NAME);
}
} }
i2c_smbus_piix4::~i2c_smbus_piix4() i2c_smbus_piix4::~i2c_smbus_piix4()
@ -39,6 +48,11 @@ i2c_smbus_piix4::~i2c_smbus_piix4()
{ {
CloseHandle(delay_timer); CloseHandle(delay_timer);
} }
if(global_smbus_access_handle != NULL)
{
CloseHandle(global_smbus_access_handle);
}
} }
//Logic adapted from piix4_transaction() in i2c-piix4.c //Logic adapted from piix4_transaction() in i2c-piix4.c
@ -221,7 +235,19 @@ s32 i2c_smbus_piix4::piix4_access(u16 addr, char read_write, u8 command, int siz
s32 i2c_smbus_piix4::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data) s32 i2c_smbus_piix4::i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data)
{ {
return piix4_access(addr, read_write, command, size, data); if(global_smbus_access_handle != NULL)
{
WaitForSingleObject(global_smbus_access_handle, INFINITE);
}
s32 result = piix4_access(addr, read_write, command, size, data);
if(global_smbus_access_handle != NULL)
{
ReleaseMutex(global_smbus_access_handle);
}
return result;
} }
s32 i2c_smbus_piix4::i2c_xfer(u8 addr, char read_write, int* size, u8* data) s32 i2c_smbus_piix4::i2c_xfer(u8 addr, char read_write, int* size, u8* data)

View file

@ -37,6 +37,8 @@
#define PIIX4_WORD_DATA 0x0C #define PIIX4_WORD_DATA 0x0C
#define PIIX4_BLOCK_DATA 0x14 #define PIIX4_BLOCK_DATA 0x14
#define GLOBAL_SMBUS_MUTEX_NAME "Global\\Access_SMBUS.HTP.Method"
class i2c_smbus_piix4 : public i2c_smbus_interface class i2c_smbus_piix4 : public i2c_smbus_interface
{ {
public: public:
@ -50,4 +52,5 @@ private:
s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data); s32 i2c_smbus_xfer(u8 addr, char read_write, u8 command, int size, i2c_smbus_data* data);
s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data); s32 i2c_xfer(u8 addr, char read_write, int* size, u8* data);
HANDLE delay_timer; HANDLE delay_timer;
HANDLE global_smbus_access_handle = NULL;
}; };

View file

@ -92,9 +92,19 @@ OpenRGBSettingsPage::OpenRGBSettingsPage(QWidget *parent) :
{ {
ui->CheckboxAMDSMBusReduceCPU->setChecked(drivers_settings["amd_smbus_reduce_cpu"]); ui->CheckboxAMDSMBusReduceCPU->setChecked(drivers_settings["amd_smbus_reduce_cpu"]);
} }
if(drivers_settings.contains("shared_smbus_access"))
{
ui->CheckboxSharedSMBusAccess->setChecked(drivers_settings["shared_smbus_access"]);
}
else
{
ui->CheckboxSharedSMBusAccess->setChecked(true);
}
#else #else
ui->DriversSettingsLabel->hide(); ui->DriversSettingsLabel->hide();
ui->CheckboxAMDSMBusReduceCPU->hide(); ui->CheckboxAMDSMBusReduceCPU->hide();
ui->CheckboxSharedSMBusAccess->hide();
#endif #endif
UpdateProfiles(); UpdateProfiles();
@ -672,3 +682,12 @@ void Ui::OpenRGBSettingsPage::on_CheckboxAMDSMBusReduceCPU_clicked()
SaveSettings(); SaveSettings();
} }
void Ui::OpenRGBSettingsPage::on_CheckboxSharedSMBusAccess_clicked()
{
json drivers_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Drivers");
drivers_settings["shared_smbus_access"] = ui->CheckboxSharedSMBusAccess->isChecked();
ResourceManager::get()->GetSettingsManager()->SetSettings("Drivers", drivers_settings);
SaveSettings();
}

View file

@ -60,6 +60,7 @@ private slots:
void on_OpenSettingsFolderButton_clicked(); void on_OpenSettingsFolderButton_clicked();
void on_CheckboxLogConsole_clicked(); void on_CheckboxLogConsole_clicked();
void on_CheckboxAMDSMBusReduceCPU_clicked(); void on_CheckboxAMDSMBusReduceCPU_clicked();
void on_CheckboxSharedSMBusAccess_clicked();
void on_CheckboxSetOnExit_clicked(bool checked); void on_CheckboxSetOnExit_clicked(bool checked);
void on_ComboBoxExitProfile_currentTextChanged(const QString exit_profile_name); void on_ComboBoxExitProfile_currentTextChanged(const QString exit_profile_name);

View file

@ -29,17 +29,24 @@
<widget class="QWidget" name="scrollAreaWidgetContents_2"> <widget class="QWidget" name="scrollAreaWidgetContents_2">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>-67</x> <x>0</x>
<y>-258</y> <y>0</y>
<width>465</width> <width>408</width>
<height>724</height> <height>556</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gridLayout_3"> <layout class="QGridLayout" name="gridLayout_3">
<item row="14" column="0"> <item row="9" column="0">
<widget class="QCheckBox" name="CheckboxAutoStart"> <widget class="QLabel" name="LogManagerSettingsLabel">
<property name="text"> <property name="text">
<string>Start At Login</string> <string>Log Manager Settings:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="UserInterfaceSettingsLabel">
<property name="text">
<string>User Interface Settings:</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -50,20 +57,33 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="25" column="1"> <item row="24" column="1">
<widget class="QComboBox" name="ComboBoxExitProfile"/> <widget class="QLineEdit" name="TextCustomArgs"/>
</item> </item>
<item row="10" column="0"> <item row="25" column="1">
<widget class="QCheckBox" name="CheckboxLogConsole"> <widget class="QComboBox" name="ComboBoxAutoStartProfile"/>
</item>
<item row="8" column="0">
<widget class="QCheckBox" name="CheckboxRunZoneChecks">
<property name="text"> <property name="text">
<string>Enable Log Console (restart required)</string> <string>Run zone checks on rescan</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="26" column="0"> <item row="26" column="0">
<widget class="QLabel" name="AutoStartStatusLabel"> <widget class="QCheckBox" name="CheckboxSetOnExit">
<property name="text"> <property name="text">
<string>Start at Login Status</string> <string>Set Profile on Exit</string>
</property>
</widget>
</item>
<item row="26" column="1">
<widget class="QComboBox" name="ComboBoxExitProfile"/>
</item>
<item row="19" column="0">
<widget class="QCheckBox" name="CheckboxAutoStartMinimized">
<property name="text">
<string>Start Minimized</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -75,54 +95,47 @@
</widget> </widget>
</item> </item>
<item row="23" column="0"> <item row="23" column="0">
<widget class="QCheckBox" name="CheckboxAutoStartCustom"> <widget class="QCheckBox" name="CheckboxAutoStartClient">
<property name="text"> <property name="text">
<string>Custom Arguments</string> <string>Start Client</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="19" column="0"> <item row="20" column="0">
<widget class="QCheckBox" name="CheckboxAutoStartServer"> <widget class="QCheckBox" name="CheckboxAutoStartServer">
<property name="text"> <property name="text">
<string>Start Server</string> <string>Start Server</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="21" column="1">
<widget class="QLabel" name="ThemeLabel"> <widget class="QLineEdit" name="TextServerHost"/>
</item>
<item row="21" column="0">
<widget class="QCheckBox" name="CheckboxAutoStartSetServerHost">
<property name="text"> <property name="text">
<string>Theme (restart required)</string> <string>Set Server Host</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="9" column="0"> <item row="10" column="0">
<widget class="QLabel" name="LogManagerSettingsLabel"> <widget class="QCheckBox" name="CheckboxLogConsole">
<property name="text"> <property name="text">
<string>Log Manager Settings:</string> <string>Enable Log Console (restart required)</string>
</property>
</widget>
</item>
<item row="14" column="0">
<widget class="QLabel" name="AutoStartLabel">
<property name="text">
<string>Start At Login Settings:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="3" column="1">
<widget class="QComboBox" name="ComboBoxTheme"/> <widget class="QComboBox" name="ComboBoxTheme"/>
</item> </item>
<item row="18" column="0">
<widget class="QCheckBox" name="CheckboxAutoStartMinimized">
<property name="text">
<string>Start Minimized</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="UserInterfaceSettingsLabel">
<property name="text">
<string>User Interface Settings:</string>
</property>
</widget>
</item>
<item row="22" column="1"> <item row="22" column="1">
<widget class="QLineEdit" name="TextClientHost"/>
</item>
<item row="21" column="1">
<widget class="QLineEdit" name="TextServerPort"> <widget class="QLineEdit" name="TextServerPort">
<property name="inputMask"> <property name="inputMask">
<string>90000</string> <string>90000</string>
@ -135,13 +148,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="21" column="0">
<widget class="QCheckBox" name="CheckboxAutoStartSetServerPort">
<property name="text">
<string>Set Server Port</string>
</property>
</widget>
</item>
<item row="4" column="0"> <item row="4" column="0">
<widget class="QCheckBox" name="CheckboxMinimizeOnClose"> <widget class="QCheckBox" name="CheckboxMinimizeOnClose">
<property name="text"> <property name="text">
@ -149,17 +155,45 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="13" column="0"> <item row="5" column="0">
<widget class="QLabel" name="AutoStartLabel"> <widget class="QCheckBox" name="CheckboxTrayIconGreyscale">
<property name="text"> <property name="text">
<string>Start At Login Settings:</string> <string>Greyscale Tray Icon</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="24" column="1">
<widget class="QComboBox" name="ComboBoxAutoStartProfile"/>
</item>
<item row="27" column="0"> <item row="27" column="0">
<widget class="QLabel" name="AutoStartStatusLabel">
<property name="text">
<string>Start at Login Status</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="ThemeLabel">
<property name="text">
<string>Theme (restart required)</string>
</property>
</widget>
</item>
<item row="15" column="0">
<widget class="QCheckBox" name="CheckboxAutoStart">
<property name="text">
<string>Start At Login</string>
</property>
</widget>
</item>
<item row="23" column="1">
<widget class="QLineEdit" name="TextClientHost"/>
</item>
<item row="22" column="0">
<widget class="QCheckBox" name="CheckboxAutoStartSetServerPort">
<property name="text">
<string>Set Server Port</string>
</property>
</widget>
</item>
<item row="28" column="0">
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
@ -175,27 +209,6 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="6" column="0">
<widget class="QCheckBox" name="CheckboxLoadGeometry">
<property name="text">
<string>Load Window Geometry</string>
</property>
</widget>
</item>
<item row="22" column="0">
<widget class="QCheckBox" name="CheckboxAutoStartClient">
<property name="text">
<string>Start Client</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QCheckBox" name="CheckboxRunZoneChecks">
<property name="text">
<string>Run zone checks on rescan</string>
</property>
</widget>
</item>
<item row="11" column="0"> <item row="11" column="0">
<widget class="QLabel" name="DriversSettingsLabel"> <widget class="QLabel" name="DriversSettingsLabel">
<property name="text"> <property name="text">
@ -203,40 +216,34 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="24" column="0"> <item row="25" column="0">
<widget class="QCheckBox" name="CheckboxAutoStartProfile"> <widget class="QCheckBox" name="CheckboxAutoStartProfile">
<property name="text"> <property name="text">
<string>Load Profile</string> <string>Load Profile</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="23" column="1"> <item row="6" column="0">
<widget class="QLineEdit" name="TextCustomArgs"/> <widget class="QCheckBox" name="CheckboxLoadGeometry">
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="CheckboxTrayIconGreyscale">
<property name="text"> <property name="text">
<string>Greyscale Tray Icon</string> <string>Load Window Geometry</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="25" column="0"> <item row="24" column="0">
<widget class="QCheckBox" name="CheckboxSetOnExit"> <widget class="QCheckBox" name="CheckboxAutoStartCustom">
<property name="text"> <property name="text">
<string>Set Profile on Exit</string> <string>Custom Arguments</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="20" column="0"> <item row="13" column="0">
<widget class="QCheckBox" name="CheckboxAutoStartSetServerHost"> <widget class="QCheckBox" name="CheckboxSharedSMBusAccess">
<property name="text"> <property name="text">
<string>Set Server Host</string> <string>Shared SMBus Access (restart required)</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="20" column="1">
<widget class="QLineEdit" name="TextServerHost"/>
</item>
</layout> </layout>
</widget> </widget>
</widget> </widget>