File indexing completed on 2024-05-19 05:29:59

0001 /*
0002  *   SPDX-FileCopyrightText: 2001 Matthias Hoelzer-Kluepfel <mhk@caldera.de>
0003  *   SPDX-License-Identifier: GPL-2.0-or-later
0004  */
0005 
0006 #include "usbdb.h"
0007 
0008 #include <iostream>
0009 
0010 #include <QDebug>
0011 #include <QFile>
0012 #include <QRegularExpression>
0013 #include <QRegularExpressionMatch>
0014 #include <QStandardPaths>
0015 #include <QTextStream>
0016 
0017 USBDB::USBDB()
0018 {
0019     QString db = QStringLiteral("/usr/share/hwdata/usb.ids"); /* on Fedora and Arch*/
0020     if (!QFile::exists(db)) {
0021         db = QStringLiteral("/usr/share/misc/usb.ids"); /* on Gentoo */
0022     }
0023     if (db.isEmpty())
0024         return;
0025 
0026     QFile f(db);
0027 
0028     if (f.open(QIODevice::ReadOnly)) {
0029         QTextStream ts(&f);
0030 
0031         QString line;
0032         int id = -1, subid = -1;
0033         const QRegularExpression vendor(QStringLiteral("^([0-9a-fA-F]{4})\\s+(.+)$"));
0034         const QRegularExpression product(QStringLiteral("^\t([0-9a-fA-F]{4})\\s+(.+)$"));
0035         const QRegularExpression cls(QStringLiteral("^C ([0-9a-fA-F]{2})\\s+(.+)$"));
0036         const QRegularExpression subclass(QStringLiteral("^\t([0-9a-fA-F]{2})\\s+(.+)$"));
0037         const QRegularExpression prot(QStringLiteral("^\t\t([0-9a-fA-F]{2})\\s+(.+)$"));
0038         while (ts.readLineInto(&line)) {
0039             if (!line.isEmpty() && line.startsWith(QLatin1String("#")))
0040                 continue;
0041 
0042             // skip unhandled categories lines
0043             if (line.isEmpty() || line.startsWith(QLatin1String("AT ")) || line.startsWith(QLatin1String("HID ")) || line.startsWith(QLatin1String("R "))
0044                 || line.startsWith(QLatin1String("BIAS ")) || line.startsWith(QLatin1String("PHY ")) || line.startsWith(QLatin1String("HUT "))
0045                 || line.startsWith(QLatin1String("L ")) || line.startsWith(QLatin1String("HCC ")) || line.startsWith(QLatin1String("VT "))) {
0046                 id = -1;
0047                 subid = -1;
0048                 continue;
0049             }
0050 
0051             QRegularExpressionMatch match;
0052             if (line.startsWith('C') && (match = cls.match(line)).hasMatch()) {
0053                 id = match.capturedView(1).toInt(0, 16);
0054                 const QString name = match.capturedView(2).trimmed().toString();
0055                 _classes.insert(QStringLiteral("%1").arg(id), name);
0056             } else if (id >= 0 && subid >= 0 && (match = prot.match(line)).hasMatch()) {
0057                 const int protid = match.capturedView(1).toInt(0, 16);
0058                 const QString name = match.capturedView(2).trimmed().toString();
0059                 _classes.insert(QStringLiteral("%1-%2-%3").arg(id).arg(subid).arg(protid), name);
0060             } else if (id >= 0 && (match = subclass.match(line)).hasMatch()) {
0061                 subid = match.capturedView(1).toInt(0, 16);
0062                 const QString name = match.capturedView(2).trimmed().toString();
0063                 _classes.insert(QStringLiteral("%1-%2").arg(id).arg(subid), name);
0064             } else if ((match = vendor.match(line)).hasMatch()) {
0065                 id = match.capturedView(1).toInt(0, 16);
0066                 const QString name = match.captured(2);
0067                 _ids.insert(QStringLiteral("%1").arg(id), name);
0068             } else if (id >= 0 && (match = product.match(line)).hasMatch()) {
0069                 subid = match.capturedView(1).toInt(0, 16);
0070                 const QString name = match.capturedView(2).trimmed().toString();
0071                 _ids.insert(QStringLiteral("%1-%2").arg(id).arg(subid), name);
0072             } else {
0073                 id = -1;
0074                 subid = -1;
0075             }
0076         }
0077 
0078         f.close();
0079     }
0080 }
0081 
0082 QString USBDB::vendor(uint16_t id) const
0083 {
0084     QString s = _ids.value(QStringLiteral("%1").arg(id));
0085     if (id != 0) {
0086         return s;
0087     }
0088     return QString();
0089 }
0090 
0091 QString USBDB::device(uint16_t vendor, uint16_t id) const
0092 {
0093     QString s = _ids.value(QStringLiteral("%1-%2").arg(vendor).arg(id));
0094     if ((id != 0) && (vendor != 0))
0095         return s;
0096     return QString();
0097 }
0098 
0099 QString USBDB::cls(uint8_t cls) const
0100 {
0101     return _classes.value(QStringLiteral("%1").arg(cls));
0102 }
0103 
0104 QString USBDB::subclass(uint8_t cls, uint8_t sub) const
0105 {
0106     return _classes.value(QStringLiteral("%1-%2").arg(cls).arg(sub));
0107 }
0108 
0109 QString USBDB::protocol(uint8_t cls, uint8_t sub, uint8_t prot) const
0110 {
0111     return _classes.value(QStringLiteral("%1-%2-%3").arg(cls).arg(sub).arg(prot));
0112 }