Skip to content

Commit d4b2593

Browse files
authored
Merge pull request #1077 from deXol/developBLEHandleNotFlashedDevice
[BLE] Add option to correct serial number
2 parents 98301b3 + 6f37e7d commit d4b2593

11 files changed

Lines changed: 307 additions & 4 deletions

src/Common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ class Common
357357
static const int BLE_BUNDLE_WITH_MIRRORING = 11;
358358
static const int BLE_BUNDLE_WITH_MULT_DOMAINS = 11;
359359
static const char ZERO_BYTE = static_cast<char>(0x00);
360+
static const int ALPHABET_SIZE = 26;
360361
static QByteArray NOT_SET_ADDR;
361362
};
362363

src/MPDeviceBleImpl.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ void MPDeviceBleImpl::getPlatInfo()
4848
connect(jobs, &AsyncJobs::finished, [this](const QByteArray &data)
4949
{
5050
QByteArray response = bleProt->getFullPayload(data);
51+
const auto messageSize = bleProt->getMessageSize(data);
5152
const auto mainMajor = bleProt->toIntFromLittleEndian(static_cast<quint8>(response[0]), static_cast<quint8>(response[1]));
5253
const auto mainMinor = bleProt->toIntFromLittleEndian(static_cast<quint8>(response[2]), static_cast<quint8>(response[3]));
5354
set_mainMCUVersion(QString::number(mainMajor) + "." + QString::number(mainMinor));
@@ -63,6 +64,16 @@ void MPDeviceBleImpl::getPlatInfo()
6364
mpDev->set_flashMbSize(memorySize);
6465
const auto bundleVersion = bleProt->toIntFromLittleEndian(static_cast<quint8>(response[14]), static_cast<quint8>(response[15]));
6566
set_bundleVersion(bundleVersion);
67+
if (messageSize > PLATFORM_SERIAL_NUM_FIRST_BYTE)
68+
{
69+
const auto serialPlatformLower = bleProt->toIntFromLittleEndian(static_cast<quint8>(response[PLATFORM_SERIAL_NUM_FIRST_BYTE]),
70+
static_cast<quint8>(response[PLATFORM_SERIAL_NUM_FIRST_BYTE+1]));
71+
const auto serialPlatformUpper = bleProt->toIntFromLittleEndian(static_cast<quint8>(response[PLATFORM_SERIAL_NUM_FIRST_BYTE+2]),
72+
static_cast<quint8>(response[PLATFORM_SERIAL_NUM_FIRST_BYTE+3]));
73+
quint32 serialPlatformNum = serialPlatformLower;
74+
serialPlatformNum |= static_cast<quint32>((serialPlatformUpper<<16));
75+
set_platformSerialNumber(serialPlatformNum);
76+
}
6677
});
6778

6879
mpDev->enqueueAndRunJob(jobs);
@@ -1960,6 +1971,26 @@ QString MPDeviceBleImpl::getBleNameFromArray(const QByteArray &arr) const
19601971
return bleProt->toQString(arr);
19611972
}
19621973

