-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement a QRCode payload generator
- Loading branch information
1 parent
34e2b26
commit efc466f
Showing
8 changed files
with
543 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
TOP_DIR = ../.. | ||
Test_Dir = tests | ||
|
||
.PHONY: all clean run_tests | ||
|
||
all: run_tests | ||
|
||
include $(TOP_DIR)/.yams/cpp_rules.min | ||
|
||
Module_Includes = \ | ||
-I. \ | ||
-I$(TOP_DIR)/src/include \ | ||
-I$(TOP_DIR)/src/lib/ \ | ||
-I$(TOP_DIR)/build/config/standalone/ | ||
|
||
Module_Test_Includes = $(Module_Includes) | ||
|
||
CPP_Files = \ | ||
SetupCodeUtils.cpp \ | ||
SetupPayloadGenerator.cpp \ | ||
|
||
libqr.a: $(CPP_Objects) | ||
ar rvs $@ $^ | ||
@echo "LINK => $@" | ||
|
||
clean: my_clean | ||
@rm -f $(LIB_NAME) *.gcda *.gcno *.gcov | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/* | ||
* | ||
* <COPYRIGHT> | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
/** | ||
* @file | ||
* This file implements converting an input into a Base45 String | ||
* | ||
*/ | ||
|
||
#include "SetupCodeUtils.h" | ||
|
||
#include <map> | ||
#include <string> | ||
|
||
using namespace std; | ||
|
||
namespace chip { | ||
|
||
map <int, char> base45CharacterMap() | ||
{ | ||
map <int, char> characterMap; | ||
// Special characters | ||
characterMap[36] = ' '; | ||
characterMap[37] = '$'; | ||
characterMap[38] = '%'; | ||
characterMap[39] = '*'; | ||
characterMap[40] = '+'; | ||
characterMap[41] = '-'; | ||
characterMap[42] = '.'; | ||
characterMap[43] = '/'; | ||
characterMap[44] = ':'; | ||
|
||
return characterMap; | ||
} | ||
|
||
string base45EncodedString(uint64_t input, size_t minLength) | ||
{ | ||
static std::map<int, char> BS45_CHARS = base45CharacterMap(); | ||
string result; | ||
int radix = 45; | ||
do { | ||
int remainder = input % radix; | ||
char base45char; | ||
if (remainder >= 0 && remainder <= 9) { | ||
// Numbers | ||
base45char = '0' + remainder; | ||
} | ||
else if (remainder >= 10 && remainder <= 35) { | ||
// Uppercase Characters | ||
base45char = 'A' + (remainder - 10); | ||
} | ||
else { | ||
// Special Characters | ||
base45char = BS45_CHARS[remainder]; | ||
} | ||
result += base45char; | ||
input = input / radix; | ||
} while (input != 0); | ||
|
||
while (result.length() < minLength) { | ||
result.append("0"); | ||
} | ||
|
||
reverse(result.begin(), result.end()); | ||
return result; | ||
} | ||
|
||
} // namespace chip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* | ||
* | ||
* <COPYRIGHT> | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
/** | ||
* @file | ||
* Utility header to encode an input into a Base45 String | ||
*/ | ||
|
||
#ifndef _SETUP_CODE_UTILS_H_ | ||
#define _SETUP_CODE_UTILS_H_ | ||
|
||
#include <string> | ||
|
||
using namespace std; | ||
|
||
namespace chip { | ||
|
||
std::string base45EncodedString(uint64_t input, size_t minLength); | ||
|
||
} // namespace chip | ||
|
||
#endif /* _SETUP_CODE_UTILS_H_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* | ||
* | ||
* <COPYRIGHT> | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
/** | ||
* @file | ||
* This file describes a QRCode Setup Payload class to hold | ||
* data enumerated from a byte stream | ||
*/ | ||
|
||
|
||
#ifndef _SETUP_PAYLOAD_H_ | ||
#define _SETUP_PAYLOAD_H_ | ||
|
||
#include <stdint.h> | ||
|
||
namespace chip { | ||
|
||
class SetupPayload | ||
{ | ||
public: | ||
uint8_t version; | ||
uint16_t vendorID; | ||
uint16_t productID; | ||
uint8_t requiresCustomFlow; | ||
uint16_t rendezvousInformation; | ||
uint16_t discriminator; | ||
uint32_t setUpPINCode; | ||
}; | ||
|
||
}; // namespace chip | ||
|
||
#endif /* _SETUP_PAYLOAD_H_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
/* | ||
* | ||
* <COPYRIGHT> | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
/** | ||
* @file | ||
* This file implements a QRCode Setup Payload generator in accordance | ||
* with the CHIP specification. | ||
* | ||
*/ | ||
|
||
#include "SetupPayloadGenerator.h" | ||
#include "SetupCodeUtils.h" | ||
|
||
#include <iostream> | ||
#include <vector> | ||
|
||
using namespace chip; | ||
using namespace std; | ||
|
||
void SetupPayloadGenerator::resetBitSet() | ||
{ | ||
mPayloadBitsIndex = kTotalPayloadDataSizeInBits; | ||
mPayloadBits.reset(); | ||
} | ||
|
||
// Populates numberOfBits starting from LSB of input into mPayloadBits | ||
void SetupPayloadGenerator::populateInteger(uint64_t input, size_t numberOfBits) | ||
{ | ||
int numberOfBitsModified = 0; | ||
|
||
mPayloadBitsIndex -= numberOfBits; | ||
int currentIndex = mPayloadBitsIndex; | ||
|
||
int endIndex = currentIndex + (numberOfBits - 1); | ||
|
||
int itercount = 1; | ||
while (currentIndex <= endIndex) { | ||
itercount++; | ||
input & 1 ? mPayloadBits.set(currentIndex) : mPayloadBits.reset(currentIndex); | ||
currentIndex++; | ||
input /= 2; | ||
} | ||
} | ||
|
||
void SetupPayloadGenerator::populateVersion() | ||
{ | ||
populateInteger(mPayload.version, kVersionFieldLengthInBits); | ||
} | ||
|
||
void SetupPayloadGenerator::populateVendorID() | ||
{ | ||
populateInteger(mPayload.vendorID, kVendorIDFieldLengthInBits); | ||
} | ||
|
||
void SetupPayloadGenerator::populateProductID() | ||
{ | ||
populateInteger(mPayload.productID, kProductIDFieldLengthInBits); | ||
} | ||
|
||
void SetupPayloadGenerator::populateCustomFlowRequiredField() | ||
{ | ||
populateInteger(mPayload.requiresCustomFlow, kCustomFlowRequiredFieldLengthInBits); | ||
} | ||
|
||
void SetupPayloadGenerator::populateRendezVousInfo() | ||
{ | ||
populateInteger(mPayload.rendezvousInformation, kRendezvousInfoFieldLengthInBits); | ||
} | ||
|
||
void SetupPayloadGenerator::populateDiscriminator() | ||
{ | ||
populateInteger(mPayload.discriminator, kPayloadDiscriminatorFieldLengthInBits); | ||
} | ||
|
||
void SetupPayloadGenerator::populateSetupPIN() | ||
{ | ||
populateInteger(mPayload.setUpPINCode, kSetupPINCodeFieldLengthInBits); | ||
} | ||
|
||
void SetupPayloadGenerator::populateReservedField() | ||
{ | ||
populateInteger(0, kReservedFieldLengthInBits); | ||
} | ||
|
||
void SetupPayloadGenerator::generateBitSet() | ||
{ | ||
resetBitSet(); | ||
populateVersion(); | ||
populateVendorID(); | ||
populateProductID(); | ||
populateCustomFlowRequiredField(); | ||
populateRendezVousInfo(); | ||
populateDiscriminator(); | ||
populateSetupPIN(); | ||
populateReservedField(); | ||
} | ||
|
||
string SetupPayloadGenerator::payloadBinaryRepresentation() | ||
{ | ||
generateBitSet(); | ||
return mPayloadBits.to_string(); | ||
} | ||
|
||
// This function assumes bits.size() % 8 == 0 | ||
// TODO: Can this method be written in a more elegant way? | ||
vector<uint16_t> arrayFromBits(bitset<kTotalPayloadDataSizeInBits> bits) | ||
{ | ||
vector<uint16_t> resultVector; | ||
size_t numberOfBits = bits.size(); | ||
size_t numberOfBytes = numberOfBits / 8; | ||
bool oddNumOfBytes = (numberOfBytes % 2) ? true : false; | ||
|
||
// Traversing in reverse, hence startIndex > endIndex | ||
int endIndex = 0; | ||
int startIndex = bits.size() - 1; | ||
|
||
/* | ||
Every 2 bytes (16 bits) of binary source data are encoded to 3 characters of the Base-45 alphabet. | ||
If an odd number of bytes are to be encoded, the remaining single byte will be encoded | ||
to 2 characters of the Base-45 alphabet. | ||
*/ | ||
if (oddNumOfBytes) { | ||
endIndex = 8; | ||
} | ||
|
||
while (startIndex > endIndex) { | ||
int currentIntegerIndex = startIndex; | ||
uint16_t result = 0; | ||
for (int i = currentIntegerIndex; i > currentIntegerIndex - 16; i--) { | ||
result = result << 1; | ||
result = result | bits.test(i); | ||
} | ||
resultVector.push_back(result); | ||
startIndex -= 16; | ||
} | ||
|
||
// If we have odd number of bytes append the last byte. | ||
if (oddNumOfBytes) { | ||
uint16_t result = 0; | ||
for (int i = 7; i >= 0 ; i--) { | ||
result = result << 1; | ||
result = result & bits.test(i); | ||
} | ||
resultVector.push_back(result); | ||
} | ||
return resultVector; | ||
} | ||
|
||
string SetupPayloadGenerator::payloadBase45Representation() | ||
{ | ||
generateBitSet(); | ||
vector<uint16_t> integerArray = arrayFromBits(mPayloadBits); | ||
string result; | ||
for (int idx = 0; idx < integerArray.size(); idx++) { | ||
result += base45EncodedString(integerArray[idx], 3); | ||
} | ||
return result; | ||
} |
Oops, something went wrong.