diff --git a/Modules/opengl/opengl.cpp b/Modules/opengl/opengl.cpp index 795636b..8e5ca14 100644 --- a/Modules/opengl/opengl.cpp +++ b/Modules/opengl/opengl.cpp @@ -1,1036 +1,1036 @@ /* * opengl.cpp * * Copyright (C) 2008 Ivo Anjo * Copyright (C) 2004 Ilya Korniyko * Adapted from Brian Paul's glxinfo from Mesa demos (http://www.mesa3d.org) * Copyright (C) 1999-2002 Brian Paul * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "opengl.h" #include #include #include #include #include #include #include #include #include #include #include #include #include // X11 includes #include #include #include #if KCM_HAVE_EGL #include #endif #ifdef KCM_ENABLE_OPENGLES #include #endif #if KCM_HAVE_GLX // GLU includes #include // OpenGL includes #include #include #include #endif #if defined(Q_OS_LINUX) #include #include #include #endif K_PLUGIN_FACTORY(KCMOpenGLFactory, registerPlugin(); ) // FIXME: Temporary! bool GetInfo_OpenGL(QTreeWidget *treeWidget); KCMOpenGL::KCMOpenGL(QWidget *parent, const QVariantList &) : KCModule(parent) { setupUi(this); layout()->setMargin(0); GetInfo_OpenGL(glinfoTreeWidget); // Watch for expanded and collapsed events, to resize columns connect(glinfoTreeWidget, &QTreeWidget::expanded, this, &KCMOpenGL::treeWidgetChanged); connect(glinfoTreeWidget, &QTreeWidget::collapsed, this, &KCMOpenGL::treeWidgetChanged); KAboutData *about = new KAboutData(i18n("kcmopengl"), i18n("KCM OpenGL Information"), QString(), QString(), KAboutLicense::GPL, i18n("(c) 2008 Ivo Anjo\n(c) 2004 Ilya Korniyko\n(c) 1999-2002 Brian Paul")); about->addAuthor(i18n("Ivo Anjo"), QString(), QStringLiteral("knuckles@gmail.com")); about->addAuthor(i18n("Ilya Korniyko"), QString(), QStringLiteral("k_ilya@ukr.net")); about->addCredit(i18n("Helge Deller"), i18n("Original Maintainer"), QStringLiteral("deller@gmx.de")); about->addCredit(i18n("Brian Paul"), i18n("Author of glxinfo Mesa demos (http://www.mesa3d.org)")); setAboutData(about); } void KCMOpenGL::treeWidgetChanged() { glinfoTreeWidget->resizeColumnToContents(0); glinfoTreeWidget->resizeColumnToContents(1); } QTreeWidgetItem *newItem(QTreeWidgetItem *parent, QTreeWidgetItem *preceding, const QString &textCol1, const QString &textCol2 = QString()) { QTreeWidgetItem *newItem; if ((parent == nullptr) && (preceding == nullptr)) { newItem = new QTreeWidgetItem(); } else if (preceding == nullptr) { newItem = new QTreeWidgetItem(parent); } else { newItem = new QTreeWidgetItem(parent, preceding); } newItem->setText(0, textCol1); if (!textCol2.isNull()) { newItem->setText(1, textCol2); } newItem->setFlags(Qt::ItemIsEnabled); return newItem; } QTreeWidgetItem *newItem(QTreeWidgetItem *parent, QString textCol1, QString textCol2 = QString()) { return newItem(parent, NULL, textCol1, textCol2); } static bool IsDirect; static struct glinfo { #if KCM_HAVE_GLX const char *serverVendor; const char *serverVersion; const char *serverExtensions; const char *clientVendor; const char *clientVersion; const char *clientExtensions; const char *glxExtensions; #endif #if KCM_HAVE_EGL const char *eglVendor; const char *eglVersion; const char *eglExtensions; #endif const char *glVendor; const char *glRenderer; const char *glVersion; const char *glExtensions; #if KCM_HAVE_GLX const char *gluVersion; const char *gluExtensions; #endif char *displayName; } gli; static struct { QString module, pci, vendor, device, subvendor, rev; } dri_info; static int ReadPipe(const QString &FileName, QStringList &list) { QProcess pipe; pipe.start(FileName, QIODevice::ReadOnly); if (!pipe.waitForFinished()) { // something went wrong, f.e. command not found return 0; } QTextStream t(&pipe); while (!t.atEnd()) list.append(t.readLine()); return list.count(); } #if defined(Q_OS_LINUX) static QString get_sysfs_link_name(const QString& path) { const QString target = QFileInfo(path).symLinkTarget(); const int index = target.lastIndexOf(QChar('/')); if (index == -1) return QString(); return target.mid(index + 1); } static bool get_drm_device_sysfs() { struct stat fileInfo; if (::stat("/dev/dri/card0", &fileInfo) != 0) return false; if ((fileInfo.st_mode & S_IFCHR) != S_IFCHR) return false; const uint16_t devMajor = major(fileInfo.st_rdev); const uint16_t devMinor = minor(fileInfo.st_rdev); QString sysPath = QStringLiteral("/sys/dev/char/%1:%2/device").arg(devMajor).arg(devMinor); dri_info.pci = get_sysfs_link_name(sysPath); dri_info.module = get_sysfs_link_name(sysPath + QStringLiteral("/driver")); return (dri_info.pci.size() && dri_info.module.size()); } #define INFO_DRI QStringLiteral("/proc/dri/0/name") static bool get_dri_device_proc() { QFile file; file.setFileName(INFO_DRI); if (!file.exists() || !file.open(QIODevice::ReadOnly)) return false; QTextStream stream(&file); QString line = stream.readLine(); if (line.isEmpty()) return false; dri_info.module = line.mid(0, line.indexOf(0x20)); // possible formats, for regression testing // line = " PCI:01:00:0"; // line = " pci:0000:01:00.0" QRegExp rx = QRegExp("\\b[Pp][Cc][Ii][:]([0-9a-fA-F]+[:])?([0-9a-fA-F]+[:][0-9a-fA-F]+[:.][0-9a-fA-F]+)\\b"); if (rx.indexIn(line)>0) { dri_info.pci = rx.cap(2); int end = dri_info.pci.lastIndexOf(':'); int end2 = dri_info.pci.lastIndexOf('.'); if (end2>end) end=end2; dri_info.pci[end]='.'; return true; } return false; } static bool get_dri_device() { if (!get_drm_device_sysfs() && !get_dri_device_proc()) return false; QString cmd = QStringLiteral("lspci -m -v -s ") + dri_info.pci; QStringList pci_info; int num; if (((num = ReadPipe(cmd, pci_info)) || (num = ReadPipe("/sbin/"+cmd, pci_info)) || (num = ReadPipe("/usr/sbin/"+cmd, pci_info)) || (num = ReadPipe("/usr/local/sbin/"+cmd, pci_info))) && num>=7) { QString line; for (int i=2; i<=6; i++) { line = pci_info[i]; line.remove(QRegExp("[^:]*:[ ]*")); switch (i){ case 2: dri_info.vendor = line; break; case 3: dri_info.device = line; break; case 4: dri_info.subvendor = line; break; case 6: dri_info.rev = line; break; } } return true; } return false; } #elif defined(Q_OS_FREEBSD) static bool get_dri_device() { QStringList pci_info; if (ReadPipe("sysctl -n hw.dri.0.name",pci_info)) { dri_info.module = pci_info[0].mid(0, pci_info[0].indexOf(0x20)); } return false; } #else static bool get_dri_device() { return false; } #endif #if KCM_HAVE_GLX static void mesa_hack(Display *dpy, int scrnum) { static const int attribs[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DEPTH_SIZE, 1, GLX_STENCIL_SIZE, 1, GLX_ACCUM_RED_SIZE, 1, GLX_ACCUM_GREEN_SIZE, 1, GLX_ACCUM_BLUE_SIZE, 1, GLX_ACCUM_ALPHA_SIZE, 1, GLX_DOUBLEBUFFER, None }; XVisualInfo *visinfo; visinfo = glXChooseVisual(dpy, scrnum, const_cast(attribs)); if (visinfo) XFree(visinfo); } #endif static void print_extension_list(const char *ext, QTreeWidgetItem *l1) { int i, j; if (!ext || !ext[0]) return; QString qext = QString::fromLatin1(ext); QTreeWidgetItem *l2 = nullptr; i = j = 0; while (1) { if (ext[j] == ' ' || ext[j] == 0) { /* found end of an extension name */ const int len = j - i; /* print the extension name between ext[i] and ext[j] */ if (!l2) l2 = newItem(l1, qext.mid(i, len)); else l2 = newItem(l1, l2, qext.mid(i, len)); i=j; if (ext[j] == 0) { break; } else { i++; j++; if (ext[j] == 0) break; } } j++; } } #if KCM_HAVE_GLX #if defined(GLX_ARB_get_proc_address) && defined(__GLXextFuncPtr) extern "C" { extern __GLXextFuncPtr glXGetProcAddressARB (const GLubyte *); } #endif static void print_limits(QTreeWidgetItem *l1, const char * glExtensions, bool getProcAddress) { /* TODO GL_SAMPLE_BUFFERS GL_SAMPLES GL_COMPRESSED_TEXTURE_FORMATS */ if (!glExtensions) return; struct token_name { GLuint type; // count and flags, !!! count must be <=2 for now GLenum token; const QString name; }; struct token_group { int count; int type; const token_name *group; const QString descr; const char *ext; }; QTreeWidgetItem *l2 = nullptr, *l3 = nullptr; #if defined(PFNGLGETPROGRAMIVARBPROC) PFNGLGETPROGRAMIVARBPROC kcm_glGetProgramivARB = nullptr; #endif #define KCMGL_FLOAT 128 #define KCMGL_PROG 256 #define KCMGL_COUNT_MASK(x) (x & 127) #define KCMGL_SIZE(x) (sizeof(x)/sizeof(x[0])) const struct token_name various_limits[] = { { 1, GL_MAX_LIGHTS, i18n("Max. number of light sources") }, { 1, GL_MAX_CLIP_PLANES, i18n("Max. number of clipping planes") }, { 1, GL_MAX_PIXEL_MAP_TABLE, i18n("Max. pixel map table size") }, { 1, GL_MAX_LIST_NESTING, i18n("Max. display list nesting level") }, { 1, GL_MAX_EVAL_ORDER, i18n("Max. evaluator order") }, { 1, GL_MAX_ELEMENTS_VERTICES, i18n("Max. recommended vertex count") }, { 1, GL_MAX_ELEMENTS_INDICES, i18n("Max. recommended index count") }, #ifdef GL_QUERY_COUNTER_BITS { 1, GL_QUERY_COUNTER_BITS, i18n("Occlusion query counter bits")}, #endif #ifdef GL_MAX_VERTEX_UNITS_ARB { 1, GL_MAX_VERTEX_UNITS_ARB, i18n("Max. vertex blend matrices") }, #endif #ifdef GL_MAX_PALETTE_MATRICES_ARB { 1, GL_MAX_PALETTE_MATRICES_ARB, i18n("Max. vertex blend matrix palette size") }, #endif {0,0,QString()} }; const struct token_name texture_limits[] = { { 1, GL_MAX_TEXTURE_SIZE, i18n("Max. texture size") }, { 1, GL_MAX_TEXTURE_UNITS_ARB, i18n("No. of texture units") }, { 1, GL_MAX_3D_TEXTURE_SIZE, i18n("Max. 3D texture size") }, { 1, GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, i18n("Max. cube map texture size") }, #ifdef GL_MAX_RECTANGLE_TEXTURE_SIZE_NV { 1, GL_MAX_RECTANGLE_TEXTURE_SIZE_NV, i18n("Max. rectangular texture size") }, #endif { 1 | KCMGL_FLOAT, GL_MAX_TEXTURE_LOD_BIAS_EXT, i18n("Max. texture LOD bias") }, { 1, GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, i18n("Max. anisotropy filtering level") }, { 1, GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB, i18n("No. of compressed texture formats") }, {0,0,QString()} }; const struct token_name float_limits[] = { { 2 | KCMGL_FLOAT, GL_ALIASED_POINT_SIZE_RANGE, "ALIASED_POINT_SIZE_RANGE" }, { 2 | KCMGL_FLOAT, GL_SMOOTH_POINT_SIZE_RANGE, "SMOOTH_POINT_SIZE_RANGE" }, { 1 | KCMGL_FLOAT, GL_SMOOTH_POINT_SIZE_GRANULARITY,"SMOOTH_POINT_SIZE_GRANULARITY"}, { 2 | KCMGL_FLOAT, GL_ALIASED_LINE_WIDTH_RANGE, "ALIASED_LINE_WIDTH_RANGE" }, { 2 | KCMGL_FLOAT, GL_SMOOTH_LINE_WIDTH_RANGE, "SMOOTH_LINE_WIDTH_RANGE" }, { 1 | KCMGL_FLOAT, GL_SMOOTH_LINE_WIDTH_GRANULARITY,"SMOOTH_LINE_WIDTH_GRANULARITY"}, {0,0,QString()} }; const struct token_name stack_depth[] = { { 1, GL_MAX_MODELVIEW_STACK_DEPTH, "MAX_MODELVIEW_STACK_DEPTH" }, { 1, GL_MAX_PROJECTION_STACK_DEPTH, "MAX_PROJECTION_STACK_DEPTH" }, { 1, GL_MAX_TEXTURE_STACK_DEPTH, "MAX_TEXTURE_STACK_DEPTH" }, { 1, GL_MAX_NAME_STACK_DEPTH, "MAX_NAME_STACK_DEPTH" }, { 1, GL_MAX_ATTRIB_STACK_DEPTH, "MAX_ATTRIB_STACK_DEPTH" }, { 1, GL_MAX_CLIENT_ATTRIB_STACK_DEPTH, "MAX_CLIENT_ATTRIB_STACK_DEPTH" }, { 1, GL_MAX_COLOR_MATRIX_STACK_DEPTH, "MAX_COLOR_MATRIX_STACK_DEPTH" }, #ifdef GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB { 1, GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB,"MAX_MATRIX_PALETTE_STACK_DEPTH"}, #endif {0,0,QString()} }; #ifdef GL_ARB_fragment_program const struct token_name arb_fp[] = { { 1, GL_MAX_TEXTURE_COORDS_ARB, "MAX_TEXTURE_COORDS" }, { 1, GL_MAX_TEXTURE_IMAGE_UNITS_ARB, "MAX_TEXTURE_IMAGE_UNITS" }, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, "MAX_PROGRAM_ENV_PARAMETERS" }, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, "MAX_PROGRAM_LOCAL_PARAMETERS" }, { 1, GL_MAX_PROGRAM_MATRICES_ARB, "MAX_PROGRAM_MATRICES" }, { 1, GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB, "MAX_PROGRAM_MATRIX_STACK_DEPTH" }, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, "MAX_PROGRAM_INSTRUCTIONS" }, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB, "MAX_PROGRAM_ALU_INSTRUCTIONS" }, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB, "MAX_PROGRAM_TEX_INSTRUCTIONS" }, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB, "MAX_PROGRAM_TEX_INDIRECTIONS" }, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_TEMPORARIES_ARB, "MAX_PROGRAM_TEMPORARIES" }, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_PARAMETERS_ARB, "MAX_PROGRAM_PARAMETERS" }, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_ATTRIBS_ARB, "MAX_PROGRAM_ATTRIBS" }, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, "MAX_PROGRAM_NATIVE_INSTRUCTIONS" }, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, "MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS" }, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB, "MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS" }, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB, "MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS" }, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, "MAX_PROGRAM_NATIVE_TEMPORARIES" }, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, "MAX_PROGRAM_NATIVE_PARAMETERS" }, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, "MAX_PROGRAM_NATIVE_ATTRIBS" }, {0,0,QString()} }; #endif #ifdef GL_ARB_vertex_program const struct token_name arb_vp[] = { { 1 | KCMGL_PROG, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB,"MAX_PROGRAM_ENV_PARAMETERS"}, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB,"MAX_PROGRAM_LOCAL_PARAMETERS"}, { 1, GL_MAX_VERTEX_ATTRIBS_ARB, "MAX_VERTEX_ATTRIBS"}, { 1, GL_MAX_PROGRAM_MATRICES_ARB,"MAX_PROGRAM_MATRICES"}, { 1, GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB,"MAX_PROGRAM_MATRIX_STACK_DEPTH"}, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_INSTRUCTIONS_ARB,"MAX_PROGRAM_INSTRUCTIONS"}, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_TEMPORARIES_ARB,"MAX_PROGRAM_TEMPORARIES"}, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_PARAMETERS_ARB,"MAX_PROGRAM_PARAMETERS"}, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_ATTRIBS_ARB,"MAX_PROGRAM_ATTRIBS"}, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB,"MAX_PROGRAM_ADDRESS_REGISTERS"}, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB,"MAX_PROGRAM_NATIVE_INSTRUCTIONS"}, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB,"MAX_PROGRAM_NATIVE_TEMPORARIES"}, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB,"MAX_PROGRAM_NATIVE_PARAMETERS"}, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB,"MAX_PROGRAM_NATIVE_ATTRIBS"}, { 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB ,"MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS"}, {0,0,QString()} }; #endif #ifdef GL_ARB_vertex_shader const struct token_name arb_vs[] = { { 1, GL_MAX_VERTEX_ATTRIBS_ARB,"MAX_VERTEX_ATTRIBS"}, { 1, GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB,"MAX_VERTEX_UNIFORM_COMPONENTS"}, { 1, GL_MAX_VARYING_FLOATS_ARB,"MAX_VARYING_FLOATS"}, { 1, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB,"MAX_COMBINED_TEXTURE_IMAGE_UNITS"}, { 1, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB,"MAX_VERTEX_TEXTURE_IMAGE_UNITS"}, { 1, GL_MAX_TEXTURE_IMAGE_UNITS_ARB,"MAX_TEXTURE_IMAGE_UNITS"}, { 1, GL_MAX_TEXTURE_COORDS_ARB,"MAX_TEXTURE_COORDS"}, {0,0,QString()} }; #endif #ifdef GL_ARB_fragment_shader const struct token_name arb_fs[] = { { 1, GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB,"MAX_FRAGMENT_UNIFORM_COMPONENTS"}, { 1, GL_MAX_TEXTURE_IMAGE_UNITS_ARB,"MAX_TEXTURE_IMAGE_UNITS"}, { 1, GL_MAX_TEXTURE_COORDS_ARB,"MAX_TEXTURE_COORDS"}, {0,0,QString()} }; #endif const struct token_name frame_buffer_props[] = { { 2, GL_MAX_VIEWPORT_DIMS, i18n("Max. viewport dimensions") }, { 1, GL_SUBPIXEL_BITS, i18n("Subpixel bits") }, { 1, GL_AUX_BUFFERS, i18n("Aux. buffers")}, {0,0,QString()} }; const struct token_group groups[] = { {KCMGL_SIZE(frame_buffer_props), 0, frame_buffer_props, i18n("Frame buffer properties"), NULL}, {KCMGL_SIZE(various_limits), 0, texture_limits, i18n("Texturing"), NULL}, {KCMGL_SIZE(various_limits), 0, various_limits, i18n("Various limits"), NULL}, {KCMGL_SIZE(float_limits), 0, float_limits, i18n("Points and lines"), NULL}, {KCMGL_SIZE(stack_depth), 0, stack_depth, i18n("Stack depth limits"), NULL}, #ifdef GL_ARB_vertex_program {KCMGL_SIZE(arb_vp), GL_VERTEX_PROGRAM_ARB, arb_vp, "ARB_vertex_program", "GL_ARB_vertex_program"}, #endif #ifdef GL_ARB_fragment_program {KCMGL_SIZE(arb_fp), GL_FRAGMENT_PROGRAM_ARB, arb_fp, "ARB_fragment_program", "GL_ARB_fragment_program"}, #endif #ifdef GL_ARB_vertex_shader {KCMGL_SIZE(arb_vs), 0, arb_vs, "ARB_vertex_shader", "GL_ARB_vertex_shader"}, #endif #ifdef GL_ARB_fragment_shader {KCMGL_SIZE(arb_fs), 0, arb_fs, "ARB_fragment_shader", "GL_ARB_fragment_shader"}, #endif }; #if defined(GLX_ARB_get_proc_address) && defined(PFNGLGETPROGRAMIVARBPROC) if (getProcAddress && strstr(glExtensions, "GL_ARB_vertex_program")) kcm_glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) glXGetProcAddressARB((const GLubyte *)"glGetProgramivARB"); #else Q_UNUSED(getProcAddress); #endif for (uint i = 0; itype; cur_token++) { bool tfloat = cur_token->type & KCMGL_FLOAT; int count = KCMGL_COUNT_MASK(cur_token->type); GLint max[2]={0,0}; GLfloat fmax[2]={0.0,0.0}; #if defined(PFNGLGETPROGRAMIVARBPROC) && defined(GL_ARB_vertex_program) bool tprog = cur_token->type & KCMGL_PROG; if (tprog && kcm_glGetProgramivARB) kcm_glGetProgramivARB(groups[i].type, cur_token->token, max); else #endif if (tfloat) glGetFloatv(cur_token->token, fmax); else glGetIntegerv(cur_token->token, max); if (glGetError() == GL_NONE) { QString s; if (!tfloat && count == 1) s = QString::number(max[0]); else if (!tfloat && count == 2) s = QStringLiteral("%1, %2").arg(max[0]).arg(max[1]); else if (tfloat && count == 2) s = QStringLiteral("%1 - %2").arg(fmax[0],0,'f',6).arg(fmax[1],0,'f',6); else if (tfloat && count == 1) s = QString::number(fmax[0],'f',6); if (l3) l3 = newItem(l2, l3, cur_token->name, s); else l3 = newItem(l2, cur_token->name, s); } } } } #endif static QTreeWidgetItem *print_screen_info(QTreeWidgetItem *l1, QTreeWidgetItem *after, const QString &title) { QTreeWidgetItem *l2 = nullptr, *l3 = nullptr; if (after) { l1 = newItem(l1, after, title); } else { l1 = newItem(l1, title); } if (IsDirect) { if (get_dri_device()) { l2 = newItem(l1, i18n("3D Accelerator")); l2->setExpanded(true); l3 = newItem(l2, l3, i18n("Vendor"), dri_info.vendor); l3 = newItem(l2, l3, i18n("Device"), dri_info.device); l3 = newItem(l2, l3, i18n("Subvendor"), dri_info.subvendor); l3 = newItem(l2, l3, i18n("Revision"), dri_info.rev); } else { l2 = newItem(l1, l2, i18n("3D Accelerator"), i18n("unknown")); } } if (l2) { l2 = newItem(l1, l2, i18n("Driver")); }else{ l2 = newItem(l1, i18n("Driver")); } l2->setExpanded(true); l3 = newItem(l2, i18n("Vendor"), gli.glVendor); l3 = newItem(l2, l3, i18n("Renderer"), gli.glRenderer); #ifdef KCM_ENABLE_OPENGLES l3 = newItem(l2, l3, i18n("OpenGL ES version"), gli.glVersion); #else l3 = newItem(l2, l3, i18n("OpenGL version"), gli.glVersion); #endif if (IsDirect) { if (dri_info.module.isEmpty()) dri_info.module = i18n("unknown"); l3 = newItem(l2, l3, i18n("Kernel module"), dri_info.module); } #ifdef KCM_ENABLE_OPENGLES l3 = newItem(l2, l3, i18n("OpenGL ES extensions")); #else l3 = newItem(l2, l3, i18n("OpenGL extensions")); #endif print_extension_list(gli.glExtensions, l3); #if KCM_HAVE_GLX if (QGuiApplication::platformName() == QStringLiteral("xcb")) { l3 = newItem(l2, l3, i18n("Implementation specific")); print_limits(l3, gli.glExtensions, strstr(gli.clientExtensions, "GLX_ARB_get_proc_address") != nullptr); } #endif return l1; } #if KCM_HAVE_GLX void print_glx_glu(QTreeWidgetItem *l1, QTreeWidgetItem *l2) { QTreeWidgetItem *l3; l2 = newItem(l1, l2, i18n("GLX")); l3 = newItem(l2, i18n("server GLX vendor"), gli.serverVendor); l3 = newItem(l2, l3, i18n("server GLX version"), gli.serverVersion); l3 = newItem(l2, l3, i18n("server GLX extensions")); print_extension_list(gli.serverExtensions, l3); l3 = newItem(l2, l3, i18n("client GLX vendor") ,gli.clientVendor); l3 = newItem(l2, l3, i18n("client GLX version"), gli.clientVersion); l3 = newItem(l2, l3, i18n("client GLX extensions")); print_extension_list(gli.clientExtensions, l3); l3 = newItem(l2, l3, i18n("GLX extensions")); print_extension_list(gli.glxExtensions, l3); l2 = newItem(l1, l2, i18n("GLU")); l3 = newItem(l2, i18n("GLU version"), gli.gluVersion); l3 = newItem(l2, l3, i18n("GLU extensions")); print_extension_list(gli.gluExtensions, l3); } #endif #if KCM_HAVE_EGL void print_egl(QTreeWidgetItem *l1, QTreeWidgetItem *l2) { QTreeWidgetItem *l3; l2 = newItem(l1, l2, i18n("EGL")); l3 = newItem(l2, i18n("EGL Vendor"), gli.eglVendor); l3 = newItem(l2, l3, i18n("EGL Version"), gli.eglVersion); l3 = newItem(l2, l3, i18n("EGL Extensions")); print_extension_list(gli.eglExtensions, l3); } #endif #if KCM_HAVE_GLX static QTreeWidgetItem *get_gl_info_glx(Display *dpy, int scrnum, Bool allowDirect, QTreeWidgetItem *l1, QTreeWidgetItem *after) { Window win; XSetWindowAttributes attr; unsigned long mask; Window root; XVisualInfo *visinfo; int width = 100, height = 100; QTreeWidgetItem *result = after; root = RootWindow(dpy, scrnum); const int attribSingle[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, None }; const int attribDouble[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, None }; GLXContext ctx; visinfo = glXChooseVisual(dpy, scrnum, const_cast(attribSingle)); if (!visinfo) { visinfo = glXChooseVisual(dpy, scrnum, const_cast(attribDouble)); if (!visinfo) { qDebug() << "Error: couldn't find RGB GLX visual\n"; return result; } } attr.background_pixel = 0; attr.border_pixel = 0; attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); attr.event_mask = StructureNotifyMask | ExposureMask; mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; win = XCreateWindow(dpy, root, 0, 0, width, height, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr); ctx = glXCreateContext( dpy, visinfo, NULL, allowDirect ); if (!ctx) { qDebug() << "Error: glXCreateContext failed\n"; XDestroyWindow(dpy, win); XFree(visinfo); return result; } if (glXMakeCurrent(dpy, win, ctx)) { gli.serverVendor = glXQueryServerString(dpy, scrnum, GLX_VENDOR); gli.serverVersion = glXQueryServerString(dpy, scrnum, GLX_VERSION); gli.serverExtensions = glXQueryServerString(dpy, scrnum, GLX_EXTENSIONS); gli.clientVendor = glXGetClientString(dpy, GLX_VENDOR); gli.clientVersion = glXGetClientString(dpy, GLX_VERSION); gli.clientExtensions = glXGetClientString(dpy, GLX_EXTENSIONS); gli.glxExtensions = glXQueryExtensionsString(dpy, scrnum); gli.glVendor = (const char *) glGetString(GL_VENDOR); gli.glRenderer = (const char *) glGetString(GL_RENDERER); gli.glVersion = (const char *) glGetString(GL_VERSION); gli.glExtensions = (const char *) glGetString(GL_EXTENSIONS); gli.displayName = nullptr; gli.gluVersion = (const char *) gluGetString(GLU_VERSION); gli.gluExtensions = (const char *) gluGetString(GLU_EXTENSIONS); IsDirect = glXIsDirect(dpy, ctx); result = print_screen_info(l1, after, IsDirect ? i18n("Direct Rendering (GLX)") : i18n("Indirect Rendering (GLX)")); } else { qDebug() << "Error: glXMakeCurrent failed\n"; } glXMakeCurrent(dpy, GL_NONE, nullptr); glXDestroyContext(dpy, ctx); XDestroyWindow(dpy, win); XFree(visinfo); return result; } #endif #if KCM_HAVE_EGL static QTreeWidgetItem *get_gl_info_egl(Display *dpy, int scrnum, QTreeWidgetItem *l1, QTreeWidgetItem *after) { Window win; XSetWindowAttributes attr; unsigned long mask; Window root; XVisualInfo *visinfo; int width = 100, height = 100; QTreeWidgetItem *result = after; root = RootWindow(dpy, scrnum); static const EGLint attribs[] = { EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, EGL_DEPTH_SIZE, 1, EGL_NONE }; static const EGLint ctx_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; XVisualInfo visTemplate; int num_visuals; EGLDisplay egl_dpy; EGLSurface surf; EGLContext ctx; EGLConfig config; EGLint num_configs; EGLint vid, major, minor; egl_dpy = eglGetDisplay(dpy); if (!egl_dpy) { qDebug() << "Error: eglGetDisplay() failed\n"; return result; } if (!eglInitialize(egl_dpy, &major, &minor)) { qDebug() << "Error: eglInitialize() failed\n"; return result; } if (!eglChooseConfig(egl_dpy, attribs, &config, 1, &num_configs)) { qDebug() << "Error: couldn't get an EGL visual config\n"; return result; } if (!eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) { qDebug() << "Error: eglGetConfigAttrib() failed\n"; return result; } visTemplate.visualid = vid; visinfo = XGetVisualInfo(dpy, VisualIDMask, &visTemplate, &num_visuals); if (!visinfo) { qDebug() << "Error: couldn't get X visual\n"; return result; } attr.background_pixel = 0; attr.border_pixel = 0; attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); attr.event_mask = StructureNotifyMask | ExposureMask; mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; win = XCreateWindow(dpy, root, 0, 0, width, height, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr); #ifdef KCM_ENABLE_OPENGLES eglBindAPI(EGL_OPENGL_ES_API); #else eglBindAPI(EGL_OPENGL_API); #endif ctx = eglCreateContext(egl_dpy, config, EGL_NO_CONTEXT, ctx_attribs); if (!ctx) { qDebug() << "Error: eglCreateContext failed\n"; XDestroyWindow(dpy, win); XFree(visinfo); return result; } surf = eglCreateWindowSurface(egl_dpy, config, win, NULL); if (!surf) { qDebug() << "Error: eglCreateWindowSurface failed\n"; eglDestroyContext(egl_dpy, ctx); XDestroyWindow(dpy, win); XFree(visinfo); return result; } if (eglMakeCurrent(egl_dpy, surf, surf, ctx)) { gli.eglVendor = eglQueryString(egl_dpy, EGL_VENDOR); gli.eglVersion = eglQueryString(egl_dpy, EGL_VERSION); gli.eglExtensions = eglQueryString(egl_dpy, EGL_EXTENSIONS); gli.glVendor = (const char *) glGetString(GL_VENDOR); gli.glRenderer = (const char *) glGetString(GL_RENDERER); gli.glVersion = (const char *) glGetString(GL_VERSION); gli.glExtensions = (const char *) glGetString(GL_EXTENSIONS); gli.displayName = nullptr; result = print_screen_info(l1, after, i18n("Direct Rendering (EGL)")); } else { qDebug() <<"Error: eglMakeCurrent() failed\n"; } eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroyContext(egl_dpy, ctx); eglDestroySurface(egl_dpy, surf); XDestroyWindow(dpy, win); XFree(visinfo); return result; } static QTreeWidgetItem *get_gl_info_egl_qt(QTreeWidgetItem *l1, QTreeWidgetItem *after, QSurfaceFormat::OpenGLContextProfile profile, const QString &title) { QTreeWidgetItem *result = after; QOffscreenSurface surface; surface.create(); QOpenGLContext context; QSurfaceFormat format; format.setProfile(profile); context.setFormat(format); if (!context.create()) { qDebug() << "Could not create QOpenGLContext"; return result; } if (context.format().profile() != profile) { qDebug() << "Could not get requested OpenGL profile, requested" << profile << "got" << context.format().profile(); return result; } if (context.makeCurrent(&surface)) { EGLDisplay egl_dpy = eglGetCurrentDisplay(); gli.eglVendor = eglQueryString(egl_dpy, EGL_VENDOR); gli.eglVersion = eglQueryString(egl_dpy, EGL_VERSION); gli.eglExtensions = eglQueryString(egl_dpy, EGL_EXTENSIONS); gli.glVendor = (const char *) glGetString(GL_VENDOR); gli.glRenderer = (const char *) glGetString(GL_RENDERER); gli.glVersion = (const char *) glGetString(GL_VERSION); gli.glExtensions = (const char *) glGetString(GL_EXTENSIONS); gli.displayName = nullptr; result = print_screen_info(l1, after, title); } else { qDebug() <<"Error: eglMakeCurrent() failed\n"; } context.doneCurrent(); return result; } #endif bool GetInfo_OpenGL(QTreeWidget *treeWidget) { QTreeWidgetItem *l1, *l2 = nullptr; static bool isX11 = QGuiApplication::platformName() == QStringLiteral("xcb"); static bool isWayland = QGuiApplication::platformName().contains(QStringLiteral("wayland")); QTreeWidgetItem *header = new QTreeWidgetItem(); header->setText(0, i18n("Information")); header->setText(1, i18n("Value")); treeWidget->setHeaderItem(header); treeWidget->setRootIsDecorated(false); l1 = new QTreeWidgetItem(treeWidget); if (isX11) { char *displayName = nullptr; Display *dpy; int numScreens, scrnum; dpy = XOpenDisplay(displayName); if (!dpy) { // qDebug() << "Error: unable to open display " << displayName; return false; } l1->setText(0, i18n("Name of the Display")); - l1->setText(1, DisplayString(dpy)); + l1->setText(1, QString::fromLatin1(DisplayString(dpy))); l1->setExpanded(true); l1->setFlags(Qt::ItemIsEnabled); numScreens = ScreenCount(dpy); scrnum = 0; #ifdef KCMGL_MANY_SCREENS for (; scrnum < numScreens; scrnum++) #endif { #if KCM_HAVE_GLX mesa_hack(dpy, scrnum); l2 = get_gl_info_glx(dpy, scrnum, true, l1, l2); if (l2) l2->setExpanded(true); #endif #if KCM_HAVE_EGL l2 = get_gl_info_egl(dpy, scrnum, l1, l2); if (l2) l2->setExpanded(true); #endif // TODO print_visual_info(dpy, scrnum, mode); } #if KCM_HAVE_GLX if (l2) print_glx_glu(l1, l2); else KMessageBox::error(0, i18n("Could not initialize OpenGL/GLX")); #endif XCloseDisplay(dpy); } if (isWayland) { IsDirect = true; l1->setText(0, i18n("Name of the Display")); - l1->setText(1, qgetenv("WAYLAND_DISPLAY")); + l1->setText(1, QString::fromLatin1(qgetenv("WAYLAND_DISPLAY"))); l1->setExpanded(true); l1->setFlags(Qt::ItemIsEnabled); #if KCM_HAVE_EGL l2 = get_gl_info_egl_qt(l1, l2, QSurfaceFormat::NoProfile, i18n("OpenGL")); if (l2) l2->setExpanded(true); l2 = get_gl_info_egl_qt(l1, l2, QSurfaceFormat::CoreProfile, i18n("Core Profile")); if (l2) l2->setExpanded(true); l2 = get_gl_info_egl_qt(l1, l2, QSurfaceFormat::CompatibilityProfile, i18n("Compatibility Profile")); if (l2) l2->setExpanded(true); #endif } #if KCM_HAVE_EGL if (l2) print_egl(l1, l2); else KMessageBox::error(0, i18n("Could not initialize OpenGL (ES)/EGL ")); #endif treeWidget->resizeColumnToContents(0); treeWidget->resizeColumnToContents(1); return true; } #include "opengl.moc" diff --git a/Modules/usbview/usbdevices.cpp b/Modules/usbview/usbdevices.cpp index e6e683b..1fb32e7 100644 --- a/Modules/usbview/usbdevices.cpp +++ b/Modules/usbview/usbdevices.cpp @@ -1,435 +1,435 @@ /*************************************************************************** * Copyright (C) 2001 by Matthias Hoelzer-Kluepfel * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "usbdevices.h" #include #include #include #include #include #include #include #include #include #include #include "usbdb.h" #include #if defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) #include #include #endif QList USBDevice::_devices; USBDB *USBDevice::_db; USBDevice::USBDevice() : _bus(0), _level(0), _parent(0), _port(0), _count(0), _device(0), _channels(0), _power(0), _speed(0.0), _bwTotal(0), _bwUsed(0), _bwPercent(0), _bwIntr(0), _bwIso(0), _hasBW(false), _verMajor(0), _verMinor(0), _class(0), _sub(0), _prot(0), _maxPacketSize(0), _configs(0), _vendorID(0), _prodID(0), _revMajor(0), _revMinor(0) { _devices.append(this); if (!_db) _db = new USBDB; } USBDevice::~USBDevice() { } static QString catFile(const QString &fname) { char buffer[256]; QString result; - int fd =:: open(QFile::encodeName(fname), O_RDONLY); + int fd =:: open(QFile::encodeName(fname).constData(), O_RDONLY); if (fd<0) return QString(); if (fd >= 0) { ssize_t count; while ((count = ::read(fd, buffer, 256)) > 0) result.append(QString::fromLatin1(buffer).leftRef(count)); ::close(fd); } return result.trimmed(); } void USBDevice::parseSysDir(int bus, int parent, int level, const QString& dname) { _level = level; _parent = parent; _manufacturer = catFile(dname + QStringLiteral("/manufacturer")); _product = catFile(dname + QStringLiteral("/product")); _bus = bus; _device = catFile(dname + QStringLiteral("/devnum")).toUInt(); if (_device == 1) _product += QStringLiteral(" (%1)").arg(_bus); _vendorID = catFile(dname + QStringLiteral("/idVendor")).toUInt(nullptr, 16); _prodID = catFile(dname + QStringLiteral("/idProduct")).toUInt(nullptr, 16); _class = catFile(dname + QStringLiteral("/bDeviceClass")).toUInt(nullptr, 16); _sub = catFile(dname + QStringLiteral("/bDeviceSubClass")).toUInt(nullptr, 16); _maxPacketSize = catFile(dname + QStringLiteral("/bMaxPacketSize0")).toUInt(); _speed = catFile(dname + QStringLiteral("/speed")).toDouble(); _serial = catFile(dname + QStringLiteral("/serial")); _channels = catFile(dname + QStringLiteral("/maxchild")).toUInt(); double version = catFile(dname + QStringLiteral("/version")).toDouble(); _verMajor = int(version); _verMinor = int(10*(version - floor(version))); QDir dir(dname); dir.setNameFilters(QStringList() << QStringLiteral("%1-*").arg(bus)); dir.setFilter(QDir::Dirs); const QStringList list = dir.entryList(); for (QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it) { if ((*it).contains(QLatin1Char(':'))) continue; USBDevice* dev = new USBDevice(); dev->parseSysDir(bus, ++level, _device, dname + QLatin1Char('/') + *it); } } void USBDevice::parseLine(const QString& line) { if (line.startsWith(QLatin1String("T:"))) sscanf(line.toLocal8Bit().data(), "T: Bus=%2d Lev=%2d Prnt=%2d Port=%d Cnt=%2d Dev#=%3d Spd=%3f MxCh=%2d", &_bus, &_level, &_parent, &_port, &_count, &_device, &_speed, &_channels); else if (line.startsWith(QLatin1String("S: Manufacturer"))) _manufacturer = line.mid(17); else if (line.startsWith(QLatin1String("S: Product"))) { _product = line.mid(12); /* add bus number to root devices */ if (_device==1) _product += QStringLiteral(" (%1)").arg(_bus); } else if (line.startsWith(QLatin1String("S: SerialNumber"))) _serial = line.mid(17); else if (line.startsWith(QLatin1String("B:"))) { sscanf(line.toLocal8Bit().data(), "B: Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d", &_bwUsed, &_bwTotal, &_bwPercent, &_bwIntr, &_bwIso); _hasBW = true; } else if (line.startsWith(QLatin1String("D:"))) { char buffer[11]; sscanf(line.toLocal8Bit().data(), "D: Ver=%x.%x Cls=%x(%10s) Sub=%x Prot=%x MxPS=%u #Cfgs=%u", &_verMajor, &_verMinor, &_class, buffer, &_sub, &_prot, &_maxPacketSize, &_configs); _className = QString::fromLatin1(buffer); } else if (line.startsWith(QLatin1String("P:"))) sscanf(line.toLocal8Bit().data(), "P: Vendor=%x ProdID=%x Rev=%x.%x", &_vendorID, &_prodID, &_revMajor, &_revMinor); } USBDevice* USBDevice::find(int bus, int device) { foreach(USBDevice* usbDevice, _devices) { if (usbDevice->bus() == bus && usbDevice->device() == device) return usbDevice; } return nullptr; } QString USBDevice::product() { if (!_product.isEmpty()) return _product; QString pname = _db->device(_vendorID, _prodID); if (!pname.isEmpty()) return pname; return i18n("Unknown"); } QString USBDevice::dump() { QString r; r = QStringLiteral("