1974+
void MPDeviceBleImpl::setSerialNumber(quint32 serialNum, std::function<void (bool)> cb)
1975+
{
1976+
QByteArray serialNumArr = bleProt->toLittleEndianFromInt32(serialNum);
1977+
auto *jobs = new AsyncJobs(QString("Set Serial number"), this);
1978+
jobs->append(new MPCommandJob(mpDev, MPCmd::SET_SERIAL_NUMBER,
1979+
serialNumArr,
1980+
[this, serialNum, cb](const QByteArray &data, bool &) -> bool
1981+
{
1982+
if (bleProt->getFirstPayloadByte(data) != MSG_SUCCESS)
1983+
{
1984+
qWarning() << "Set serial number to: " << serialNum << " failed";
1985+
cb(false);
1986+
return false;
1987+
}
1988+
cb(true);
1989+
return true;
1990+
}));
1991+
mpDev->enqueueAndRunJob(jobs);
1992+
}
1993+
19631994
Common::SubdomainSelection MPDeviceBleImpl::getForceSubdomainSelection() const
19641995
{
19651996
QSettings s;

src/MPDeviceBleImpl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class MPDeviceBleImpl: public QObject
2727
QT_WRITABLE_PROPERTY(bool, bluetoothEnabled, false)
2828
QT_WRITABLE_PROPERTY(bool, knockDisabled, false)
2929
QT_WRITABLE_PROPERTY(bool, chargingStatus, false)
30+
QT_WRITABLE_PROPERTY(quint32, platformSerialNumber, 0)
3031

3132
enum UserSettingsMask : quint8
3233
{
@@ -177,6 +178,8 @@ class MPDeviceBleImpl: public QObject
177178
void getBleName(const MessageHandlerCbData &cb);
178179
QString getBleNameFromArray(const QByteArray& arr) const;
179180

181+
void setSerialNumber(quint32 serialNum, std::function<void(bool)> cb);
182+
180183
Common::SubdomainSelection getForceSubdomainSelection() const;
181184

182185
signals:
@@ -280,6 +283,7 @@ public slots:
280283
static constexpr int FORCE_SUBDOMAIN_BUNDLE_VERSION = 8;
281284
static constexpr int SET_BLE_NAME_BUNDLE_VERSION = 9;
282285
static constexpr int POINTED_TO_ADDR_SIZE = 2;
286+
static constexpr int PLATFORM_SERIAL_NUM_FIRST_BYTE = 16;
283287
const QByteArray DEFAULT_BUNDLE_PASSWORD = "\x63\x44\x31\x91\x3a\xfd\x23\xff\xb3\xac\x93\x69\x22\x5b\xf3\xc0";
284288
const QString DEFAULT_BLE_NAME = "Mooltipass Mini BLE";
285289
};

src/MainWindow.cpp

Lines changed: 106 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const QString MainWindow::MANUAL_STRING = "<a href=\"%1\">" + tr("User Manual")
4141
const QString MainWindow::BLE_MANUAL_URL = "https://raw.githubusercontent.com/mooltipass/minible/master/MooltipassMiniBLEUserManual.pdf";
4242
const QString MainWindow::MINI_MANUAL_URL = "https://raw.githubusercontent.com/limpkin/mooltipass/master/user_manual_mini.pdf";
4343
const QString MainWindow::BUNDLE_OUTDATED_TEXT = tr("New bundle update available <a href=\"https://www.themooltipass.com/updates/index.php?sn=%1&bundlev=%2\">here.</a>");
44+
const QString MainWindow::SERIAL_STR_START = "MOOLTIP";
4445

4546
void MainWindow::initHelpLabels()
4647
{
@@ -130,6 +131,11 @@ MainWindow::MainWindow(WSClient *client, DbMasterController *mc, QWidget *parent
130131
ui->labelAboutAuxMCU->setText(tr("Aux MCU version:"));
131132
ui->labelAboutMainMCU->setText(tr("Main MCU version:"));
132133

134+
ui->widgetNotFlashedWarning->hide();
135+
ui->labelNotFlashedWarningIcon->setPixmap(AppGui::qtAwesome()->icon(fa::warning).pixmap(QSize(20, 20)));
136+
ui->labelSerialNumberIncorrect->setStyleSheet("QLabel {color: blue;}");
137+
connect(ui->labelSerialNumberIncorrect, &ClickableLabel::clicked, this, &MainWindow::onIncorrectSerialNumberClicked);
138+
133139
ui->pbBleBattery->setStyleSheet("border: 1px solid black");
134140
ui->pbBleBattery->hide();
135141

@@ -484,6 +490,7 @@ MainWindow::MainWindow(WSClient *client, DbMasterController *mc, QWidget *parent
484490
connect(wsClient, &WSClient::fwVersionChanged, this, &MainWindow::updateSerialInfos);
485491
connect(wsClient, &WSClient::hwSerialChanged, this, &MainWindow::updateSerialInfos);
486492
connect(wsClient, &WSClient::hwMemoryChanged, this, &MainWindow::updateSerialInfos);
493+
connect(wsClient, &WSClient::platformSerialChanged, this, &MainWindow::updateSerialInfos);
487494
connect(wsClient, &WSClient::bundleVersionChanged, this, &MainWindow::displayBundleVersion);
488495
connect(wsClient, &WSClient::bundleVersionChanged, this, &MainWindow::sendRequestNotes);
489496
connect(wsClient, &WSClient::bundleVersionChanged, this, &MainWindow::onBundleVersionChanged);
@@ -628,6 +635,8 @@ MainWindow::MainWindow(WSClient *client, DbMasterController *mc, QWidget *parent
628635

629636
connect(wsClient, &WSClient::bleNameChanged, this, &MainWindow::onBleNameChanged);
630637

638+
connect(wsClient, &WSClient::serialNumberChanged, this, &MainWindow::onSerialNumberChanged);
639+
631640
wsClient->settingsHelper()->setMainWindow(this);
632641
#ifdef Q_OS_WIN
633642
const auto keyboardLayoutWidth = 150;
@@ -957,14 +966,24 @@ void MainWindow::updateSerialInfos() {
957966
if(connected)
958967
{
959968
ui->labelAboutFwVersValue->setText(wsClient->get_fwVersion());
960-
ui->labelAbouHwSerialValue->setText(wsClient->get_hwSerial() > 0 ? QString::number(wsClient->get_hwSerial()) : NONE_STRING);
969+
auto serialNum = QString::number(wsClient->get_hwSerial());
970+
ui->labelAbouHwSerialValue->setText(wsClient->get_hwSerial() > 0 ? serialNum : NONE_STRING);
961971
ui->labelAbouHwMemoryValue->setText(wsClient->get_hwMemory() > 0 ? tr("%1Mb").arg(wsClient->get_hwMemory()): NONE_STRING);
962972
displayMCUVersion(wsClient->isMPBLE());
963973
//When ble is detected not displaying fw version
964974
ui->labelAboutFwVers->setVisible(!wsClient->isMPBLE());
965975
ui->labelAboutFwVersValue->setVisible(!wsClient->isMPBLE());
966976
ui->label_UserManual->setText(MANUAL_STRING.arg(wsClient->isMPBLE() ? BLE_MANUAL_URL : MINI_MANUAL_URL));
967977
ui->label_UserManual->show();
978+
if (wsClient->isMPBLE() && serialNum > STARTING_NOT_FLASHED_SERIAL &&
979+
wsClient->get_hwSerial() != wsClient->get_platformSerial())
980+
{
981+
ui->widgetNotFlashedWarning->show();
982+
}
983+
else
984+
{
985+
ui->widgetNotFlashedWarning->hide();
986+
}
968987
}
969988
else
970989
{
@@ -977,6 +996,7 @@ void MainWindow::updateSerialInfos() {
977996
wsClient->set_auxMCUVersion(NONE_STRING);
978997
wsClient->set_mainMCUVersion(NONE_STRING);
979998
wsClient->set_bundleVersion(0);
999+
wsClient->set_platformSerial(0);
9801000
ui->label_UserManual->hide();
9811001
}
9821002
}
@@ -1923,6 +1943,46 @@ void MainWindow::fillInitialCurrentCategories()
19231943
ui->comboBoxBleCurrentCategory->blockSignals(false);
19241944
}
19251945

1946+
bool MainWindow::validateSerialString(const QString &serialStr, uint &serialNum)
1947+
{
1948+
/*
1949+
* Correct serial string: MOOLTIPXXXXY,
1950+
* XXXX is the new serial number
1951+
* Y is a char which is 'A' + (XXXX)%26
1952+
*/
1953+
1954+
const int serialStartSize = SERIAL_STR_START.size();
1955+
const int serialStringSize = serialStartSize + SERIAL_NUM_LENGTH + 1;
1956+
if (serialStr.size() != serialStringSize)
1957+
{
1958+
qCritical() << "Serial string has an incorrect size";
1959+
return false;
1960+
}
1961+
1962+
if (!serialStr.startsWith(SERIAL_STR_START))
1963+
{
1964+
qCritical() << "Serial string is not started with " << SERIAL_STR_START;
1965+
return false;
1966+
}
1967+
QString serialPart = serialStr.mid(serialStartSize, SERIAL_NUM_LENGTH);
1968+
bool ok = false;
1969+
serialNum = serialPart.toUInt(&ok);
1970+
if (!ok)
1971+
{
1972+
qCritical() << "Serial number part is not a number";
1973+
return false;
1974+
}
1975+
1976+
int hash = serialStr.toStdString()[serialStringSize - 1] - 'A';
1977+
if (hash != serialNum % Common::ALPHABET_SIZE)
1978+
{
1979+
serialNum = 0;
1980+
qCritical() << "Incorrect hash in serial string";
1981+
return false;
1982+
}
1983+
return true;
1984+
}
1985+
19261986
void MainWindow::on_toolButton_clearBackupFilePath_released()
19271987
{
19281988
ui->lineEdit_dbBackupFilePath->clear();
@@ -2405,3 +2465,48 @@ void MainWindow::onBleNameChanged(const QString &name)
24052465
ui->lineEditBleName->setText(name);
24062466
checkSettingsChanged();
24072467
}
2468+
2469+
void MainWindow::onIncorrectSerialNumberClicked()
2470+
{
2471+
bool ok = false;
2472+
QString serialNumStr = QInputDialog::getText(this, tr("Incorrect Serial Number"),
2473+
tr("It looks like your device serial number doesn't match the one present on your device's case.\n") +
2474+
tr("Please reach out to support@themooltipass.com for the right code to enter below"),
2475+
QLineEdit::Normal, "", &ok);
2476+
if (ok)
2477+
{
2478+
uint serialNum = 0;
2479+
if (validateSerialString(serialNumStr, serialNum))
2480+
{
2481+
wsClient->sendSetSerialNumber(serialNum);
2482+
}
2483+
else
2484+
{
2485+
qCritical() << "The entered serial number is incorrect: " << serialNumStr;
2486+
QMessageBox::critical(this, tr("Incorrect Serial Number"),
2487+
tr("The entered serial number is incorrect!"));
2488+
}
2489+
}
2490+
}
2491+
2492+
void MainWindow::onSerialNumberChanged(bool success, int serialNumber)
2493+
{
2494+
auto title = tr("Serial number change");
2495+
if (success)
2496+
{
2497+
wsClient->set_hwSerial(serialNumber);
2498+
if (wsClient->get_hwSerial() == wsClient->get_platformSerial())
2499+
{
2500+
QMessageBox::information(this, title, tr("Set serial number successfully."));
2501+
ui->widgetNotFlashedWarning->hide();
2502+
}
2503+
else
2504+
{
2505+
QMessageBox::critical(this, title, tr("Serial number still does not match platform serial."));
2506+
}
2507+
}
2508+
else
2509+
{
2510+
QMessageBox::critical(this, title, tr("Set serial number failed."));
2511+
}
2512+
}

src/MainWindow.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,10 @@ private slots:
211211

212212
void onBleNameChanged(const QString& name);
213213

214+
void onIncorrectSerialNumberClicked();
215+
216+
void onSerialNumberChanged(bool success, int serialNumber);
217+
214218
protected:
215219
virtual void keyPressEvent(QKeyEvent *event) override;
216220
virtual void keyReleaseEvent(QKeyEvent *event) override;
@@ -256,6 +260,8 @@ private slots:
256260

257261
void fillInitialCurrentCategories();
258262

263+
bool validateSerialString(const QString& serialStr, uint& serialNum);
264+
259265
Ui::MainWindow *ui = nullptr;
260266
QtAwesome* awesome;
261267

@@ -319,9 +325,12 @@ private slots:
319325
static const QString BLE_MANUAL_URL;
320326
static const QString MINI_MANUAL_URL;
321327
static const QString BUNDLE_OUTDATED_TEXT;
328+
static const QString SERIAL_STR_START;
329+
static constexpr int SERIAL_NUM_LENGTH = 4;
322330
#ifdef Q_OS_MAC
323331
static constexpr int MAC_DEFAULT_HEIGHT = 500;
324332
#endif
333+
static constexpr int STARTING_NOT_FLASHED_SERIAL = 2000;
325334
};
326335

327336
#endif // MAINWINDOW_H

0 commit comments

Comments
 (0)