summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Joseph W. Joshua <joejoshw@gmail.com>2014-06-14 22:27:57 +0300
committerGravatar Dirk Hohndel <dirk@hohndel.org>2014-06-14 12:50:35 -0700
commit1ec5e6ffc4f9f32a6d7149e52b161aeaba6adfa4 (patch)
tree58a6be26495b540d3471682a1a91369bfbd9a14e
parentcdd3b3d9cd5439cd56fb752e56a72045bed55f90 (diff)
downloadsubsurface-1ec5e6ffc4f9f32a6d7149e52b161aeaba6adfa4.tar.gz
OS Detection
Implements automatic OS and architecture detection. This code has been taken from the Qt repositories for Qt 5.4 (LGPL) and slightly modified into the SubsurfaceSysInfo class. Signed-off-by: Joseph W. Joshua <joejoshw@gmail.com> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
-rw-r--r--qt-ui/usersurvey.cpp4
-rw-r--r--subsurface.pro6
-rw-r--r--subsurfacesysinfo.cpp603
-rw-r--r--subsurfacesysinfo.h293
4 files changed, 903 insertions, 3 deletions
diff --git a/qt-ui/usersurvey.cpp b/qt-ui/usersurvey.cpp
index 7da7b3cdb..d9cee8ce8 100644
--- a/qt-ui/usersurvey.cpp
+++ b/qt-ui/usersurvey.cpp
@@ -8,12 +8,14 @@
#include "ssrf-version.h"
#include "helpers.h"
-
+#include "subsurfacesysinfo.h"
UserSurvey::UserSurvey(QWidget *parent) : QDialog(parent),
ui(new Ui::UserSurvey)
{
ui->setupUi(this);
// fill in the system data
+ ui->system->append(tr("Operating System: %1").arg(SubsurfaceSysInfo::prettyOsName()));
+ ui->system->append(tr("CPU Architecture: %1").arg(SubsurfaceSysInfo::cpuArchitecture()));
}
UserSurvey::~UserSurvey()
diff --git a/subsurface.pro b/subsurface.pro
index 8245f75d4..1172020c5 100644
--- a/subsurface.pro
+++ b/subsurface.pro
@@ -82,7 +82,8 @@ HEADERS = \
qt-ui/profile/ruleritem.h \
qt-ui/updatemanager.h \
qt-ui/divelogexportdialog.h \
- qt-ui/usersurvey.h
+ qt-ui/usersurvey.h \
+ subsurfacesysinfo.h
android: HEADERS -= \
qt-ui/usermanual.h \
@@ -160,7 +161,8 @@ SOURCES = \
qt-ui/profile/ruleritem.cpp \
qt-ui/updatemanager.cpp \
qt-ui/divelogexportdialog.cpp \
- qt-ui/usersurvey.cpp
+ qt-ui/usersurvey.cpp \
+ subsurfacesysinfo.cpp
android: SOURCES += android.cpp
else: linux*: SOURCES += linux.c
diff --git a/subsurfacesysinfo.cpp b/subsurfacesysinfo.cpp
new file mode 100644
index 000000000..5d556c6fc
--- /dev/null
+++ b/subsurfacesysinfo.cpp
@@ -0,0 +1,603 @@
+#include "subsurfacesysinfo.h"
+#include <QString>
+#include "qplatformdefs.h"
+
+#ifdef Q_OS_UNIX
+#include <sys/utsname.h>
+#endif
+
+// main part: processor type
+#if defined(Q_PROCESSOR_ALPHA)
+# define ARCH_PROCESSOR "alpha"
+#elif defined(Q_PROCESSOR_ARM)
+# define ARCH_PROCESSOR "arm"
+#elif defined(Q_PROCESSOR_AVR32)
+# define ARCH_PROCESSOR "avr32"
+#elif defined(Q_PROCESSOR_BLACKFIN)
+# define ARCH_PROCESSOR "bfin"
+#elif defined(Q_PROCESSOR_X86_32)
+# define ARCH_PROCESSOR "i386"
+#elif defined(Q_PROCESSOR_X86_64)
+# define ARCH_PROCESSOR "x86_64"
+#elif defined(Q_PROCESSOR_IA64)
+# define ARCH_PROCESSOR "ia64"
+#elif defined(Q_PROCESSOR_MIPS)
+# define ARCH_PROCESSOR "mips"
+#elif defined(Q_PROCESSOR_POWER)
+# define ARCH_PROCESSOR "power"
+#elif defined(Q_PROCESSOR_S390)
+# define ARCH_PROCESSOR "s390"
+#elif defined(Q_PROCESSOR_SH)
+# define ARCH_PROCESSOR "sh"
+#elif defined(Q_PROCESSOR_SPARC)
+# define ARCH_PROCESSOR "sparc"
+#else
+# define ARCH_PROCESSOR "unknown"
+#endif
+
+// endinanness
+#if defined(Q_LITTLE_ENDIAN)
+# define ARCH_ENDIANNESS "little_endian"
+#elif defined(Q_BIG_ENDIAN)
+# define ARCH_ENDIANNESS "big_endian"
+#endif
+
+// pointer type
+#if defined(Q_OS_WIN64) || (defined(Q_OS_WINRT) && defined(_M_X64))
+# define ARCH_POINTER "llp64"
+#elif defined(__LP64__) || QT_POINTER_SIZE - 0 == 8
+# define ARCH_POINTER "lp64"
+#else
+# define ARCH_POINTER "ilp32"
+#endif
+
+// secondary: ABI string (includes the dash)
+#if defined(__ARM_EABI__) || defined(__mips_eabi)
+# define ARCH_ABI1 "-eabi"
+#elif defined(_MIPS_SIM)
+# if _MIPS_SIM == _ABIO32
+# define ARCH_ABI1 "-o32"
+# elif _MIPS_SIM == _ABIN32
+# define ARCH_ABI1 "-n32"
+# elif _MIPS_SIM == _ABI64
+# define ARCH_ABI1 "-n64"
+# elif _MIPS_SIM == _ABIO64
+# define ARCH_ABI1 "-o64"
+# endif
+#else
+# define ARCH_ABI1 ""
+#endif
+#if defined(__ARM_PCS_VFP) || defined(__mips_hard_float)
+# define ARCH_ABI2 "-hardfloat"
+#else
+# define ARCH_ABI2 ""
+#endif
+
+#define ARCH_ABI ARCH_ABI1 ARCH_ABI2
+
+#define ARCH_FULL ARCH_PROCESSOR "-" ARCH_ENDIANNESS "-" ARCH_POINTER ARCH_ABI
+
+
+#if defined(Q_OS_OSX)
+
+Q_CORE_EXPORT OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref)
+{
+ return FSPathMakeRef(reinterpret_cast<const UInt8 *>(file.toUtf8().constData()), fsref, 0);
+}
+
+Q_CORE_EXPORT void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1)
+{
+ Q_UNUSED(encoding);
+ Q_UNUSED(len);
+ CFStringGetPascalString(QCFString(s), str, 256, CFStringGetSystemEncoding());
+}
+
+Q_CORE_EXPORT QString qt_mac_from_pascal_string(const Str255 pstr) {
+ return QCFString(CFStringCreateWithPascalString(0, pstr, CFStringGetSystemEncoding()));
+}
+
+SubsurfaceSysInfo::MacVersion SubsurfaceSysInfo::macVersion()
+{
+#if defined(Q_OS_OSX)
+ SInt32 gestalt_version;
+ if (Gestalt(gestaltSystemVersionMinor, &gestalt_version) == noErr) {
+ // add 2 because OS X 10.0 is 0x02 in the enum
+ return SubsurfaceSysInfo::MacVersion(gestalt_version + 2);
+ }
+#elif defined(Q_OS_IOS)
+ return qt_ios_version(); // qtcore_mac_objc.mm
+#endif
+ return SubsurfaceSysInfo::MV_Unknown;
+}
+const SubsurfaceSysInfo::MacVersion SubsurfaceSysInfo::MacintoshVersion = SubsurfaceSysInfo::macVersion();
+#elif defined(Q_OS_WIN) || defined(Q_OS_CYGWIN) || defined(Q_OS_WINCE) || defined(Q_OS_WINRT)
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "qt_windows.h"
+QT_END_INCLUDE_NAMESPACE
+
+#ifndef Q_OS_WINRT
+static inline OSVERSIONINFO winOsVersion()
+{
+ OSVERSIONINFO result = { sizeof(OSVERSIONINFO), 0, 0, 0, 0, {'\0'}};
+ // GetVersionEx() has been deprecated in Windows 8.1 and will return
+ // only Windows 8 from that version on.
+# if defined(_MSC_VER) && _MSC_VER >= 1800
+# pragma warning( push )
+# pragma warning( disable : 4996 )
+# endif
+ GetVersionEx(&result);
+# if defined(_MSC_VER) && _MSC_VER >= 1800
+# pragma warning( pop )
+# endif
+# ifndef Q_OS_WINCE
+ if (result.dwMajorVersion == 6 && result.dwMinorVersion == 2) {
+ // This could be Windows 8.1 or higher. Note that as of Windows 9,
+ // the major version needs to be checked as well.
+ DWORDLONG conditionMask = 0;
+ VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
+ VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
+ VER_SET_CONDITION(conditionMask, VER_PLATFORMID, VER_EQUAL);
+ OSVERSIONINFOEX checkVersion = { sizeof(OSVERSIONINFOEX), result.dwMajorVersion, result.dwMinorVersion,
+ result.dwBuildNumber, result.dwPlatformId, {'\0'}, 0, 0, 0, 0, 0 };
+ for ( ; VerifyVersionInfo(&checkVersion, VER_MAJORVERSION | VER_MINORVERSION | VER_PLATFORMID, conditionMask); ++checkVersion.dwMinorVersion)
+ result.dwMinorVersion = checkVersion.dwMinorVersion;
+ }
+# endif // !Q_OS_WINCE
+ return result;
+}
+#endif // !Q_OS_WINRT
+
+SubsurfaceSysInfo::WinVersion SubsurfaceSysInfo::windowsVersion()
+{
+#ifndef VER_PLATFORM_WIN32s
+#define VER_PLATFORM_WIN32s 0
+#endif
+#ifndef VER_PLATFORM_WIN32_WINDOWS
+#define VER_PLATFORM_WIN32_WINDOWS 1
+#endif
+#ifndef VER_PLATFORM_WIN32_NT
+#define VER_PLATFORM_WIN32_NT 2
+#endif
+#ifndef VER_PLATFORM_WIN32_CE
+#define VER_PLATFORM_WIN32_CE 3
+#endif
+
+ static SubsurfaceSysInfo::WinVersion winver;
+ if (winver)
+ return winver;
+#ifdef Q_OS_WINRT
+ winver = SubsurfaceSysInfo::WV_WINDOWS8;
+#else
+ winver = SubsurfaceSysInfo::WV_NT;
+ const OSVERSIONINFO osver = winOsVersion();
+#ifdef Q_OS_WINCE
+ DWORD qt_cever = 0;
+ qt_cever = osver.dwMajorVersion * 100;
+ qt_cever += osver.dwMinorVersion * 10;
+#endif
+ switch (osver.dwPlatformId) {
+ case VER_PLATFORM_WIN32s:
+ winver = SubsurfaceSysInfo::WV_32s;
+ break;
+ case VER_PLATFORM_WIN32_WINDOWS:
+ // We treat Windows Me (minor 90) the same as Windows 98
+ if (osver.dwMinorVersion == 90)
+ winver = SubsurfaceSysInfo::WV_Me;
+ else if (osver.dwMinorVersion == 10)
+ winver = SubsurfaceSysInfo::WV_98;
+ else
+ winver = SubsurfaceSysInfo::WV_95;
+ break;
+#ifdef Q_OS_WINCE
+ case VER_PLATFORM_WIN32_CE:
+ if (qt_cever >= 600)
+ winver = SubsurfaceSysInfo::WV_CE_6;
+ if (qt_cever >= 500)
+ winver = SubsurfaceSysInfo::WV_CE_5;
+ else if (qt_cever >= 400)
+ winver = SubsurfaceSysInfo::WV_CENET;
+ else
+ winver = SubsurfaceSysInfo::WV_CE;
+ break;
+#endif
+ default: // VER_PLATFORM_WIN32_NT
+ if (osver.dwMajorVersion < 5) {
+ winver = SubsurfaceSysInfo::WV_NT;
+ } else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 0) {
+ winver = SubsurfaceSysInfo::WV_2000;
+ } else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 1) {
+ winver = SubsurfaceSysInfo::WV_XP;
+ } else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion == 2) {
+ winver = SubsurfaceSysInfo::WV_2003;
+ } else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 0) {
+ winver = SubsurfaceSysInfo::WV_VISTA;
+ } else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 1) {
+ winver = SubsurfaceSysInfo::WV_WINDOWS7;
+ } else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2) {
+ winver = SubsurfaceSysInfo::WV_WINDOWS8;
+ } else if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 3) {
+ winver = SubsurfaceSysInfo::WV_WINDOWS8_1;
+ } else {
+ qWarning("Qt: Untested Windows version %d.%d detected!",
+ int(osver.dwMajorVersion), int(osver.dwMinorVersion));
+ winver = SubsurfaceSysInfo::WV_NT_based;
+ }
+ }
+
+#ifdef QT_DEBUG
+ {
+ QByteArray override = qgetenv("QT_WINVER_OVERRIDE");
+ if (override.isEmpty())
+ return winver;
+
+ if (override == "Me")
+ winver = SubsurfaceSysInfo::WV_Me;
+ if (override == "95")
+ winver = SubsurfaceSysInfo::WV_95;
+ else if (override == "98")
+ winver = SubsurfaceSysInfo::WV_98;
+ else if (override == "NT")
+ winver = SubsurfaceSysInfo::WV_NT;
+ else if (override == "2000")
+ winver = SubsurfaceSysInfo::WV_2000;
+ else if (override == "2003")
+ winver = SubsurfaceSysInfo::WV_2003;
+ else if (override == "XP")
+ winver = SubsurfaceSysInfo::WV_XP;
+ else if (override == "VISTA")
+ winver = SubsurfaceSysInfo::WV_VISTA;
+ else if (override == "WINDOWS7")
+ winver = SubsurfaceSysInfo::WV_WINDOWS7;
+ else if (override == "WINDOWS8")
+ winver = SubsurfaceSysInfo::WV_WINDOWS8;
+ else if (override == "WINDOWS8_1")
+ winver = SubsurfaceSysInfo::WV_WINDOWS8_1;
+ }
+#endif
+#endif // !Q_OS_WINRT
+
+ return winver;
+}
+
+static const char *winVer_helper()
+{
+ switch (int(SubsurfaceSysInfo::WindowsVersion)) {
+ case SubsurfaceSysInfo::WV_NT:
+ return "NT";
+ case SubsurfaceSysInfo::WV_2000:
+ return "2000";
+ case SubsurfaceSysInfo::WV_XP:
+ return "XP";
+ case SubsurfaceSysInfo::WV_2003:
+ return "2003";
+ case SubsurfaceSysInfo::WV_VISTA:
+ return "Vista";
+ case SubsurfaceSysInfo::WV_WINDOWS7:
+ return "7";
+ case SubsurfaceSysInfo::WV_WINDOWS8:
+ return "8";
+ case SubsurfaceSysInfo::WV_WINDOWS8_1:
+ return "8.1";
+
+ case SubsurfaceSysInfo::WV_CE:
+ return "CE";
+ case SubsurfaceSysInfo::WV_CENET:
+ return "CENET";
+ case SubsurfaceSysInfo::WV_CE_5:
+ return "CE5";
+ case SubsurfaceSysInfo::WV_CE_6:
+ return "CE6";
+ }
+ // unknown, future version
+ return 0;
+}
+
+const SubsurfaceSysInfo::WinVersion SubsurfaceSysInfo::WindowsVersion = SubsurfaceSysInfo::windowsVersion();
+
+#endif
+
+#if defined(Q_OS_UNIX)
+# if (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD)
+# define USE_ETC_OS_RELEASE
+# endif
+struct QUnixOSVersion
+{
+ // from uname(2)
+ QString sysName;
+ QString sysNameLower;
+ QString sysRelease;
+
+# if !defined(Q_OS_ANDROID) && !defined(Q_OS_BLACKBERRY) && !defined(Q_OS_MAC)
+ // from /etc/os-release or guessed
+ QString versionIdentifier; // ${ID}_$VERSION_ID
+ QString versionText; // $PRETTY_NAME
+# endif
+};
+
+
+#ifdef USE_ETC_OS_RELEASE
+static QString unquote(const char *begin, const char *end)
+{
+ if (*begin == '"') {
+ Q_ASSERT(end[-1] == '"');
+ return QString::fromLatin1(begin + 1, end - begin - 2);
+ }
+ return QString::fromLatin1(begin, end - begin);
+}
+
+
+static bool readEtcOsRelease(QUnixOSVersion &v)
+{
+ // we're avoiding QFile here
+
+ int fd = QT_OPEN("/etc/os-release", O_RDONLY);
+ if (fd == -1)
+ return false;
+
+ QT_STATBUF sbuf;
+ if (QT_FSTAT(fd, &sbuf) == -1) {
+ QT_CLOSE(fd);
+ return false;
+ }
+
+ QString partialIdentifier;
+ QByteArray buffer(sbuf.st_size, Qt::Uninitialized);
+ buffer.resize(QT_READ(fd, buffer.data(), sbuf.st_size));
+ QT_CLOSE(fd);
+
+ const char *ptr = buffer.constData();
+ const char *end = buffer.constEnd();
+ const char *eol;
+ for ( ; ptr != end; ptr = eol + 1) {
+ static const char idString[] = "ID=";
+ static const char prettyNameString[] = "PRETTY_NAME=";
+ static const char versionIdString[] = "VERSION_ID=";
+
+ // find the end of the line after ptr
+ eol = static_cast<const char *>(memchr(ptr, '\n', end - ptr));
+ if (!eol)
+ eol = end - 1;
+
+ int cmp = strncmp(ptr, idString, strlen(idString));
+ if (cmp < 0)
+ continue;
+ if (cmp == 0) {
+ ptr += strlen(idString);
+ QString id = unquote(ptr, eol);
+ if (partialIdentifier.isNull())
+ partialIdentifier = id;
+ else
+ v.versionIdentifier = id + QLatin1Char('_') + partialIdentifier;
+ continue;
+ }
+
+ cmp = strncmp(ptr, prettyNameString, strlen(prettyNameString));
+ if (cmp < 0)
+ continue;
+ if (cmp == 0) {
+ ptr += strlen(prettyNameString);
+ v.versionText = unquote(ptr, eol);
+ continue;
+ }
+
+ cmp = strncmp(ptr, versionIdString, strlen(versionIdString));
+ if (cmp < 0)
+ continue;
+ if (cmp == 0) {
+ ptr += strlen(versionIdString);
+ QString id = unquote(ptr, eol);
+ if (partialIdentifier.isNull())
+ partialIdentifier = id;
+ else
+ v.versionIdentifier = partialIdentifier + QLatin1Char('_') + id;
+ continue;
+ }
+ }
+
+ return true;
+}
+#endif // USE_ETC_OS_RELEASE
+
+static QUnixOSVersion detectUnixVersion()
+{
+ QUnixOSVersion v;
+ struct utsname u;
+ if (uname(&u) != -1) {
+ v.sysName = QString::fromLatin1(u.sysname);
+ v.sysNameLower = v.sysName.toLower();
+ v.sysRelease = QString::fromLatin1(u.release);
+ } else {
+ v.sysName = QLatin1String("Detection failed");
+ // leave sysNameLower & sysRelease unset
+ }
+
+# if !defined(Q_OS_ANDROID) && !defined(Q_OS_BLACKBERRY) && !defined(Q_OS_MAC)
+# ifdef USE_ETC_OS_RELEASE
+ if (readEtcOsRelease(v))
+ return v;
+# endif
+
+ if (!v.sysNameLower.isEmpty()) {
+ // will produce "qnx_6.5" or "sunos_5.9"
+ v.versionIdentifier = v.sysNameLower + QLatin1Char('_') + v.sysRelease;
+ }
+# endif
+
+ return v;
+}
+#endif
+
+QString SubsurfaceSysInfo::unknownText()
+{
+ return QStringLiteral("unknown");
+}
+
+QString SubsurfaceSysInfo::cpuArchitecture()
+{
+ return QStringLiteral(ARCH_PROCESSOR);
+}
+
+QString SubsurfaceSysInfo::fullCpuArchitecture()
+{
+ return QLatin1String(ARCH_FULL);
+}
+
+QString SubsurfaceSysInfo::osType()
+{
+#if defined(Q_OS_WINPHONE)
+ return QStringLiteral("winphone");
+#elif defined(Q_OS_WINRT)
+ return QStringLiteral("winrt");
+#elif defined(Q_OS_WINCE)
+ return QStringLiteral("wince");
+#elif defined(Q_OS_WIN)
+ return QStringLiteral("windows");
+
+#elif defined(Q_OS_BLACKBERRY)
+ return QStringLiteral("blackberry");
+#elif defined(Q_OS_QNX)
+ return QStringLiteral("qnx");
+
+#elif defined(Q_OS_ANDROID)
+ return QStringLiteral("android");
+#elif defined(Q_OS_LINUX)
+ return QStringLiteral("linux");
+
+#elif defined(Q_OS_IOS)
+ return QStringLiteral("ios");
+#elif defined(Q_OS_OSX)
+ return QStringLiteral("osx");
+#elif defined(Q_OS_DARWIN)
+ return QStringLiteral("darwin");
+
+#elif defined(Q_OS_FREEBSD_KERNEL)
+ return QStringLiteral("freebsd");
+#elif defined(Q_OS_UNIX)
+ QUnixOSVersion unixOsVersion = detectUnixVersion();
+ if (!unixOsVersion.sysNameLower.isEmpty())
+ return unixOsVersion.sysNameLower;
+#endif
+ return unknownText();
+}
+
+QString SubsurfaceSysInfo::osKernelVersion()
+{
+#ifdef Q_OS_WINRT
+ // TBD
+ return QString();
+#elif defined(Q_OS_WIN)
+ const OSVERSIONINFO osver = winOsVersion();
+ return QString::number(int(osver.dwMajorVersion)) + QLatin1Char('.') + QString::number(int(osver.dwMinorVersion))
+ + QLatin1Char('.') + QString::number(int(osver.dwBuildNumber));
+#else
+ return detectUnixVersion().sysRelease;
+#endif
+}
+
+QString SubsurfaceSysInfo::osVersion()
+{
+#if defined(Q_OS_IOS)
+ int major = (int(MacintoshVersion) >> 4) & 0xf;
+ int minor = int(MacintoshVersion) & 0xf;
+ if (Q_LIKELY(major < 10 && minor < 10)) {
+ char buf[4] = { char(major + '0'), '.', char(minor + '0'), '\0' };
+ return QString::fromLatin1(buf, 3);
+ }
+ return QString::number(major) + QLatin1Char('.') + QString::number(minor);
+#elif defined(Q_OS_OSX)
+ int minor = int(MacintoshVersion) - 2; // we're not running on Mac OS 9
+ Q_ASSERT(minor < 100);
+ char buf[] = "10.0\0";
+ if (Q_LIKELY(minor < 10)) {
+ buf[3] += minor;
+ } else {
+ buf[3] += minor / 10;
+ buf[4] = '0' + minor % 10;
+ }
+ return QString::fromLatin1(buf);
+#elif defined(Q_OS_WIN)
+ const char *version = winVer_helper();
+ if (version)
+ return QString::fromLatin1(version).toLower();
+ // fall through
+
+ // Android and Blackberry should not fall through to the Unix code
+#elif defined(Q_OS_ANDROID)
+ // TBD
+#elif defined(Q_OS_BLACKBERRY)
+ deviceinfo_details_t *deviceInfo;
+ if (deviceinfo_get_details(&deviceInfo) == BPS_SUCCESS) {
+ QString bbVersion = QString::fromLatin1(deviceinfo_details_get_device_os_version(deviceInfo));
+ deviceinfo_free_details(&deviceInfo);
+ return bbVersion;
+ }
+#elif defined(Q_OS_UNIX)
+ QUnixOSVersion unixOsVersion = detectUnixVersion();
+ if (!unixOsVersion.versionIdentifier.isEmpty())
+ return unixOsVersion.versionIdentifier;
+#endif
+
+ // fallback
+ return unknownText();
+}
+
+QString SubsurfaceSysInfo::prettyOsName()
+{
+#if defined(Q_OS_IOS)
+ return QLatin1String("iOS ") + osVersion();
+#elif defined(Q_OS_OSX)
+ // get the known codenames
+ const char *basename = 0;
+ switch (int(MacintoshVersion)) {
+ case MV_CHEETAH:
+ case MV_PUMA:
+ case MV_JAGUAR:
+ case MV_PANTHER:
+ case MV_TIGER:
+ // This version of Qt does not run on those versions of OS X
+ // so this case label will never be reached
+ Q_UNREACHABLE();
+ break;
+ case MV_LEOPARD:
+ basename = "Mac OS X Leopard (";
+ break;
+ case MV_SNOWLEOPARD:
+ basename = "Mac OS X Snow Leopard (";
+ break;
+ case MV_LION:
+ basename = "Mac OS X Lion (";
+ break;
+ case MV_MOUNTAINLION:
+ basename = "OS X Mountain Lion (";
+ break;
+ case MV_MAVERICKS:
+ basename = "OS X Mavericks (";
+ break;
+ case MV_YOSEMITE:
+ basename = "OS X Yosemite (";
+ break;
+ }
+ if (basename)
+ return QLatin1String(basename) + osVersion() + QLatin1Char(')');
+
+ // a future version of OS X
+ return QLatin1String("OS X ") + osVersion();
+#elif defined(Q_OS_WINPHONE)
+ return QLatin1String("Windows Phone ") + QLatin1String(winVer_helper());
+#elif defined(Q_OS_WIN)
+ return QLatin1String("Windows ") + QLatin1String(winVer_helper());
+#elif defined(Q_OS_ANDROID)
+ return QLatin1String("Android ") + osVersion();
+#elif defined(Q_OS_BLACKBERRY)
+ return QLatin1String("BlackBerry ") + osVersion();
+#elif defined(Q_OS_UNIX)
+ QUnixOSVersion unixOsVersion = detectUnixVersion();
+ if (unixOsVersion.versionText.isEmpty())
+ return unixOsVersion.sysName;
+ else
+ return unixOsVersion.sysName + QLatin1String(" (") + unixOsVersion.versionText + QLatin1Char(')');
+#else
+ return unknownText();
+#endif
+}
diff --git a/subsurfacesysinfo.h b/subsurfacesysinfo.h
new file mode 100644
index 000000000..8018ddb31
--- /dev/null
+++ b/subsurfacesysinfo.h
@@ -0,0 +1,293 @@
+#ifndef SUBSURFACESYSINFO_H
+#define SUBSURFACESYSINFO_H
+
+#include <QtGlobal>
+
+#if defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM) || defined(__arm64__)
+# define Q_PROCESSOR_ARM
+# if defined(__arm64__)
+# define Q_PROCESSOR_ARM_64
+# else
+# define Q_PROCESSOR_ARM_32
+# endif
+# if defined(__ARM64_ARCH_8__)
+# define Q_PROCESSOR_ARM_V8
+# define Q_PROCESSOR_ARM_V7
+# define Q_PROCESSOR_ARM_V6
+# define Q_PROCESSOR_ARM_V5
+# elif defined(__ARM_ARCH_7__) \
+ || defined(__ARM_ARCH_7A__) \
+ || defined(__ARM_ARCH_7R__) \
+ || defined(__ARM_ARCH_7M__) \
+ || defined(__ARM_ARCH_7S__) \
+ || defined(_ARM_ARCH_7) \
+ || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 7) \
+ || (defined(_M_ARM) && _M_ARM-0 >= 7)
+# define Q_PROCESSOR_ARM_V7
+# define Q_PROCESSOR_ARM_V6
+# define Q_PROCESSOR_ARM_V5
+# elif defined(__ARM_ARCH_6__) \
+ || defined(__ARM_ARCH_6J__) \
+ || defined(__ARM_ARCH_6T2__) \
+ || defined(__ARM_ARCH_6Z__) \
+ || defined(__ARM_ARCH_6K__) \
+ || defined(__ARM_ARCH_6ZK__) \
+ || defined(__ARM_ARCH_6M__) \
+ || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 6) \
+ || (defined(_M_ARM) && _M_ARM-0 >= 6)
+# define Q_PROCESSOR_ARM_V6
+# define Q_PROCESSOR_ARM_V5
+# elif defined(__ARM_ARCH_5TEJ__) \
+ || defined(__ARM_ARCH_5TE__) \
+ || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 5) \
+ || (defined(_M_ARM) && _M_ARM-0 >= 5)
+# define Q_PROCESSOR_ARM_V5
+# endif
+# if defined(__ARMEL__)
+# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
+# elif defined(__ARMEB__)
+# define Q_BYTE_ORDER Q_BIG_ENDIAN
+# else
+// Q_BYTE_ORDER not defined, use endianness auto-detection
+#endif
+
+
+#elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
+# define Q_PROCESSOR_X86_32
+# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
+
+# if defined(_M_IX86)
+# define Q_PROCESSOR_X86 (_M_IX86/100)
+# elif defined(__i686__) || defined(__athlon__) || defined(__SSE__)
+# define Q_PROCESSOR_X86 6
+# elif defined(__i586__) || defined(__k6__)
+# define Q_PROCESSOR_X86 5
+# elif defined(__i486__)
+# define Q_PROCESSOR_X86 4
+# else
+# define Q_PROCESSOR_X86 3
+#endif
+
+#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64)
+# define Q_PROCESSOR_X86 6
+# define Q_PROCESSOR_X86_64
+# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
+# define Q_PROCESSOR_WORDSIZE 8
+
+#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
+# define Q_PROCESSOR_IA64
+# define Q_PROCESSOR_WORDSIZE 8
+
+#elif defined(__mips) || defined(__mips__) || defined(_M_MRX000)
+# define Q_PROCESSOR_MIPS
+# if defined(_MIPS_ARCH_MIPS1) || (defined(__mips) && __mips - 0 >= 1)
+# define Q_PROCESSOR_MIPS_I
+# endif
+# if defined(_MIPS_ARCH_MIPS2) || (defined(__mips) && __mips - 0 >= 2)
+# define Q_PROCESSOR_MIPS_II
+# endif
+# if defined(_MIPS_ARCH_MIPS32) || defined(__mips32)
+# define Q_PROCESSOR_MIPS_32
+# endif
+# if defined(_MIPS_ARCH_MIPS3) || (defined(__mips) && __mips - 0 >= 3)
+# define Q_PROCESSOR_MIPS_III
+# endif
+# if defined(_MIPS_ARCH_MIPS4) || (defined(__mips) && __mips - 0 >= 4)
+# define Q_PROCESSOR_MIPS_IV
+# endif
+# if defined(_MIPS_ARCH_MIPS5) || (defined(__mips) && __mips - 0 >= 5)
+# define Q_PROCESSOR_MIPS_V
+# endif
+# if defined(_MIPS_ARCH_MIPS64) || defined(__mips64)
+# define Q_PROCESSOR_MIPS_64
+# endif
+# if defined(__MIPSEL__)
+# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
+# elif defined(__MIPSEB__)
+# define Q_BYTE_ORDER Q_BIG_ENDIAN
+# else
+// Q_BYTE_ORDER not defined, use endianness auto-detection
+#endif
+
+
+#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \
+ || defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \
+ || defined(_M_MPPC) || defined(_M_PPC)
+# define Q_PROCESSOR_POWER
+# if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__)
+# define Q_PROCESSOR_POWER_64
+# else
+# define Q_PROCESSOR_POWER_32
+# endif
+
+#elif defined(__s390__)
+# define Q_PROCESSOR_S390
+# if defined(__s390x__)
+# define Q_PROCESSOR_S390_X
+# endif
+# define Q_BYTE_ORDER Q_BIG_ENDIAN
+
+
+#endif
+
+// Some processors support either endian format, try to detect which we are using.
+#if !defined(Q_BYTE_ORDER)
+# if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == Q_BIG_ENDIAN || __BYTE_ORDER__ == Q_LITTLE_ENDIAN)
+// Reuse __BYTE_ORDER__ as-is, since our Q_*_ENDIAN #defines match the preprocessor defaults
+# define Q_BYTE_ORDER __BYTE_ORDER__
+# elif defined(__BIG_ENDIAN__) || defined(_big_endian__) || defined(_BIG_ENDIAN)
+# define Q_BYTE_ORDER Q_BIG_ENDIAN
+# elif defined(__LITTLE_ENDIAN__) || defined(_little_endian__) || defined(_LITTLE_ENDIAN) \
+ || defined(_WIN32_WCE) || defined(WINAPI_FAMILY) // Windows CE is always little-endian according to MSDN.
+# define Q_BYTE_ORDER Q_LITTLE_ENDIAN
+# else
+# error "Unable to determine byte order!"
+# endif
+#endif
+
+#ifndef Q_PROCESSOR_WORDSIZE
+# ifdef __SIZEOF_POINTER__
+/* GCC & friends define this */
+# define Q_PROCESSOR_WORDSIZE __SIZEOF_POINTER__
+# elif defined(_LP64) || defined(__LP64__) || defined(WIN64) || defined(_WIN64)
+# define Q_PROCESSOR_WORDSIZE 8
+# else
+# define Q_PROCESSOR_WORDSIZE QT_POINTER_SIZE
+# endif
+#endif
+
+class QString;
+class SubsurfaceSysInfo {
+public:
+ enum Sizes {
+ WordSize = (sizeof(void *)<<3)
+ };
+
+#ifndef QStringLiteral
+ // no lambdas, not GCC, or GCC in C++98 mode with 4-byte wchar_t
+ // fallback, return a temporary QString
+ // source code is assumed to be encoded in UTF-8
+
+# define QStringLiteral(str) QString::fromUtf8("" str "", sizeof(str) - 1)
+#endif
+
+
+#if defined(QT_BUILD_QMAKE)
+ enum Endian {
+ BigEndian,
+ LittleEndian
+ };
+ /* needed to bootstrap qmake */
+ static const int ByteOrder;
+#elif defined(Q_BYTE_ORDER)
+ enum Endian {
+ BigEndian,
+ LittleEndian
+
+# ifdef Q_QDOC
+ , ByteOrder = <platform-dependent>
+# elif Q_BYTE_ORDER == Q_BIG_ENDIAN
+ , ByteOrder = BigEndian
+# elif Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ , ByteOrder = LittleEndian
+# else
+# error "Undefined byte order"
+# endif
+ };
+#endif
+#if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN)
+ enum WinVersion {
+ WV_32s = 0x0001,
+ WV_95 = 0x0002,
+ WV_98 = 0x0003,
+ WV_Me = 0x0004,
+ WV_DOS_based= 0x000f,
+
+ /* codenames */
+ WV_NT = 0x0010,
+ WV_2000 = 0x0020,
+ WV_XP = 0x0030,
+ WV_2003 = 0x0040,
+ WV_VISTA = 0x0080,
+ WV_WINDOWS7 = 0x0090,
+ WV_WINDOWS8 = 0x00a0,
+ WV_WINDOWS8_1 = 0x00b0,
+ WV_NT_based = 0x00f0,
+
+ /* version numbers */
+ WV_4_0 = WV_NT,
+ WV_5_0 = WV_2000,
+ WV_5_1 = WV_XP,
+ WV_5_2 = WV_2003,
+ WV_6_0 = WV_VISTA,
+ WV_6_1 = WV_WINDOWS7,
+ WV_6_2 = WV_WINDOWS8,
+ WV_6_3 = WV_WINDOWS8_1,
+
+ WV_CE = 0x0100,
+ WV_CENET = 0x0200,
+ WV_CE_5 = 0x0300,
+ WV_CE_6 = 0x0400,
+ WV_CE_based = 0x0f00
+ };
+ static const WinVersion WindowsVersion;
+ static WinVersion windowsVersion();
+
+#endif
+#ifdef Q_OS_MAC
+# define Q_MV_IOS(major, minor) (QSysInfo::MV_IOS | major << 4 | minor)
+ enum MacVersion {
+ MV_Unknown = 0x0000,
+
+ /* version */
+ MV_9 = 0x0001,
+ MV_10_0 = 0x0002,
+ MV_10_1 = 0x0003,
+ MV_10_2 = 0x0004,
+ MV_10_3 = 0x0005,
+ MV_10_4 = 0x0006,
+ MV_10_5 = 0x0007,
+ MV_10_6 = 0x0008,
+ MV_10_7 = 0x0009,
+ MV_10_8 = 0x000A,
+ MV_10_9 = 0x000B,
+ MV_10_10 = 0x000C,
+
+ /* codenames */
+ MV_CHEETAH = MV_10_0,
+ MV_PUMA = MV_10_1,
+ MV_JAGUAR = MV_10_2,
+ MV_PANTHER = MV_10_3,
+ MV_TIGER = MV_10_4,
+ MV_LEOPARD = MV_10_5,
+ MV_SNOWLEOPARD = MV_10_6,
+ MV_LION = MV_10_7,
+ MV_MOUNTAINLION = MV_10_8,
+ MV_MAVERICKS = MV_10_9,
+ MV_YOSEMITE = MV_10_10,
+
+ /* iOS */
+ MV_IOS = 1 << 8,
+ MV_IOS_4_3 = Q_MV_IOS(4, 3),
+ MV_IOS_5_0 = Q_MV_IOS(5, 0),
+ MV_IOS_5_1 = Q_MV_IOS(5, 1),
+ MV_IOS_6_0 = Q_MV_IOS(6, 0),
+ MV_IOS_6_1 = Q_MV_IOS(6, 1),
+ MV_IOS_7_0 = Q_MV_IOS(7, 0),
+ MV_IOS_7_1 = Q_MV_IOS(7, 1),
+ MV_IOS_8_0 = Q_MV_IOS(8, 0)
+ };
+ static const MacVersion MacintoshVersion;
+ static MacVersion macVersion();
+#endif
+ static QString unknownText();
+ static QString cpuArchitecture();
+ static QString fullCpuArchitecture();
+ static QString osType();
+ static QString osKernelVersion();
+ static QString osVersion();
+ static QString prettyOsName();
+};
+
+
+#endif // SUBSURFACESYSINFO_H