#include "config.h"
#include <wtf/glib/ChassisType.h>
#include <mutex>
#include <wtf/Optional.h>
#include <wtf/glib/GUniquePtr.h>
namespace WTF {
static Optional<ChassisType> readMachineInfoChassisType()
{
GUniqueOutPtr<char> buffer;
GUniqueOutPtr<GError> error;
if (!g_file_get_contents("/etc/machine-info", &buffer.outPtr(), nullptr, &error.outPtr())) {
if (!g_error_matches(error.get(), G_FILE_ERROR, G_FILE_ERROR_NOENT))
g_warning("Could not open /etc/machine-info: %s", error->message);
return WTF::nullopt;
}
GUniquePtr<char*> split(g_strsplit(buffer.get(), "\n", -1));
for (int i = 0; split.get()[i]; ++i) {
if (g_str_has_prefix(split.get()[i], "CHASSIS=")) {
char* chassis = split.get()[i] + 8;
if (!strcmp(chassis, "tablet") || !strcmp(chassis, "handset"))
return ChassisType::Mobile;
return ChassisType::Desktop;
}
}
return WTF::nullopt;
}
static Optional<ChassisType> readDMIChassisType()
{
GUniqueOutPtr<char> buffer;
GUniqueOutPtr<GError> error;
if (g_file_get_contents("/sys/class/dmi/id/chassis_type", &buffer.outPtr(), nullptr, &error.outPtr())) {
int type = strtol(buffer.get(), nullptr, 10);
switch (type) {
case 0x3:
case 0x4:
case 0x6:
case 0x7:
case 0x8:
case 0x9:
case 0xA:
case 0xE:
case 0x11:
case 0x1C:
case 0x1D:
case 0x1F:
case 0x20:
return ChassisType::Desktop;
case 0xB:
case 0x1E:
return ChassisType::Mobile;
}
} else if (!g_error_matches(error.get(), G_FILE_ERROR, G_FILE_ERROR_NOENT))
g_warning("Could not open /sys/class/dmi/id/chassis_type: %s", error->message);
return WTF::nullopt;
}
static Optional<ChassisType> readACPIChassisType()
{
GUniqueOutPtr<char> buffer;
GUniqueOutPtr<GError> error;
if (g_file_get_contents("/sys/firmware/acpi/pm_profile", &buffer.outPtr(), nullptr, &error.outPtr())) {
int type = strtol(buffer.get(), nullptr, 10);
switch (type) {
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
return ChassisType::Desktop;
case 8:
return ChassisType::Mobile;
}
} else if (!g_error_matches(error.get(), G_FILE_ERROR, G_FILE_ERROR_NOENT))
g_warning("Could not open /sys/firmware/acpi/pm_profile: %s", error->message);
return WTF::nullopt;
}
ChassisType chassisType()
{
static ChassisType chassisType;
static std::once_flag initializeChassis;
std::call_once(initializeChassis, [] {
Optional<ChassisType> optionalChassisType = readMachineInfoChassisType();
if (!optionalChassisType)
optionalChassisType = readDMIChassisType();
if (!optionalChassisType)
optionalChassisType = readACPIChassisType();
chassisType = optionalChassisType.valueOr(ChassisType::Desktop);
});
return chassisType;
}
}