") + product() + QStringLiteral("


"); if (!_manufacturer.isEmpty()) r += i18n("Manufacturer: ") + _manufacturer + QStringLiteral("
"); if (!_serial.isEmpty()) r += i18n("Serial #: ") + _serial + QStringLiteral("
"); r += QLatin1String("
"); QString c = QStringLiteral("").arg(_class); QString cname = _db->cls(_class); if (!cname.isEmpty()) - c += QStringLiteral(""); + c += QStringLiteral(""); r += i18n("%1", c); QString sc = QStringLiteral("").arg(_sub); QString scname = _db->subclass(_class, _sub); if (!scname.isEmpty()) - sc += QStringLiteral(""); + sc += QStringLiteral(""); r += i18n("%1", sc); QString pr = QStringLiteral("").arg(_prot); QString prname = _db->protocol(_class, _sub, _prot); if (!prname.isEmpty()) pr += QStringLiteral(""); r += i18n("%1", pr); #if !(defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD)) r += ki18n("") .subs(_verMajor,0,16).subs(_verMinor,2,16,QChar::fromLatin1('0')) .toString(); #endif r += QLatin1String(""); QString v = QString::number(_vendorID, 16); QString name = _db->vendor(_vendorID); if (!name.isEmpty()) v += QStringLiteral(""); r += i18n("", v); QString p = QString::number(_prodID, 16); QString pname = _db->device(_vendorID, _prodID); if (!pname.isEmpty()) p += QStringLiteral(""); r += i18n("", p); r += ki18n("") .subs(_revMajor,0,16).subs(_revMinor,2,16,QChar::fromLatin1('0')) .toString(); r += QLatin1String(""); r += i18n("", _speed); r += i18n("", _channels); #if (defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD)) && !defined(DISABLE_USBDEVICES_FREEBSD) if ( _power ) r += i18n("", _power); else r += i18n(""); r += i18n("", _devnodes.at(0)); if ( _devnodes.count() > 1 ) { QStringList::const_iterator it = _devnodes.constBegin(); ++it; for (; it != _devnodes.constEnd(); ++it ) r += QStringLiteral(""); } #else r += i18n("", _maxPacketSize); #endif r += QLatin1String(""); if (_hasBW) { r += i18n("", _bwUsed, _bwTotal, _bwPercent); r += i18n("", _bwIntr); r += i18n("", _bwIso); r += QLatin1String(""); } r += QLatin1String("
%1(") + i18n(cname.toLatin1()) +QStringLiteral(")(") + i18n(cname.toLatin1().constData()) +QStringLiteral(")
Class
%1(") + i18n(scname.toLatin1()) +QStringLiteral(")(") + i18n(scname.toLatin1().constData()) +QStringLiteral(")
Subclass
%1(") + prname +QStringLiteral(")
Protocol
USB Version%1.%2
(") + name +QStringLiteral(")
Vendor ID0x%1
(") + pname +QStringLiteral(")
Product ID0x%1
Revision%1.%2
Speed%1 Mbit/s
Channels%1
Power Consumption%1 mA
Power Consumptionself powered
Attached Devicenodes%1
") + *it + QStringLiteral("
Max. Packet Size%1
Bandwidth%1 of %2 (%3%)
Intr. requests%1
Isochr. requests%1
"); return r; } #if !(defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD)) bool USBDevice::parse(const QString &fname) { _devices.clear(); QString result; // read in the complete file // // Note: we can't use a QTextStream, as the files in /proc // are pseudo files with zero length char buffer[256]; - int fd =:: open(QFile::encodeName(fname), O_RDONLY); + int fd =:: open(QFile::encodeName(fname).constData(), O_RDONLY); if (fd<0) return false; if (fd >= 0) { ssize_t count; while ((count = ::read(fd, buffer, 256)) > 0) result.append(QString::fromLatin1(buffer).leftRef(count)); ::close(fd); } // read in the device infos USBDevice *device = nullptr; int start=0, end; result.remove(QRegExp(QStringLiteral("^\n"))); while ((end = result.indexOf(QLatin1Char('\n'), start)) > 0) { QString line = result.mid(start, end-start); if (line.startsWith(QLatin1String("T:"))) device = new USBDevice(); if (device) device->parseLine(line); start = end+1; } return true; } bool USBDevice::parseSys(const QString &dname) { QDir d(dname); d.setNameFilters(QStringList() << QStringLiteral("usb*")); const QStringList list = d.entryList(); for (QStringList::const_iterator it = list.constBegin(), total = list.constEnd(); it != total; ++it) { USBDevice* device = new USBDevice(); int bus = 0; QRegExp bus_reg(QStringLiteral("[a-z]*([0-9]+)")); if (bus_reg.indexIn(*it) != -1) bus = bus_reg.cap(1).toInt(); device->parseSysDir(bus, 0, 0, d.absolutePath() + QLatin1Char('/') + *it); } return d.count(); } #else // Unused by *BSD bool USBDevice::parseSys(const QString &fname) { Q_UNUSED(fname) return true; } # if defined(DISABLE_USBDEVICES_FREEBSD) /* * FIXME: The USB subsystem has changed a lot in FreeBSD 8.0 * Support for it must be written. */ bool USBDevice::parse(const QString &fname) { Q_UNUSED(fname) return true; } # else /* * FreeBSD support by Markus Brueffer * * Basic idea and some code fragments were taken from FreeBSD's usbdevs(8), * originally developed for NetBSD, so this code should work with no or * only little modification on NetBSD. */ void USBDevice::collectData( int fd, int level, usb_device_info &di, int parent) { // determine data for this device _level = level; _parent = parent; _bus = di.udi_bus; _device = di.udi_addr; _product = QLatin1String(di.udi_product); if ( _device == 1 ) _product += ' ' + QString::number( _bus ); _manufacturer = QLatin1String(di.udi_vendor); _prodID = di.udi_productNo; _vendorID = di.udi_vendorNo; _class = di.udi_class; _sub = di.udi_subclass; _prot = di.udi_protocol; _power = di.udi_power; _channels = di.udi_nports; // determine the speed #if defined(__DragonFly__) || (defined(Q_OS_FREEBSD) && __FreeBSD_version > 490102) || defined(Q_OS_NETBSD) switch (di.udi_speed) { case USB_SPEED_LOW: _speed = 1.5; break; case USB_SPEED_FULL: _speed = 12.0; break; case USB_SPEED_HIGH: _speed = 480.0; break; } #else _speed = di.udi_lowspeed ? 1.5 : 12.0; #endif // Get all attached devicenodes for ( int i = 0; i < USB_MAX_DEVNAMES; ++i ) if ( di.udi_devnames[i][0] ) _devnodes << di.udi_devnames[i]; // For compatibility, split the revision number sscanf( di.udi_release, "%x.%x", &_revMajor, &_revMinor ); // Cycle through the attached devices if there are any for ( int p = 0; p < di.udi_nports; ++p ) { // Get data for device struct usb_device_info di2; di2.udi_addr = di.udi_ports[p]; if ( di2.udi_addr >= USB_MAX_DEVICES ) continue; if ( ioctl(fd, USB_DEVICEINFO, &di2) == -1 ) continue; // Only add the device if we didn't detect it, yet if (!find( di2.udi_bus, di2.udi_addr ) ) { USBDevice *device = new USBDevice(); device->collectData( fd, level + 1, di2, di.udi_addr ); } } } bool USBDevice::parse(const QString &fname) { Q_UNUSED(fname) static bool showErrorMessage = true; bool error = false; _devices.clear(); QFile controller("/dev/usb0"); int i = 1; while ( controller.exists() ) { // If the devicenode exists, continue with further inspection if ( controller.open(QIODevice::ReadOnly) ) { for ( int addr = 1; addr < USB_MAX_DEVICES; ++addr ) { struct usb_device_info di; di.udi_addr = addr; if ( ioctl(controller.handle(), USB_DEVICEINFO, &di) != -1 ) { if (!find( di.udi_bus, di.udi_addr ) ) { USBDevice *device = new USBDevice(); device->collectData( controller.handle(), 0, di, 0); } } } controller.close(); #ifndef Q_OS_NETBSD } else { error = true; #endif } controller.setFileName( QString::fromLocal8Bit("/dev/usb%1").arg(i++) ); } if ( showErrorMessage && error ) { showErrorMessage = false; KMessageBox::error( 0, i18n("Could not open one or more USB controller. Make sure, you have read access to all USB controllers that should be listed here.")); } return true; } # endif // defined(DISABLE_USBDEVICES_FREEBSD) #endif // !(defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD))