File indexing completed on 2024-05-19 09:41:49
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 }