Extend qChecksum calculation

ISO 14443-3 is for nfc communication and uses 2 different checksums.
The existing one is from ISO 3309 and the other one is from ITU-V.41.
Both are needed to implement an own transport layer defined in ISO
14443-4 to allow nfc commands with a length above 250 byte independent
from the smartphone.

This change will avoid code duplication in QNearFieldTarget.
The private function qNfcChecksum is a copy of qChecksum.

Change-Id: I790ffec8e2ea46f88b2db6f48b64fdcb140e7b70
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Lars Schmertmann 2016-12-18 21:15:10 +01:00 committed by Lars Schmertmann
parent 615027129d
commit 5882866768
5 changed files with 85 additions and 6 deletions

View File

@ -1656,6 +1656,11 @@ public:
};
Q_DECLARE_FLAGS(MouseEventFlags, MouseEventFlag)
enum ChecksumType {
ChecksumIso3309,
ChecksumItuV41
};
#ifndef Q_QDOC
// NOTE: Generally, do not add QT_Q_ENUM if a corresponding Q_Q_FLAG exists.
QT_Q_ENUM(ScrollBarPolicy)
@ -1740,6 +1745,7 @@ public:
QT_Q_ENUM(ScrollPhase)
QT_Q_ENUM(MouseEventSource)
QT_Q_FLAG(MouseEventFlag)
QT_Q_ENUM(ChecksumType)
QT_Q_ENUM(TabFocusBehavior)
#endif // Q_DOC

View File

@ -3158,3 +3158,14 @@
\omitvalue MouseEventFlagMask
*/
/*!
\enum Qt::ChecksumType
\since 5.9
This enum describes the possible standards used by qChecksum().
\value ChecksumIso3309 Checksum calculation based on ISO 3309.
\value ChecksumItuV41 Checksum calculation based on ITU-V.41.
*/

View File

@ -541,15 +541,40 @@ static const quint16 crc_tbl[16] = {
Returns the CRC-16 checksum of the first \a len bytes of \a data.
The checksum is independent of the byte order (endianness).
The checksum is independent of the byte order (endianness) and will be
calculated accorded to the algorithm published in ISO 3309 (Qt::ChecksumIso3309).
\note This function is a 16-bit cache conserving (16 entry table)
implementation of the CRC-16-CCITT algorithm.
*/
quint16 qChecksum(const char *data, uint len)
{
quint16 crc = 0xffff;
return qChecksum(data, len, Qt::ChecksumIso3309);
}
/*!
\relates QByteArray
\since 5.9
Returns the CRC-16 checksum of the first \a len bytes of \a data.
The checksum is independent of the byte order (endianness) and will
be calculated accorded to the algorithm published in \a standard.
\note This function is a 16-bit cache conserving (16 entry table)
implementation of the CRC-16-CCITT algorithm.
*/
quint16 qChecksum(const char *data, uint len, Qt::ChecksumType standard)
{
quint16 crc = 0x0000;
switch (standard) {
case Qt::ChecksumIso3309:
crc = 0xffff;
break;
case Qt::ChecksumItuV41:
crc = 0x6363;
break;
}
uchar c;
const uchar *p = reinterpret_cast<const uchar *>(data);
while (len--) {
@ -558,7 +583,14 @@ quint16 qChecksum(const char *data, uint len)
c >>= 4;
crc = ((crc >> 4) & 0x0fff) ^ crc_tbl[((crc ^ c) & 15)];
}
return ~crc & 0xffff;
switch (standard) {
case Qt::ChecksumIso3309:
crc = ~crc;
break;
case Qt::ChecksumItuV41:
break;
}
return crc & 0xffff;
}
/*!

View File

@ -105,8 +105,8 @@ Q_CORE_EXPORT int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap);
Q_CORE_EXPORT int qsnprintf(char *str, size_t n, const char *fmt, ...);
// qChecksum: Internet checksum
Q_CORE_EXPORT quint16 qChecksum(const char *s, uint len);
Q_CORE_EXPORT quint16 qChecksum(const char *s, uint len); // ### Qt 6: Remove
Q_CORE_EXPORT quint16 qChecksum(const char *s, uint len, Qt::ChecksumType standard); // ### Qt 6: Use Qt::ChecksumType standard = Qt::ChecksumIso3309
class QByteRef;
class QString;

View File

@ -43,6 +43,8 @@ public:
tst_QByteArray();
private slots:
void swap();
void qChecksum_data();
void qChecksum();
void qCompress_data();
#ifndef QT_NO_COMPRESS
void qCompress();
@ -239,6 +241,34 @@ tst_QByteArray::tst_QByteArray()
{
}
void tst_QByteArray::qChecksum_data()
{
QTest::addColumn<QByteArray>("data");
QTest::addColumn<uint>("len");
QTest::addColumn<Qt::ChecksumType>("standard");
QTest::addColumn<uint>("checksum");
// Examples from ISO 14443-3
QTest::newRow("1") << QByteArray("\x00\x00") << 2U << Qt::ChecksumItuV41 << 0x1EA0U;
QTest::newRow("2") << QByteArray("\x12\x34") << 2U << Qt::ChecksumItuV41 << 0xCF26U;
QTest::newRow("3") << QByteArray("\x00\x00\x00") << 3U << Qt::ChecksumIso3309 << 0xC6CCU;
QTest::newRow("4") << QByteArray("\x0F\xAA\xFF") << 3U << Qt::ChecksumIso3309 << 0xD1FCU;
QTest::newRow("5") << QByteArray("\x0A\x12\x34\x56") << 4U << Qt::ChecksumIso3309 << 0xF62CU;
}
void tst_QByteArray::qChecksum()
{
QFETCH(QByteArray, data);
QFETCH(uint, len);
QFETCH(Qt::ChecksumType, standard);
QFETCH(uint, checksum);
if (standard == Qt::ChecksumIso3309) {
QCOMPARE(::qChecksum(data.constData(), len), static_cast<quint16>(checksum));
}
QCOMPARE(::qChecksum(data.constData(), len, standard), static_cast<quint16>(checksum));
}
void tst_QByteArray::qCompress_data()
{
QTest::addColumn<QByteArray>("ba");