1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * Copyright (C) 2007 by Dominik Wenger
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
30 #if defined(Q_OS_WIN32)
41 // Linux and Mac includes
42 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
44 #include <libusb-1.0/libusb.h>
48 #include <sys/utsname.h>
54 #if defined(Q_OS_LINUX)
59 #if defined(Q_OS_MACX)
60 #include <sys/param.h>
61 #include <sys/ucred.h>
62 #include <sys/mount.h>
64 #include <CoreFoundation/CoreFoundation.h>
65 #include <SystemConfiguration/SystemConfiguration.h>
66 #include <CoreServices/CoreServices.h>
67 #include <IOKit/IOKitLib.h>
68 #include <IOKit/usb/IOUSBLib.h>
72 #include "rbsettings.h"
74 /** @brief detect permission of user (only Windows at moment).
75 * @return enum userlevel.
77 #if defined(Q_OS_WIN32)
78 enum System::userlevel
System::userPermissions(void)
81 NET_API_STATUS napistatus
;
82 wchar_t userbuf
[UNLEN
];
83 DWORD usersize
= UNLEN
;
85 enum userlevel result
;
87 status
= GetUserNameW(userbuf
, &usersize
);
91 napistatus
= NetUserGetInfo(NULL
, userbuf
, (DWORD
)1, (LPBYTE
*)&buf
);
93 switch(buf
->usri1_priv
) {
100 case USER_PRIV_ADMIN
:
107 NetApiBufferFree(buf
);
112 /** @brief detects user permissions (only Windows at moment).
113 * @return a user readable string with the permission.
115 QString
System::userPermissionsString(void)
118 int perm
= userPermissions();
121 result
= tr("Guest");
124 result
= tr("Admin");
130 result
= tr("Error");
138 /** @brief detects current Username.
139 * @return string with Username.
141 QString
System::userName(void)
143 #if defined(Q_OS_WIN32)
144 wchar_t userbuf
[UNLEN
];
145 DWORD usersize
= UNLEN
;
148 status
= GetUserNameW(userbuf
, &usersize
);
150 return QString::fromWCharArray(userbuf
);
152 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
154 user
= getpwuid(geteuid());
155 return QString(user
->pw_name
);
160 /** @brief detects the OS Version
161 * @return String with OS Version.
163 QString
System::osVersionString(void)
166 #if defined(Q_OS_WIN32)
169 ZeroMemory(&osvi
, sizeof(OSVERSIONINFO
));
170 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
172 GetSystemInfo(&sysinfo
);
174 result
= QString("Windows version %1.%2, ").arg(osvi
.dwMajorVersion
).arg(osvi
.dwMinorVersion
);
175 if(osvi
.szCSDVersion
)
176 result
+= QString("build %1 (%2)").arg(osvi
.dwBuildNumber
)
177 .arg(QString::fromWCharArray(osvi
.szCSDVersion
));
179 result
+= QString("build %1").arg(osvi
.dwBuildNumber
);
180 result
+= QString("<br/>CPU: %1, %2 processor(s)").arg(sysinfo
.dwProcessorType
)
181 .arg(sysinfo
.dwNumberOfProcessors
);
183 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
188 #if defined(Q_OS_MACX)
189 ItemCount cores
= MPProcessors();
191 long cores
= sysconf(_SC_NPROCESSORS_ONLN
);
193 result
= QString("CPU: %1, %2 processor(s)").arg(u
.machine
).arg(cores
);
194 result
+= QString("<br/>System: %2<br/>Release: %3<br/>Version: %4")
195 .arg(u
.sysname
).arg(u
.release
).arg(u
.version
);
196 #if defined(Q_OS_MACX)
201 error
= Gestalt(gestaltSystemVersionMajor
, &major
);
202 error
= Gestalt(gestaltSystemVersionMinor
, &minor
);
203 error
= Gestalt(gestaltSystemVersionBugFix
, &bugfix
);
205 result
+= QString("<br/>OS X %1.%2.%3 ").arg(major
).arg(minor
).arg(bugfix
);
206 // 1: 86k, 2: ppc, 10: i386
208 error
= Gestalt(gestaltSysArchitecture
, &arch
);
211 result
.append("(86k)");
214 result
.append("(ppc)");
217 result
.append("(x86)");
220 result
.append("(unknown)");
225 result
+= QString("<br/>Qt version %1").arg(qVersion());
229 QList
<uint32_t> System::listUsbIds(void)
231 return listUsbDevices().keys();
234 /** @brief detect devices based on usb pid / vid.
235 * @return list with usb VID / PID values.
237 QMap
<uint32_t, QString
> System::listUsbDevices(void)
239 QMap
<uint32_t, QString
> usbids
;
241 qDebug() << "[System] Searching for USB devices";
242 #if defined(Q_OS_LINUX)
244 libusb_device
**devs
;
247 res
= libusb_init(NULL
);
249 count
= libusb_get_device_list(NULL
, &devs
);
252 while((dev
= devs
[i
++]) != NULL
) {
254 unsigned char buf
[256];
256 struct libusb_device_descriptor descriptor
;
257 if(libusb_get_device_descriptor(dev
, &descriptor
) == 0) {
258 id
= descriptor
.idVendor
<< 16 | descriptor
.idProduct
;
260 libusb_device_handle
*dh
;
261 if(libusb_open(dev
, &dh
) == 0) {
262 libusb_get_string_descriptor_ascii(dh
, descriptor
.iManufacturer
, buf
, 256);
263 name
+= QString::fromAscii((char*)buf
) + " ";
264 libusb_get_string_descriptor_ascii(dh
, descriptor
.iProduct
, buf
, 256);
265 name
+= QString::fromAscii((char*)buf
);
269 name
= tr("(no description available)");
271 usbids
.insert(id
, name
);
272 qDebug("[System] USB: 0x%08x, %s", id
, name
.toLocal8Bit().data());
277 libusb_free_device_list(devs
, 1);
288 struct usb_device
*u
;
292 id
= u
->descriptor
.idVendor
<< 16 | u
->descriptor
.idProduct
;
293 // get identification strings
300 if(u
->descriptor
.iManufacturer
) {
301 res
= usb_get_string_simple(dev
, u
->descriptor
.iManufacturer
,
302 string
, sizeof(string
));
304 name
+= QString::fromAscii(string
) + " ";
306 if(u
->descriptor
.iProduct
) {
307 res
= usb_get_string_simple(dev
, u
->descriptor
.iProduct
,
308 string
, sizeof(string
));
310 name
+= QString::fromAscii(string
);
314 if(name
.isEmpty()) name
= tr("(no description available)");
317 usbids
.insert(id
, name
);
318 qDebug() << "[System] USB:" << QString("0x%1").arg(id
, 8, 16) << name
;
328 #if defined(Q_OS_MACX)
329 kern_return_t result
= KERN_FAILURE
;
330 CFMutableDictionaryRef usb_matching_dictionary
;
331 io_iterator_t usb_iterator
= IO_OBJECT_NULL
;
332 usb_matching_dictionary
= IOServiceMatching(kIOUSBDeviceClassName
);
333 result
= IOServiceGetMatchingServices(kIOMasterPortDefault
, usb_matching_dictionary
,
336 qDebug() << "[System] USB: IOKit: Could not get matching services.";
340 io_object_t usbCurrentObj
;
341 while((usbCurrentObj
= IOIteratorNext(usb_iterator
))) {
345 CFTypeRef vidref
= NULL
;
347 vidref
= IORegistryEntryCreateCFProperty(usbCurrentObj
, CFSTR("idVendor"),
348 kCFAllocatorDefault
, 0);
349 CFNumberGetValue((CFNumberRef
)vidref
, kCFNumberIntType
, &vid
);
353 CFTypeRef pidref
= NULL
;
355 pidref
= IORegistryEntryCreateCFProperty(usbCurrentObj
, CFSTR("idProduct"),
356 kCFAllocatorDefault
, 0);
357 CFNumberGetValue((CFNumberRef
)pidref
, kCFNumberIntType
, &pid
);
359 id
= vid
<< 16 | pid
;
361 /* get product vendor */
362 char vendor_buf
[256];
363 CFIndex vendor_buflen
= 256;
364 CFTypeRef vendor_name_ref
= NULL
;
366 vendor_name_ref
= IORegistryEntrySearchCFProperty(usbCurrentObj
,
367 kIOServicePlane
, CFSTR("USB Vendor Name"),
368 kCFAllocatorDefault
, 0);
369 if(vendor_name_ref
!= NULL
) {
370 CFStringGetCString((CFStringRef
)vendor_name_ref
, vendor_buf
, vendor_buflen
,
371 kCFStringEncodingUTF8
);
372 name
+= QString::fromUtf8(vendor_buf
) + " ";
373 CFRelease(vendor_name_ref
);
376 name
+= QObject::tr("(unknown vendor name) ");
379 /* get product name */
380 char product_buf
[256];
381 CFIndex product_buflen
= 256;
382 CFTypeRef product_name_ref
= NULL
;
384 product_name_ref
= IORegistryEntrySearchCFProperty(usbCurrentObj
,
385 kIOServicePlane
, CFSTR("USB Product Name"),
386 kCFAllocatorDefault
, 0);
387 if(product_name_ref
!= NULL
) {
388 CFStringGetCString((CFStringRef
)product_name_ref
, product_buf
, product_buflen
,
389 kCFStringEncodingUTF8
);
390 name
+= QString::fromUtf8(product_buf
);
391 CFRelease(product_name_ref
);
394 name
+= QObject::tr("(unknown product name)");
398 usbids
.insert(id
, name
);
399 qDebug() << "[System] USB:" << QString("0x%1").arg(id
, 8, 16) << name
;
403 IOObjectRelease(usb_iterator
);
406 #if defined(Q_OS_WIN32)
408 SP_DEVINFO_DATA infoData
;
411 // Iterate over all devices
412 // by doing it this way it's unneccessary to use GUIDs which might be not
413 // present in current MinGW. It also seemed to be more reliably than using
415 // See KB259695 for an example.
416 deviceInfo
= SetupDiGetClassDevs(NULL
, NULL
, NULL
, DIGCF_ALLCLASSES
| DIGCF_PRESENT
);
418 infoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
420 for(i
= 0; SetupDiEnumDeviceInfo(deviceInfo
, i
, &infoData
); i
++) {
422 LPTSTR buffer
= NULL
;
423 DWORD buffersize
= 0;
426 // get device desriptor first
427 // for some reason not doing so results in bad things (tm)
428 while(!SetupDiGetDeviceRegistryProperty(deviceInfo
, &infoData
,
429 SPDRP_DEVICEDESC
, &data
, (PBYTE
)buffer
, buffersize
, &buffersize
)) {
430 if(GetLastError() == ERROR_INSUFFICIENT_BUFFER
) {
431 if(buffer
) free(buffer
);
432 // double buffer size to avoid problems as per KB888609
433 buffer
= (LPTSTR
)malloc(buffersize
* 2);
439 description
= QString::fromWCharArray(buffer
);
441 // now get the hardware id, which contains PID and VID.
442 while(!SetupDiGetDeviceRegistryProperty(deviceInfo
, &infoData
,
443 SPDRP_HARDWAREID
, &data
, (PBYTE
)buffer
, buffersize
, &buffersize
)) {
444 if(GetLastError() == ERROR_INSUFFICIENT_BUFFER
) {
445 if(buffer
) free(buffer
);
446 // double buffer size to avoid problems as per KB888609
447 buffer
= (LPTSTR
)malloc(buffersize
* 2);
454 unsigned int vid
, pid
;
455 // convert buffer text to upper case to avoid depending on the case of
456 // the keys (W7 uses different casing than XP at least).
457 int len
= _tcslen(buffer
);
458 while(len
--) buffer
[len
] = _totupper(buffer
[len
]);
459 if(_stscanf(buffer
, _TEXT("USB\\VID_%x&PID_%x"), &vid
, &pid
) == 2) {
461 id
= vid
<< 16 | pid
;
462 usbids
.insert(id
, description
);
463 qDebug("[System] USB VID: %04x, PID: %04x", vid
, pid
);
465 if(buffer
) free(buffer
);
467 SetupDiDestroyDeviceInfoList(deviceInfo
);
474 /** @brief detects current system proxy
475 * @return QUrl with proxy or empty
477 QUrl
System::systemProxy(void)
479 #if defined(Q_OS_LINUX)
480 return QUrl(getenv("http_proxy"));
481 #elif defined(Q_OS_WIN32)
483 wchar_t proxyval
[80];
487 DWORD enalen
= sizeof(DWORD
);
489 ret
= RegOpenKeyEx(HKEY_CURRENT_USER
,
490 _TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"),
491 0, KEY_QUERY_VALUE
, &hk
);
492 if(ret
!= ERROR_SUCCESS
) return QUrl("");
494 ret
= RegQueryValueEx(hk
, _TEXT("ProxyServer"), NULL
, NULL
, (LPBYTE
)proxyval
, &buflen
);
495 if(ret
!= ERROR_SUCCESS
) return QUrl("");
497 ret
= RegQueryValueEx(hk
, _TEXT("ProxyEnable"), NULL
, NULL
, (LPBYTE
)&enable
, &enalen
);
498 if(ret
!= ERROR_SUCCESS
) return QUrl("");
502 //qDebug() << QString::fromWCharArray(proxyval) << QString("%1").arg(enable);
504 return QUrl("http://" + QString::fromWCharArray(proxyval
));
507 #elif defined(Q_OS_MACX)
509 CFDictionaryRef dictref
;
510 CFStringRef stringref
;
511 CFNumberRef numberref
;
514 unsigned int bufsize
= 0;
518 dictref
= SCDynamicStoreCopyProxies(NULL
);
521 numberref
= (CFNumberRef
)CFDictionaryGetValue(dictref
, kSCPropNetProxiesHTTPEnable
);
522 if(numberref
!= NULL
)
523 CFNumberGetValue(numberref
, kCFNumberIntType
, &enable
);
526 stringref
= (CFStringRef
)CFDictionaryGetValue(dictref
, kSCPropNetProxiesHTTPProxy
);
527 if(stringref
!= NULL
) {
528 // get number of characters. CFStringGetLength uses UTF-16 code pairs
529 bufsize
= CFStringGetLength(stringref
) * 2 + 1;
530 buf
= (char*)malloc(sizeof(char) * bufsize
);
532 qDebug() << "[System] can't allocate memory for proxy string!";
536 CFStringGetCString(stringref
, buf
, bufsize
, kCFStringEncodingUTF16
);
537 numberref
= (CFNumberRef
)CFDictionaryGetValue(dictref
, kSCPropNetProxiesHTTPPort
);
538 if(numberref
!= NULL
)
539 CFNumberGetValue(numberref
, kCFNumberIntType
, &port
);
540 proxy
.setScheme("http");
541 proxy
.setHost(QString::fromUtf16((unsigned short*)buf
));