1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * Copyright (C) 2007 by Dominik Wenger
11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement.
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
17 ****************************************************************************/
29 #if defined(Q_OS_WIN32)
40 // Linux and Mac includes
41 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
43 #include <libusb-1.0/libusb.h>
47 #include <sys/utsname.h>
53 #if defined(Q_OS_LINUX)
58 #if defined(Q_OS_MACX)
59 #include <sys/param.h>
60 #include <sys/ucred.h>
61 #include <sys/mount.h>
63 #include <CoreFoundation/CoreFoundation.h>
64 #include <SystemConfiguration/SystemConfiguration.h>
65 #include <CoreServices/CoreServices.h>
66 #include <IOKit/IOKitLib.h>
67 #include <IOKit/usb/IOUSBLib.h>
71 #include "rbsettings.h"
73 /** @brief detect permission of user (only Windows at moment).
74 * @return enum userlevel.
76 #if defined(Q_OS_WIN32)
77 enum System::userlevel
System::userPermissions(void)
79 LPUSER_INFO_1 buf
= NULL
;
80 wchar_t userbuf
[UNLEN
];
81 DWORD usersize
= UNLEN
;
83 enum userlevel result
= ERR
;
85 status
= GetUserNameW(userbuf
, &usersize
);
89 if(NetUserGetInfo(NULL
, userbuf
, (DWORD
)1, (LPBYTE
*)&buf
) == NERR_Success
) {
90 switch(buf
->usri1_priv
) {
106 NetApiBufferFree(buf
);
111 /** @brief detects user permissions (only Windows at moment).
112 * @return a user readable string with the permission.
114 QString
System::userPermissionsString(void)
117 int perm
= userPermissions();
120 result
= tr("Guest");
123 result
= tr("Admin");
129 result
= tr("Error");
137 /** @brief detects current Username.
138 * @return string with Username.
140 QString
System::userName(void)
142 #if defined(Q_OS_WIN32)
143 wchar_t userbuf
[UNLEN
];
144 DWORD usersize
= UNLEN
;
146 if(GetUserNameW(userbuf
, &usersize
) == 0)
149 return QString::fromWCharArray(userbuf
);
151 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
153 user
= getpwuid(geteuid());
154 return QString(user
->pw_name
);
159 /** @brief detects the OS Version
160 * @return String with OS Version.
162 QString
System::osVersionString(void)
165 #if defined(Q_OS_WIN32)
168 ZeroMemory(&osvi
, sizeof(OSVERSIONINFO
));
169 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
171 GetSystemInfo(&sysinfo
);
173 result
= QString("Windows version %1.%2, ").arg(osvi
.dwMajorVersion
).arg(osvi
.dwMinorVersion
);
174 if(osvi
.szCSDVersion
)
175 result
+= QString("build %1 (%2)").arg(osvi
.dwBuildNumber
)
176 .arg(QString::fromWCharArray(osvi
.szCSDVersion
));
178 result
+= QString("build %1").arg(osvi
.dwBuildNumber
);
179 result
+= QString("<br/>CPU: %1, %2 processor(s)").arg(sysinfo
.dwProcessorType
)
180 .arg(sysinfo
.dwNumberOfProcessors
);
182 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
187 #if defined(Q_OS_MACX)
188 ItemCount cores
= MPProcessors();
190 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
);
198 result
= QString("(Error when retrieving system information)");
200 #if defined(Q_OS_MACX)
205 error
= Gestalt(gestaltSystemVersionMajor
, &major
);
206 error
= Gestalt(gestaltSystemVersionMinor
, &minor
);
207 error
= Gestalt(gestaltSystemVersionBugFix
, &bugfix
);
209 result
+= QString("<br/>OS X %1.%2.%3 ").arg(major
).arg(minor
).arg(bugfix
);
210 // 1: 86k, 2: ppc, 10: i386
212 error
= Gestalt(gestaltSysArchitecture
, &arch
);
215 result
.append("(86k)");
218 result
.append("(ppc)");
221 result
.append("(x86)");
224 result
.append("(unknown)");
229 result
+= QString("<br/>Qt version %1").arg(qVersion());
233 QList
<uint32_t> System::listUsbIds(void)
235 return listUsbDevices().keys();
238 /** @brief detect devices based on usb pid / vid.
239 * @return list with usb VID / PID values.
241 QMap
<uint32_t, QString
> System::listUsbDevices(void)
243 QMap
<uint32_t, QString
> usbids
;
245 qDebug() << "[System] Searching for USB devices";
246 #if defined(Q_OS_LINUX)
248 libusb_device
**devs
;
249 if(libusb_init(NULL
) != 0) {
250 qDebug() << "[System] Initializing libusb-1 failed.";
254 if(libusb_get_device_list(NULL
, &devs
) < 1) {
255 qDebug() << "[System] Error getting device list.";
260 while((dev
= devs
[i
++]) != NULL
) {
262 unsigned char buf
[256];
264 struct libusb_device_descriptor descriptor
;
265 if(libusb_get_device_descriptor(dev
, &descriptor
) == 0) {
266 id
= descriptor
.idVendor
<< 16 | descriptor
.idProduct
;
268 libusb_device_handle
*dh
;
269 if(libusb_open(dev
, &dh
) == 0) {
270 libusb_get_string_descriptor_ascii(dh
, descriptor
.iManufacturer
, buf
, 256);
271 name
+= QString::fromLatin1((char*)buf
) + " ";
272 libusb_get_string_descriptor_ascii(dh
, descriptor
.iProduct
, buf
, 256);
273 name
+= QString::fromLatin1((char*)buf
);
277 name
= tr("(no description available)");
279 usbids
.insert(id
, name
);
280 qDebug("[System] USB: 0x%08x, %s", id
, name
.toLocal8Bit().data());
285 libusb_free_device_list(devs
, 1);
296 struct usb_device
*u
;
300 id
= u
->descriptor
.idVendor
<< 16 | u
->descriptor
.idProduct
;
301 // get identification strings
308 if(u
->descriptor
.iManufacturer
) {
309 res
= usb_get_string_simple(dev
, u
->descriptor
.iManufacturer
,
310 string
, sizeof(string
));
312 name
+= QString::fromLatin1(string
) + " ";
314 if(u
->descriptor
.iProduct
) {
315 res
= usb_get_string_simple(dev
, u
->descriptor
.iProduct
,
316 string
, sizeof(string
));
318 name
+= QString::fromLatin1(string
);
322 if(name
.isEmpty()) name
= tr("(no description available)");
325 usbids
.insert(id
, name
);
326 qDebug() << "[System] USB:" << QString("0x%1").arg(id
, 8, 16) << name
;
336 #if defined(Q_OS_MACX)
337 kern_return_t result
= KERN_FAILURE
;
338 CFMutableDictionaryRef usb_matching_dictionary
;
339 io_iterator_t usb_iterator
= IO_OBJECT_NULL
;
340 usb_matching_dictionary
= IOServiceMatching(kIOUSBDeviceClassName
);
341 result
= IOServiceGetMatchingServices(kIOMasterPortDefault
, usb_matching_dictionary
,
344 qDebug() << "[System] USB: IOKit: Could not get matching services.";
348 io_object_t usbCurrentObj
;
349 while((usbCurrentObj
= IOIteratorNext(usb_iterator
))) {
353 CFTypeRef vidref
= NULL
;
355 vidref
= IORegistryEntryCreateCFProperty(usbCurrentObj
, CFSTR("idVendor"),
356 kCFAllocatorDefault
, 0);
357 CFNumberGetValue((CFNumberRef
)vidref
, kCFNumberIntType
, &vid
);
361 CFTypeRef pidref
= NULL
;
363 pidref
= IORegistryEntryCreateCFProperty(usbCurrentObj
, CFSTR("idProduct"),
364 kCFAllocatorDefault
, 0);
365 CFNumberGetValue((CFNumberRef
)pidref
, kCFNumberIntType
, &pid
);
367 id
= vid
<< 16 | pid
;
369 /* get product vendor */
370 char vendor_buf
[256];
371 CFIndex vendor_buflen
= 256;
372 CFTypeRef vendor_name_ref
= NULL
;
374 vendor_name_ref
= IORegistryEntrySearchCFProperty(usbCurrentObj
,
375 kIOServicePlane
, CFSTR("USB Vendor Name"),
376 kCFAllocatorDefault
, 0);
377 if(vendor_name_ref
!= NULL
) {
378 CFStringGetCString((CFStringRef
)vendor_name_ref
, vendor_buf
, vendor_buflen
,
379 kCFStringEncodingUTF8
);
380 name
+= QString::fromUtf8(vendor_buf
) + " ";
381 CFRelease(vendor_name_ref
);
384 name
+= QObject::tr("(unknown vendor name) ");
387 /* get product name */
388 char product_buf
[256];
389 CFIndex product_buflen
= 256;
390 CFTypeRef product_name_ref
= NULL
;
392 product_name_ref
= IORegistryEntrySearchCFProperty(usbCurrentObj
,
393 kIOServicePlane
, CFSTR("USB Product Name"),
394 kCFAllocatorDefault
, 0);
395 if(product_name_ref
!= NULL
) {
396 CFStringGetCString((CFStringRef
)product_name_ref
, product_buf
, product_buflen
,
397 kCFStringEncodingUTF8
);
398 name
+= QString::fromUtf8(product_buf
);
399 CFRelease(product_name_ref
);
402 name
+= QObject::tr("(unknown product name)");
406 usbids
.insert(id
, name
);
407 qDebug() << "[System] USB:" << QString("0x%1").arg(id
, 8, 16) << name
;
411 IOObjectRelease(usb_iterator
);
414 #if defined(Q_OS_WIN32)
416 SP_DEVINFO_DATA infoData
;
419 // Iterate over all devices
420 // by doing it this way it's unneccessary to use GUIDs which might be not
421 // present in current MinGW. It also seemed to be more reliably than using
423 // See KB259695 for an example.
424 deviceInfo
= SetupDiGetClassDevs(NULL
, NULL
, NULL
, DIGCF_ALLCLASSES
| DIGCF_PRESENT
);
426 infoData
.cbSize
= sizeof(SP_DEVINFO_DATA
);
428 for(i
= 0; SetupDiEnumDeviceInfo(deviceInfo
, i
, &infoData
); i
++) {
430 LPTSTR buffer
= NULL
;
431 DWORD buffersize
= 0;
434 // get device desriptor first
435 // for some reason not doing so results in bad things (tm)
436 while(!SetupDiGetDeviceRegistryProperty(deviceInfo
, &infoData
,
437 SPDRP_DEVICEDESC
, &data
, (PBYTE
)buffer
, buffersize
, &buffersize
)) {
438 if(GetLastError() == ERROR_INSUFFICIENT_BUFFER
) {
439 if(buffer
) free(buffer
);
440 // double buffer size to avoid problems as per KB888609
441 buffer
= (LPTSTR
)malloc(buffersize
* 2);
447 description
= QString::fromWCharArray(buffer
);
449 // now get the hardware id, which contains PID and VID.
450 while(!SetupDiGetDeviceRegistryProperty(deviceInfo
, &infoData
,
451 SPDRP_HARDWAREID
, &data
, (PBYTE
)buffer
, buffersize
, &buffersize
)) {
452 if(GetLastError() == ERROR_INSUFFICIENT_BUFFER
) {
453 if(buffer
) free(buffer
);
454 // double buffer size to avoid problems as per KB888609
455 buffer
= (LPTSTR
)malloc(buffersize
* 2);
462 unsigned int vid
, pid
;
463 // convert buffer text to upper case to avoid depending on the case of
464 // the keys (W7 uses different casing than XP at least).
465 int len
= _tcslen(buffer
);
466 while(len
--) buffer
[len
] = _totupper(buffer
[len
]);
467 if(_stscanf(buffer
, _TEXT("USB\\VID_%x&PID_%x"), &vid
, &pid
) == 2) {
469 id
= vid
<< 16 | pid
;
470 usbids
.insert(id
, description
);
471 qDebug("[System] USB VID: %04x, PID: %04x", vid
, pid
);
473 if(buffer
) free(buffer
);
475 SetupDiDestroyDeviceInfoList(deviceInfo
);
482 /** @brief detects current system proxy
483 * @return QUrl with proxy or empty
485 QUrl
System::systemProxy(void)
487 #if defined(Q_OS_LINUX)
488 return QUrl(getenv("http_proxy"));
489 #elif defined(Q_OS_WIN32)
491 wchar_t proxyval
[80];
495 DWORD enalen
= sizeof(DWORD
);
497 ret
= RegOpenKeyEx(HKEY_CURRENT_USER
,
498 _TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"),
499 0, KEY_QUERY_VALUE
, &hk
);
500 if(ret
!= ERROR_SUCCESS
) return QUrl("");
502 ret
= RegQueryValueEx(hk
, _TEXT("ProxyServer"), NULL
, NULL
, (LPBYTE
)proxyval
, &buflen
);
503 if(ret
!= ERROR_SUCCESS
) return QUrl("");
505 ret
= RegQueryValueEx(hk
, _TEXT("ProxyEnable"), NULL
, NULL
, (LPBYTE
)&enable
, &enalen
);
506 if(ret
!= ERROR_SUCCESS
) return QUrl("");
510 //qDebug() << QString::fromWCharArray(proxyval) << QString("%1").arg(enable);
512 return QUrl("http://" + QString::fromWCharArray(proxyval
));
515 #elif defined(Q_OS_MACX)
517 CFDictionaryRef dictref
;
518 CFStringRef stringref
;
519 CFNumberRef numberref
;
522 unsigned int bufsize
= 0;
526 dictref
= SCDynamicStoreCopyProxies(NULL
);
529 numberref
= (CFNumberRef
)CFDictionaryGetValue(dictref
, kSCPropNetProxiesHTTPEnable
);
530 if(numberref
!= NULL
)
531 CFNumberGetValue(numberref
, kCFNumberIntType
, &enable
);
534 stringref
= (CFStringRef
)CFDictionaryGetValue(dictref
, kSCPropNetProxiesHTTPProxy
);
535 if(stringref
!= NULL
) {
536 // get number of characters. CFStringGetLength uses UTF-16 code pairs
537 bufsize
= CFStringGetLength(stringref
) * 2 + 1;
538 buf
= (char*)malloc(sizeof(char) * bufsize
);
540 qDebug() << "[System] can't allocate memory for proxy string!";
544 CFStringGetCString(stringref
, buf
, bufsize
, kCFStringEncodingUTF16
);
545 numberref
= (CFNumberRef
)CFDictionaryGetValue(dictref
, kSCPropNetProxiesHTTPPort
);
546 if(numberref
!= NULL
)
547 CFNumberGetValue(numberref
, kCFNumberIntType
, &port
);
548 proxy
.setScheme("http");
549 proxy
.setHost(QString::fromUtf16((unsigned short*)buf
));