+ if (!track2)
+ return NULL;
+
+ for (int i = 0; i < track2->len; ++i, tmp += 2)
+ sprintf(tmp, "%02x", (unsigned int)track2->value[i]);
+
+ int posD = strchr(track2Hex, 'd') - track2Hex;
+ if (posD < 1)
+ return NULL;
+
+ track2Hex[posD] = 0;
+ if (strlen(track2Hex) % 2) {
+ track2Hex[posD] = 'F';
+ track2Hex[posD + 1] = '\0';
+ }
+
+ param_gethex_to_eol(track2Hex, 0, PAN, sizeof(PAN), &PANlen);
+
+ return tlvdb_fixed(0x5a, PANlen, PAN);
+}
+
+struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2) {
+ char track2Hex[200] = {0};
+ char dCVVHex[100] = {0};
+ uint8_t dCVV[100] = {0};
+ int dCVVlen = 0;
+ const int PINlen = 5; // must calculated from 9F67 MSD Offset but i have not seen this tag)
+ char *tmp = track2Hex;
+
+ if (!track2)
+ return NULL;
+
+ for (int i = 0; i < track2->len; ++i, tmp += 2)
+ sprintf(tmp, "%02x", (unsigned int)track2->value[i]);
+
+ int posD = strchr(track2Hex, 'd') - track2Hex;
+ if (posD < 1)
+ return NULL;
+
+ memset(dCVVHex, '0', 32);
+ // ATC
+ memcpy(dCVVHex + 0, track2Hex + posD + PINlen + 11, 4);
+ // PAN 5 hex
+ memcpy(dCVVHex + 4, track2Hex, 5);
+ // expire date
+ memcpy(dCVVHex + 9, track2Hex + posD + 1, 4);
+ // service code
+ memcpy(dCVVHex + 13, track2Hex + posD + 5, 3);
+
+ param_gethex_to_eol(dCVVHex, 0, dCVV, sizeof(dCVV), &dCVVlen);
+
+ return tlvdb_fixed(0x02, dCVVlen, dCVV);
+}
+
+int EMVExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) {