Warning, file /system/kpmcore/src/core/smartattributeparseddata.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     SPDX-FileCopyrightText: 2008 Lennart Poettering
0003     SPDX-FileCopyrightText: 2018 Caio Jordão Carvalho <caiojcarvalho@gmail.com>
0004     SPDX-FileCopyrightText: 2018-2020 Andrius Štikonas <andrius@stikonas.eu>
0005 
0006     SPDX-License-Identifier: GPL-3.0-or-later
0007 */
0008 
0009 #include "smartattributeparseddata.h"
0010 #include "core/smartdiskinformation.h"
0011 
0012 #include <utility>
0013 
0014 #include <QJsonObject>
0015 #include <QMap>
0016 #include <QRegularExpression>
0017 #include <QVariant>
0018 #include <QVector>
0019 
0020 #define MKELVIN_VALID_MIN ((qint64) ((-15LL*1000LL) + 273150LL))
0021 #define MKELVIN_VALID_MAX ((qint64) ((100LL*1000LL) + 273150LL))
0022 
0023 #define MSECOND_VALID_MIN 1ULL
0024 #define MSECOND_VALID_SHORT_MAX (60ULL * 60ULL * 1000ULL)
0025 #define MSECOND_VALID_LONG_MAX (30ULL * 365ULL * 24ULL * 60ULL * 60ULL * 1000ULL)
0026 
0027 static QMap<qint32, SmartAttributeUnit> tableUnit();
0028 static SmartQuirk getQuirk(QString model, QString firmware);
0029 
0030 /** Creates a new SmartAttributeParsedData object.
0031     @param disk the reference to the disk that this attribute is allocated to
0032     @param jsonAttribute JSON attribute data
0033 */
0034 SmartAttributeParsedData::SmartAttributeParsedData(SmartDiskInformation *disk,
0035                                                    QJsonObject jsonAttribute) :
0036     m_Id(0),
0037     m_CurrentValue(0),
0038     m_WorstValue(0),
0039     m_Threshold(0),
0040     m_Raw(0),
0041     m_PrettyValue(0),
0042     m_CurrentValueValid(false),
0043     m_WorstValueValid(false),
0044     m_ThresholdValid(false),
0045     m_Prefailure(false),
0046     m_Online(false),
0047     m_GoodNow(true),
0048     m_GoodNowValid(false),
0049     m_GoodInThePast(true),
0050     m_GoodInThePastValid(false),
0051     m_Warn(false),
0052     m_PrettyUnit(SmartAttributeUnit::Unknown),
0053     m_Disk(disk),
0054     m_Quirk(SmartQuirk::None)
0055 {
0056     if (disk)
0057         m_Quirk = getQuirk(disk->model(), disk->firmware());
0058 
0059     if (!jsonAttribute.isEmpty()) {
0060         QString id = QStringLiteral("id");
0061         QString value = QStringLiteral("value");
0062         QString worst = QStringLiteral("worst");
0063         QString thresh = QStringLiteral("thresh");
0064         QString raw = QStringLiteral("raw");
0065         QString flags = QStringLiteral("flags");
0066         QString prefailure = QStringLiteral("prefailure");
0067         QString online = QStringLiteral("updated_online");
0068 
0069         m_Id = jsonAttribute[id].toInt();
0070         m_CurrentValue = jsonAttribute[value].toInt();
0071         m_WorstValue = jsonAttribute[worst].toInt();
0072         m_Threshold = jsonAttribute[thresh].toInt();
0073 
0074         QJsonObject rawObj = jsonAttribute[raw].toObject();
0075 
0076         m_Raw = rawObj[value].toVariant().toULongLong();
0077 
0078         QJsonObject flagsObj = jsonAttribute[flags].toObject();
0079 
0080         m_Prefailure = flagsObj[prefailure].toBool();
0081         m_Online = flagsObj[online].toBool();
0082 
0083         if (!updateUnit())
0084             m_PrettyUnit = SmartAttributeUnit::Unknown;
0085 
0086         makePretty();
0087 
0088         validateValues();
0089 
0090         verifyAttribute();
0091     }
0092 }
0093 
0094 /** @param other SmartAttributeParsedData to copy
0095 */
0096 SmartAttributeParsedData::SmartAttributeParsedData(const SmartAttributeParsedData &other) :
0097     m_Id(other.id()),
0098     m_CurrentValue(other.currentValue()),
0099     m_WorstValue(other.worstValue()),
0100     m_Threshold(other.threshold()),
0101     m_Raw(other.raw()),
0102     m_PrettyValue(other.prettyValue()),
0103     m_CurrentValueValid(other.currentValueValid()),
0104     m_WorstValueValid(other.worstValueValid()),
0105     m_ThresholdValid(other.thresholdValid()),
0106     m_Prefailure(other.prefailure()),
0107     m_Online(other.online()),
0108     m_GoodNow(other.goodNow()),
0109     m_GoodNowValid(other.goodNowValid()),
0110     m_GoodInThePast(other.goodInThePast()),
0111     m_GoodInThePastValid(other.goodInThePastValid()),
0112     m_Warn(other.warn()),
0113     m_PrettyUnit(other.prettyUnit()),
0114     m_Disk(other.disk()),
0115     m_Quirk(other.m_Quirk)
0116 {
0117 
0118 }
0119 
0120 /** Validate values from the current attribute */
0121 void SmartAttributeParsedData::validateValues()
0122 {
0123     m_CurrentValueValid = m_CurrentValue >= 1 && m_CurrentValue <= 0xFD;
0124     m_WorstValueValid = m_WorstValue >= 1 && m_WorstValue <= 0xFD;
0125     m_ThresholdValid = m_Threshold != 0xFE;
0126 
0127     if (m_Threshold >= 1 && m_Threshold <= 0xFD) {
0128         if (m_WorstValueValid) {
0129             m_GoodInThePast = m_GoodInThePast && (m_WorstValue > m_Threshold);
0130             m_GoodInThePastValid = true;
0131         }
0132         if (m_CurrentValueValid) {
0133             m_GoodNow = m_GoodNow && (m_CurrentValue > m_Threshold);
0134             m_GoodNowValid = true;
0135         }
0136     }
0137 
0138     m_Warn = (m_GoodNowValid && !m_GoodNow) || (m_GoodInThePastValid && !m_GoodInThePast);
0139 }
0140 
0141 /** Make a pretty value from raw based on attribute's id */
0142 void SmartAttributeParsedData::makePretty()
0143 {
0144     if (m_PrettyUnit == SmartAttributeUnit::Unknown)
0145         return;
0146 
0147     switch (id()) {
0148     case 3:
0149         m_PrettyValue = raw() & 0xFFFF;
0150         break;
0151 
0152     case 5:
0153         m_PrettyValue = raw() & 0xFFFFFFFFU;
0154         break;
0155 
0156     case 9:
0157         m_PrettyValue = (raw() & 0xFFFFFFFFU) * 60 * 60 * 1000;
0158         break;
0159 
0160     case 170:
0161         m_PrettyValue = currentValue();
0162         break;
0163 
0164     case 190:
0165         m_PrettyValue = (raw() & 0xFFFF) * 1000 + 273150;
0166         break;
0167 
0168     case 194:
0169         m_PrettyValue = (raw() & 0xFFFF) * 1000 + 273150;
0170         break;
0171 
0172     case 197:
0173         m_PrettyValue = (raw() & 0xFFFFFFFFU);
0174         break;
0175 
0176     case 222:
0177         m_PrettyValue = (raw() & 0xFFFFFFFFU) * 60 * 60 * 1000;
0178         break;
0179 
0180     case 228:
0181         m_PrettyValue = raw() * 60 * 1000;
0182         break;
0183 
0184     case 231:
0185         m_PrettyValue = (raw() & 0xFFFF) * 1000 + 273150;
0186         break;
0187 
0188     case 232:
0189         m_PrettyValue = currentValue();
0190         break;
0191 
0192     case 240:
0193         m_PrettyValue = (raw() & 0xFFFFFFFFU) * 60 * 60 * 1000;
0194         break;
0195 
0196     case 241:
0197         m_PrettyValue = raw() * 65536ULL * 512ULL / 1000000ULL;
0198         break;
0199 
0200     case 242:
0201         m_PrettyValue = raw() * 65536ULL * 512ULL / 1000000ULL;
0202         break;
0203 
0204     default:
0205         m_PrettyValue = raw();
0206         break;
0207 
0208     }
0209 }
0210 
0211 /** Verify attribute's unit */
0212 void SmartAttributeParsedData::verifyAttribute()
0213 {
0214     if (id() == 3 || id() == 226)
0215         verifyShortTime();
0216     else if (id() == 5 || id() == 187 || id() == 197 || id() == 198)
0217         verifySectors();
0218     else if (id() == 9 || id() == 222 || id() == 240)
0219         verifyLongTime();
0220     else if (id() == 190 || id() == 194 || id() == 231)
0221         verifyTemperature();
0222 }
0223 
0224 void SmartAttributeParsedData::verifyTemperature()
0225 {
0226     if (prettyUnit() != SmartAttributeUnit::Milikelvin)
0227         return;
0228 
0229     if (prettyValue() < MKELVIN_VALID_MIN || prettyValue() > MKELVIN_VALID_MAX)
0230         m_PrettyUnit = SmartAttributeUnit::Unknown;
0231 }
0232 
0233 void SmartAttributeParsedData::verifyShortTime()
0234 {
0235     if (prettyUnit() != SmartAttributeUnit::Miliseconds)
0236         return;
0237 
0238     if (prettyValue() < MSECOND_VALID_MIN || prettyValue() > MSECOND_VALID_SHORT_MAX)
0239         m_PrettyUnit = SmartAttributeUnit::Unknown;
0240 }
0241 
0242 void SmartAttributeParsedData::verifyLongTime()
0243 {
0244     if (prettyUnit() != SmartAttributeUnit::Miliseconds)
0245         return;
0246 
0247     if (prettyValue() < MSECOND_VALID_MIN || prettyValue() > MSECOND_VALID_LONG_MAX)
0248         m_PrettyUnit = SmartAttributeUnit::Unknown;
0249 }
0250 
0251 void SmartAttributeParsedData::verifySectors()
0252 {
0253     if (prettyUnit() != SmartAttributeUnit::Sectors)
0254         return;
0255 
0256     quint64 maxSectors = disk()->sectors();
0257 
0258     if (prettyValue() == 0xFFFFFFFFULL || prettyValue() == 0xFFFFFFFFFFFFULL || (maxSectors > 0
0259                                                                                  && prettyValue() > maxSectors))
0260         m_PrettyUnit = SmartAttributeUnit::Unknown;
0261     else if ((id() == 5 || id() == 197) && prettyValue() > 0)
0262         m_Warn = true;
0263 }
0264 
0265 bool SmartAttributeParsedData::updateUnit()
0266 {
0267     if (m_Quirk) {
0268         switch (id()) {
0269         case 3:
0270             if (m_Quirk & SmartQuirk::SMART_QUIRK_3_UNUSED) {
0271                 m_PrettyUnit = SmartAttributeUnit::Unknown;
0272                 return true;
0273             }
0274             break;
0275 
0276         case 4:
0277             if (m_Quirk & SmartQuirk::SMART_QUIRK_4_UNUSED) {
0278                 m_PrettyUnit = SmartAttributeUnit::Unknown;
0279                 return true;
0280             }
0281             break;
0282 
0283         case 5:
0284             if (m_Quirk & SmartQuirk::SMART_QUIRK_5_UNKNOWN)
0285                 return false;
0286             break;
0287 
0288         case 9:
0289             if (m_Quirk & SmartQuirk::SMART_QUIRK_9_POWERONMINUTES) {
0290                 m_PrettyUnit = SmartAttributeUnit::Miliseconds;
0291                 return true;
0292             } else if (m_Quirk & SmartQuirk::SMART_QUIRK_9_POWERONSECONDS) {
0293                 m_PrettyUnit = SmartAttributeUnit::Miliseconds;
0294                 return true;
0295             } else if (m_Quirk & SmartQuirk::SMART_QUIRK_9_POWERONHALFMINUTES) {
0296                 m_PrettyUnit = SmartAttributeUnit::Miliseconds;
0297                 return true;
0298             } else if (m_Quirk & SmartQuirk::SMART_QUIRK_9_UNKNOWN)
0299                 return false;
0300             break;
0301 
0302         case 190:
0303             if (m_Quirk & SmartQuirk::SMART_QUIRK_190_UNKNOWN)
0304                 return false;
0305             break;
0306 
0307         case 192:
0308             if (m_Quirk & SmartQuirk::SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT) {
0309                 m_PrettyUnit = SmartAttributeUnit::None;
0310                 return true;
0311             }
0312             break;
0313 
0314         case 194:
0315             if (m_Quirk & SmartQuirk::SMART_QUIRK_194_10XCELSIUS) {
0316                 m_PrettyUnit = SmartAttributeUnit::Milikelvin;
0317                 return true;
0318             } else if (m_Quirk & SmartQuirk::SMART_QUIRK_194_UNKNOWN)
0319                 return false;
0320             break;
0321 
0322         case 197:
0323             if (m_Quirk & SmartQuirk::SMART_QUIRK_197_UNKNOWN)
0324                 return false;
0325             break;
0326 
0327         case 198:
0328             if (m_Quirk & SmartQuirk::SMART_QUIRK_198_UNKNOWN)
0329                 return false;
0330             break;
0331 
0332         case 200:
0333             if (m_Quirk & SmartQuirk::SMART_QUIRK_200_WRITEERRORCOUNT) {
0334                 m_PrettyUnit = SmartAttributeUnit::None;
0335                 return true;
0336             }
0337             break;
0338 
0339         case 201:
0340             if (m_Quirk & SmartQuirk::SMART_QUIRK_201_DETECTEDTACOUNT) {
0341                 m_PrettyUnit = SmartAttributeUnit::None;
0342                 return true;
0343             }
0344             break;
0345 
0346         case 225:
0347             if (m_Quirk & SmartQuirk::SMART_QUIRK_225_TOTALLBASWRITTEN) {
0348                 m_PrettyUnit = SmartAttributeUnit::MB;
0349                 return true;
0350             }
0351             break;
0352 
0353         case 226:
0354             if (m_Quirk & SmartQuirk::SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR) {
0355                 m_PrettyUnit = SmartAttributeUnit::SmallPercent;
0356                 return true;
0357             }
0358             break;
0359 
0360         case 227:
0361             if (m_Quirk & SmartQuirk::SMART_QUIRK_227_TIMEWORKLOADHOSTREADS) {
0362                 m_PrettyUnit = SmartAttributeUnit::SmallPercent;
0363                 return true;
0364             }
0365             break;
0366 
0367         case 228:
0368             if (m_Quirk & SmartQuirk::SMART_QUIRK_228_WORKLOADTIMER) {
0369                 m_PrettyUnit = SmartAttributeUnit::Miliseconds;
0370                 return true;
0371             }
0372             break;
0373 
0374         case 232:
0375             if (m_Quirk & SmartQuirk::SMART_QUIRK_232_AVAILABLERESERVEDSPACE) {
0376                 m_PrettyUnit = SmartAttributeUnit::Percent;
0377                 return true;
0378             }
0379             break;
0380 
0381         case 233:
0382             if (m_Quirk & SmartQuirk::SMART_QUIRK_233_MEDIAWEAROUTINDICATOR) {
0383                 m_PrettyUnit = SmartAttributeUnit::Percent;
0384                 return true;
0385             }
0386             break;
0387 
0388         }
0389     }
0390 
0391     if (tableUnit().contains(id())) {
0392         m_PrettyUnit = tableUnit()[id()];
0393         return true;
0394     }
0395 
0396     return false;
0397 }
0398 
0399 static QMap<qint32, SmartAttributeUnit> tableUnit()
0400 {
0401     QMap<qint32, SmartAttributeUnit> table;
0402     table.insert(1, SmartAttributeUnit::None);
0403     table.insert(2, SmartAttributeUnit::Unknown);
0404     table.insert(3, SmartAttributeUnit::Miliseconds);
0405     table.insert(4, SmartAttributeUnit::None);
0406     table.insert(5, SmartAttributeUnit::Sectors);
0407     table.insert(6, SmartAttributeUnit::Unknown);
0408     table.insert(7, SmartAttributeUnit::None);
0409     table.insert(8, SmartAttributeUnit::Unknown);
0410     table.insert(9, SmartAttributeUnit::Miliseconds);
0411     table.insert(10, SmartAttributeUnit::None);
0412     table.insert(11, SmartAttributeUnit::None);
0413     table.insert(12, SmartAttributeUnit::None);
0414     table.insert(13, SmartAttributeUnit::None);
0415     table.insert(170, SmartAttributeUnit::Percent);
0416     table.insert(171, SmartAttributeUnit::None);
0417     table.insert(172, SmartAttributeUnit::None);
0418     table.insert(175, SmartAttributeUnit::None);
0419     table.insert(176, SmartAttributeUnit::None);
0420     table.insert(177, SmartAttributeUnit::None);
0421     table.insert(178, SmartAttributeUnit::None);
0422     table.insert(179, SmartAttributeUnit::None);
0423     table.insert(180, SmartAttributeUnit::None);
0424     table.insert(181, SmartAttributeUnit::None);
0425     table.insert(182, SmartAttributeUnit::None);
0426     table.insert(183, SmartAttributeUnit::None);
0427     table.insert(184, SmartAttributeUnit::None);
0428     table.insert(187, SmartAttributeUnit::Sectors);
0429     table.insert(188, SmartAttributeUnit::None);
0430     table.insert(189, SmartAttributeUnit::None);
0431     table.insert(190, SmartAttributeUnit::Milikelvin);
0432     table.insert(191, SmartAttributeUnit::None);
0433     table.insert(192, SmartAttributeUnit::None);
0434     table.insert(193, SmartAttributeUnit::None);
0435     table.insert(194, SmartAttributeUnit::Milikelvin);
0436     table.insert(195, SmartAttributeUnit::None);
0437     table.insert(196, SmartAttributeUnit::None);
0438     table.insert(197, SmartAttributeUnit::Sectors);
0439     table.insert(198, SmartAttributeUnit::Sectors);
0440     table.insert(199, SmartAttributeUnit::None);
0441     table.insert(200, SmartAttributeUnit::None);
0442     table.insert(201, SmartAttributeUnit::None);
0443     table.insert(202, SmartAttributeUnit::None);
0444     table.insert(203, SmartAttributeUnit::Unknown);
0445     table.insert(204, SmartAttributeUnit::None);
0446     table.insert(205, SmartAttributeUnit::None);
0447     table.insert(206, SmartAttributeUnit::Unknown);
0448     table.insert(207, SmartAttributeUnit::Unknown);
0449     table.insert(208, SmartAttributeUnit::Unknown);
0450     table.insert(209, SmartAttributeUnit::Unknown);
0451     table.insert(220, SmartAttributeUnit::Unknown);
0452     table.insert(221, SmartAttributeUnit::None);
0453     table.insert(222, SmartAttributeUnit::Miliseconds);
0454     table.insert(223, SmartAttributeUnit::None);
0455     table.insert(224, SmartAttributeUnit::Unknown);
0456     table.insert(225, SmartAttributeUnit::None);
0457     table.insert(226, SmartAttributeUnit::Miliseconds);
0458     table.insert(227, SmartAttributeUnit::None);
0459     table.insert(228, SmartAttributeUnit::None);
0460     table.insert(230, SmartAttributeUnit::Unknown);
0461     table.insert(231, SmartAttributeUnit::Milikelvin);
0462     table.insert(232, SmartAttributeUnit::Percent);
0463     table.insert(233, SmartAttributeUnit::Unknown);
0464     table.insert(234, SmartAttributeUnit::Sectors);
0465     table.insert(235, SmartAttributeUnit::Unknown);
0466     table.insert(240, SmartAttributeUnit::Miliseconds);
0467     table.insert(241, SmartAttributeUnit::MB);
0468     table.insert(242, SmartAttributeUnit::MB);
0469     table.insert(250, SmartAttributeUnit::None);
0470 
0471     return table;
0472 }
0473 
0474 static const QVector<SmartAttributeParsedData::SmartQuirkDataBase> quirkDatabase()
0475 {
0476     typedef SmartAttributeParsedData::SmartQuirkDataBase QuirkDatabase;
0477 
0478     QVector<QuirkDatabase> quirkDb;
0479 
0480     quirkDb << QuirkDatabase(QStringLiteral("^(FUJITSU MHY2120BH|FUJITSU MHY2250BH)$"), QStringLiteral("^0085000B$"),
0481                             static_cast<SmartQuirk>(SmartQuirk::SMART_QUIRK_9_POWERONMINUTES |
0482                                                     SmartQuirk::SMART_QUIRK_197_UNKNOWN |
0483                                                     SmartQuirk::SMART_QUIRK_198_UNKNOWN));
0484 
0485     quirkDb << QuirkDatabase(QStringLiteral("^FUJITSU MHR2040AT$"), QStringLiteral(), 
0486                             static_cast<SmartQuirk>(SmartQuirk::SMART_QUIRK_9_POWERONSECONDS |
0487                                                     SmartQuirk::SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT |
0488                                                     SmartQuirk::SMART_QUIRK_200_WRITEERRORCOUNT));
0489 
0490     quirkDb << QuirkDatabase(QStringLiteral("^FUJITSU MHS20[6432]0AT(  .)?$"), QStringLiteral(),
0491                             static_cast<SmartQuirk>(SmartQuirk::SMART_QUIRK_9_POWERONSECONDS |
0492                                                     SmartQuirk::SMART_QUIRK_192_EMERGENCYRETRACTCYCLECT |
0493                                                     SmartQuirk::SMART_QUIRK_200_WRITEERRORCOUNT |
0494                                                     SmartQuirk::SMART_QUIRK_201_DETECTEDTACOUNT));
0495 
0496     quirkDb << QuirkDatabase(QStringLiteral("^("
0497                             "FUJITSU M1623TAU|"
0498                             "FUJITSU MHG2...ATU?.*|"
0499                             "FUJITSU MHH2...ATU?.*|"
0500                             "FUJITSU MHJ2...ATU?.*|"
0501                             "FUJITSU MHK2...ATU?.*|"
0502                             "FUJITSU MHL2300AT|"
0503                             "FUJITSU MHM2(20|15|10|06)0AT|"
0504                             "FUJITSU MHN2...AT|"
0505                             "FUJITSU MHR2020AT|"
0506                             "FUJITSU MHT2...(AH|AS|AT|BH)U?.*|"
0507                             "FUJITSU MHU2...ATU?.*|"
0508                             "FUJITSU MHV2...(AH|AS|AT|BH|BS|BT).*|"
0509                             "FUJITSU MP[A-G]3...A[HTEV]U?.*"
0510                             ")$"),
0511                             QStringLiteral(),
0512                             SmartQuirk::SMART_QUIRK_9_POWERONSECONDS);
0513 
0514     quirkDb << QuirkDatabase(QStringLiteral("^("
0515                             "SAMSUNG SV4012H|"
0516                             "SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]"
0517                             ")$"),
0518                             QStringLiteral(),
0519                             SmartQuirk::SMART_QUIRK_9_POWERONHALFMINUTES);
0520 
0521     quirkDb << QuirkDatabase(QStringLiteral("^("
0522                             "SAMSUNG SV0412H|"
0523                             "SAMSUNG SV1204H"
0524                             ")$"),
0525                             QStringLiteral(),
0526                             static_cast<SmartQuirk>(SmartQuirk::SMART_QUIRK_9_POWERONHALFMINUTES | SmartQuirk::SMART_QUIRK_194_10XCELSIUS));
0527 
0528     quirkDb << QuirkDatabase(QStringLiteral("^SAMSUNG SP40A2H$"),
0529                             QStringLiteral("^RR100-07$"),
0530                             SmartQuirk::SMART_QUIRK_9_POWERONHALFMINUTES);
0531 
0532     quirkDb << QuirkDatabase(QStringLiteral("^SAMSUNG SP80A4H$"),
0533                             QStringLiteral("^RT100-06$"),
0534                             SmartQuirk::SMART_QUIRK_9_POWERONHALFMINUTES);
0535 
0536     quirkDb << QuirkDatabase(QStringLiteral("^SAMSUNG SP8004H$"),
0537                             QStringLiteral("^QW100-61$"),
0538                             SmartQuirk::SMART_QUIRK_9_POWERONHALFMINUTES);
0539 
0540     quirkDb << QuirkDatabase(QStringLiteral("^("
0541                             "Maxtor 2B0(0[468]|1[05]|20)H1|"
0542                             "Maxtor 4G(120J6|160J[68])|"
0543                             "Maxtor 4D0(20H1|40H2|60H3|80H4)"
0544                             ")$"),
0545                             QStringLiteral(),
0546                             static_cast<SmartQuirk>(SmartQuirk::SMART_QUIRK_9_POWERONMINUTES | SmartQuirk::SMART_QUIRK_194_UNKNOWN));
0547 
0548     quirkDb << QuirkDatabase(QStringLiteral("^("
0549                             "Maxtor 2F0[234]0[JL]0|"
0550                             "Maxtor 8(1280A2|2160A4|2560A4|3840A6|4000A6|5120A8)|"
0551                             "Maxtor 8(2160D2|3228D3|3240D3|4320D4|6480D6|8400D8|8455D8)|"
0552                             "Maxtor 9(0510D4|0576D4|0648D5|0720D5|0840D6|0845D6|0864D6|1008D7|1080D8|1152D8)|"
0553                             "Maxtor 9(1(360|350|202)D8|1190D7|10[12]0D6|0840D5|06[48]0D4|0510D3|1(350|202)E8|1010E6|0840E5|0640E4)|"
0554                             "Maxtor 9(0512D2|0680D3|0750D3|0913D4|1024D4|1360D6|1536D6|1792D7|2048D8)|"
0555                             "Maxtor 9(2732U8|2390U7|204[09]U6|1707U5|1366U4|1024U3|0845U3|0683U2)|"
0556                             "Maxtor 4(R0[68]0[JL]0|R1[26]0L0|A160J0|R120L4)|"
0557                             "Maxtor (91728D8|91512D7|91303D6|91080D5|90845D4|90645D3|90648D[34]|90432D2)|"
0558                             "Maxtor 9(0431U1|0641U2|0871U2|1301U3|1741U4)|"
0559                             "Maxtor (94091U8|93071U6|92561U5|92041U4|91731U4|91531U3|91361U3|91021U2|90841U2|90651U2)|"
0560                             "Maxtor (33073U4|32049U3|31536U2|30768U1|33073H4|32305H3|31536H2|30768H1)|"
0561                             "Maxtor (93652U8|92739U6|91826U4|91369U3|90913U2|90845U2|90435U1)|"
0562                             "Maxtor 9(0684U2|1024U2|1362U3|1536U3|2049U4|2562U5|3073U6|4098U8)|"
0563                             "Maxtor (54098[UH]8|53073[UH]6|52732[UH]6|52049[UH]4|51536[UH]3|51369[UH]3|51024[UH]2)|"
0564                             "Maxtor 3(1024H1|1535H2|2049H2|3073H3|4098H4)( B)?|"
0565                             "Maxtor 5(4610H6|4098H6|3073H4|2049H3|1536H2|1369H2|1023H2)|"
0566                             "Maxtor 9(1023U2|1536U2|2049U3|2305U3|3073U4|4610U6|6147U8)|"
0567                             "Maxtor 9(1023H2|1536H2|2049H3|2305H3|3073H4|4098H6|4610H6|6147H8)|"
0568                             "Maxtor 5T0(60H6|40H4|30H3|20H2|10H1)|"
0569                             "Maxtor (98196H8|96147H6)|"
0570                             "Maxtor 4W(100H6|080H6|060H4|040H3|030H2)|"
0571                             "Maxtor 6(E0[234]|K04)0L0|"
0572                             "Maxtor 6(B(30|25|20|16|12|10|08)0[MPRS]|L(080[MLP]|(100|120)[MP]|160[MP]|200[MPRS]|250[RS]|300[RS]))0|"
0573                             "Maxtor 6Y((060|080|120|160)L0|(060|080|120|160|200|250)P0|(060|080|120|160|200|250)M0)|"
0574                             "Maxtor 7Y250[PM]0|"
0575                             "Maxtor [45]A(25|30|32)0[JN]0|"
0576                             "Maxtor 7L(25|30)0[SR]0"
0577                             ")$"),
0578                             QStringLiteral(),
0579                             SmartQuirk::SMART_QUIRK_9_POWERONMINUTES);
0580 
0581     quirkDb << QuirkDatabase(QStringLiteral("^("
0582                             "HITACHI_DK14FA-20B|"
0583                             "HITACHI_DK23..-..B?|"
0584                             "HITACHI_DK23FA-20J|HTA422020F9AT[JN]0|"
0585                             "HE[JN]4230[23]0F9AT00|"
0586                             "HTC4260[23]0G5CE00|HTC4260[56]0G8CE00"
0587                             ")$"),
0588                             QStringLiteral(),
0589                             static_cast<SmartQuirk>(SmartQuirk::SMART_QUIRK_9_POWERONMINUTES | SmartQuirk::SMART_QUIRK_193_LOADUNLOAD));
0590 
0591     quirkDb << QuirkDatabase(QStringLiteral("^HTS541010G9SA00$"),
0592                             QStringLiteral("^MBZOC60P$"),
0593                             SmartQuirk::SMART_QUIRK_5_UNKNOWN);
0594 
0595     quirkDb << QuirkDatabase(QStringLiteral("^MCCOE64GEMPP$"),
0596                             QStringLiteral("^2.9.0[3-9]$"),
0597                             static_cast<SmartQuirk>(SmartQuirk::SMART_QUIRK_5_UNKNOWN | SmartQuirk::SMART_QUIRK_190_UNKNOWN));
0598 
0599     quirkDb << QuirkDatabase(QStringLiteral("^INTEL SSDSA2(CT|BT|CW|BW)[0-9]{3}G3.*$"), 
0600                             QStringLiteral(), 
0601                             static_cast<SmartQuirk>(SmartQuirk::SMART_QUIRK_3_UNUSED |
0602                                                     SmartQuirk::SMART_QUIRK_4_UNUSED |
0603                                                     SmartQuirk::SMART_QUIRK_225_TOTALLBASWRITTEN |
0604                                                     SmartQuirk::SMART_QUIRK_226_TIMEWORKLOADMEDIAWEAR |
0605                                                     SmartQuirk::SMART_QUIRK_227_TIMEWORKLOADHOSTREADS |
0606                                                     SmartQuirk::SMART_QUIRK_228_WORKLOADTIMER |
0607                                                     SmartQuirk::SMART_QUIRK_232_AVAILABLERESERVEDSPACE |
0608                                                     SmartQuirk::SMART_QUIRK_233_MEDIAWEAROUTINDICATOR));
0609 
0610     return quirkDb;
0611 }
0612 
0613 static SmartQuirk getQuirk(QString model, QString firmware)
0614 {
0615     const QVector<SmartAttributeParsedData::SmartQuirkDataBase> db = quirkDatabase();
0616 
0617     QRegularExpression modelRegex;
0618     QRegularExpression firmwareRegex;
0619 
0620     for (const SmartAttributeParsedData::SmartQuirkDataBase &item : std::as_const(db)) {
0621         if (!item.model.isEmpty()) {
0622             modelRegex.setPattern(item.model);
0623             QRegularExpressionMatch match = modelRegex.match(model);
0624             if (!match.hasMatch())
0625                 continue;
0626         }
0627         if (!item.firmware.isEmpty()) {
0628             firmwareRegex.setPattern(item.firmware);
0629             QRegularExpressionMatch match = firmwareRegex.match(firmware);
0630             if (!match.hasMatch())
0631                 continue;
0632         }
0633         return item.quirk;
0634     }
0635 
0636     return SmartQuirk::None;
0637 }