Bump version numbers for 3.13
[maemo-rb.git] / rbutil / rbutilqt / base / system.cpp
blobffd667995aada9bba2b4965b895734721e810671
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
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 ****************************************************************************/
20 #include "system.h"
22 #include <QtCore>
23 #include <QDebug>
25 #include <cstdlib>
26 #include <stdio.h>
28 // Windows Includes
29 #if defined(Q_OS_WIN32)
30 #if defined(UNICODE)
31 #define _UNICODE
32 #endif
33 #include <windows.h>
34 #include <tchar.h>
35 #include <lm.h>
36 #include <windows.h>
37 #include <setupapi.h>
38 #endif
40 // Linux and Mac includes
41 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
42 #if defined(LIBUSB1)
43 #include <libusb-1.0/libusb.h>
44 #else
45 #include <usb.h>
46 #endif
47 #include <sys/utsname.h>
48 #include <unistd.h>
49 #include <pwd.h>
50 #endif
52 // Linux includes
53 #if defined(Q_OS_LINUX)
54 #include <mntent.h>
55 #endif
57 // Mac includes
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>
68 #endif
70 #include "utils.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;
82 BOOL status;
83 enum userlevel result = ERR;
85 status = GetUserNameW(userbuf, &usersize);
86 if(!status)
87 return ERR;
89 if(NetUserGetInfo(NULL, userbuf, (DWORD)1, (LPBYTE*)&buf) == NERR_Success) {
90 switch(buf->usri1_priv) {
91 case USER_PRIV_GUEST:
92 result = GUEST;
93 break;
94 case USER_PRIV_USER:
95 result = USER;
96 break;
97 case USER_PRIV_ADMIN:
98 result = ADMIN;
99 break;
100 default:
101 result = ERR;
102 break;
105 if(buf != NULL)
106 NetApiBufferFree(buf);
108 return result;
111 /** @brief detects user permissions (only Windows at moment).
112 * @return a user readable string with the permission.
114 QString System::userPermissionsString(void)
116 QString result;
117 int perm = userPermissions();
118 switch(perm) {
119 case GUEST:
120 result = tr("Guest");
121 break;
122 case ADMIN:
123 result = tr("Admin");
124 break;
125 case USER:
126 result = tr("User");
127 break;
128 default:
129 result = tr("Error");
130 break;
132 return result;
134 #endif
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)
147 return QString();
149 return QString::fromWCharArray(userbuf);
150 #endif
151 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
152 struct passwd *user;
153 user = getpwuid(geteuid());
154 return QString(user->pw_name);
155 #endif
159 /** @brief detects the OS Version
160 * @return String with OS Version.
162 QString System::osVersionString(void)
164 QString result;
165 #if defined(Q_OS_WIN32)
166 SYSTEM_INFO sysinfo;
167 OSVERSIONINFO osvi;
168 ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
169 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
170 GetVersionEx(&osvi);
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));
177 else
178 result += QString("build %1").arg(osvi.dwBuildNumber);
179 result += QString("<br/>CPU: %1, %2 processor(s)").arg(sysinfo.dwProcessorType)
180 .arg(sysinfo.dwNumberOfProcessors);
181 #endif
182 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
183 struct utsname u;
184 int ret;
185 ret = uname(&u);
187 #if defined(Q_OS_MACX)
188 ItemCount cores = MPProcessors();
189 #else
190 long cores = sysconf(_SC_NPROCESSORS_ONLN);
191 #endif
192 if(ret != -1) {
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);
197 else {
198 result = QString("(Error when retrieving system information)");
200 #if defined(Q_OS_MACX)
201 SInt32 major;
202 SInt32 minor;
203 SInt32 bugfix;
204 OSErr error;
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
211 SInt32 arch;
212 error = Gestalt(gestaltSysArchitecture, &arch);
213 switch(arch) {
214 case 1:
215 result.append("(86k)");
216 break;
217 case 2:
218 result.append("(ppc)");
219 break;
220 case 10:
221 result.append("(x86)");
222 break;
223 default:
224 result.append("(unknown)");
225 break;
227 #endif
228 #endif
229 result += QString("<br/>Qt version %1").arg(qVersion());
230 return result;
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;
244 // usb pid detection
245 qDebug() << "[System] Searching for USB devices";
246 #if defined(Q_OS_LINUX)
247 #if defined(LIBUSB1)
248 libusb_device **devs;
249 if(libusb_init(NULL) != 0) {
250 qDebug() << "[System] Initializing libusb-1 failed.";
251 return usbids;
254 if(libusb_get_device_list(NULL, &devs) < 1) {
255 qDebug() << "[System] Error getting device list.";
256 return usbids;
258 libusb_device *dev;
259 int i = 0;
260 while((dev = devs[i++]) != NULL) {
261 QString name;
262 unsigned char buf[256];
263 uint32_t id;
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);
274 libusb_close(dh);
276 if(name.isEmpty())
277 name = tr("(no description available)");
278 if(id) {
279 usbids.insert(id, name);
280 qDebug("[System] USB: 0x%08x, %s", id, name.toLocal8Bit().data());
285 libusb_free_device_list(devs, 1);
286 libusb_exit(NULL);
287 #else
288 usb_init();
289 usb_find_busses();
290 usb_find_devices();
291 struct usb_bus *b;
292 b = usb_busses;
294 while(b) {
295 if(b->devices) {
296 struct usb_device *u;
297 u = b->devices;
298 while(u) {
299 uint32_t id;
300 id = u->descriptor.idVendor << 16 | u->descriptor.idProduct;
301 // get identification strings
302 usb_dev_handle *dev;
303 QString name;
304 char string[256];
305 int res;
306 dev = usb_open(u);
307 if(dev) {
308 if(u->descriptor.iManufacturer) {
309 res = usb_get_string_simple(dev, u->descriptor.iManufacturer,
310 string, sizeof(string));
311 if(res > 0)
312 name += QString::fromLatin1(string) + " ";
314 if(u->descriptor.iProduct) {
315 res = usb_get_string_simple(dev, u->descriptor.iProduct,
316 string, sizeof(string));
317 if(res > 0)
318 name += QString::fromLatin1(string);
320 usb_close(dev);
322 if(name.isEmpty()) name = tr("(no description available)");
324 if(id) {
325 usbids.insert(id, name);
326 qDebug() << "[System] USB:" << QString("0x%1").arg(id, 8, 16) << name;
328 u = u->next;
331 b = b->next;
333 #endif
334 #endif
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,
342 &usb_iterator);
343 if(result) {
344 qDebug() << "[System] USB: IOKit: Could not get matching services.";
345 return usbids;
348 io_object_t usbCurrentObj;
349 while((usbCurrentObj = IOIteratorNext(usb_iterator))) {
350 uint32_t id;
351 QString name;
352 /* get vendor ID */
353 CFTypeRef vidref = NULL;
354 int vid = 0;
355 vidref = IORegistryEntryCreateCFProperty(usbCurrentObj, CFSTR("idVendor"),
356 kCFAllocatorDefault, 0);
357 CFNumberGetValue((CFNumberRef)vidref, kCFNumberIntType, &vid);
358 CFRelease(vidref);
360 /* get product ID */
361 CFTypeRef pidref = NULL;
362 int pid = 0;
363 pidref = IORegistryEntryCreateCFProperty(usbCurrentObj, CFSTR("idProduct"),
364 kCFAllocatorDefault, 0);
365 CFNumberGetValue((CFNumberRef)pidref, kCFNumberIntType, &pid);
366 CFRelease(pidref);
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);
383 else {
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);
401 else {
402 name += QObject::tr("(unknown product name)");
405 if(id) {
406 usbids.insert(id, name);
407 qDebug() << "[System] USB:" << QString("0x%1").arg(id, 8, 16) << name;
411 IOObjectRelease(usb_iterator);
412 #endif
414 #if defined(Q_OS_WIN32)
415 HDEVINFO deviceInfo;
416 SP_DEVINFO_DATA infoData;
417 DWORD i;
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
422 // a GUID.
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++) {
429 DWORD data;
430 LPTSTR buffer = NULL;
431 DWORD buffersize = 0;
432 QString description;
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);
443 else {
444 break;
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);
457 else {
458 break;
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) {
468 uint32_t id;
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);
477 #endif
478 return usbids;
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)
490 HKEY hk;
491 wchar_t proxyval[80];
492 DWORD buflen = 80;
493 long ret;
494 DWORD enable;
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("");
508 RegCloseKey(hk);
510 //qDebug() << QString::fromWCharArray(proxyval) << QString("%1").arg(enable);
511 if(enable != 0)
512 return QUrl("http://" + QString::fromWCharArray(proxyval));
513 else
514 return QUrl("");
515 #elif defined(Q_OS_MACX)
517 CFDictionaryRef dictref;
518 CFStringRef stringref;
519 CFNumberRef numberref;
520 int enable = 0;
521 int port = 0;
522 unsigned int bufsize = 0;
523 char *buf;
524 QUrl proxy;
526 dictref = SCDynamicStoreCopyProxies(NULL);
527 if(dictref == NULL)
528 return proxy;
529 numberref = (CFNumberRef)CFDictionaryGetValue(dictref, kSCPropNetProxiesHTTPEnable);
530 if(numberref != NULL)
531 CFNumberGetValue(numberref, kCFNumberIntType, &enable);
532 if(enable == 1) {
533 // get proxy string
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);
539 if(buf == NULL) {
540 qDebug() << "[System] can't allocate memory for proxy string!";
541 CFRelease(dictref);
542 return QUrl("");
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));
550 proxy.setPort(port);
552 free(buf);
555 CFRelease(dictref);
557 return proxy;
558 #else
559 return QUrl("");
560 #endif