static int M24SR_ProcessNDEFMessage()

in WiFiConfigurationViaNfc/src/M24SR/M24SR.c [413:582]


static int M24SR_ProcessNDEFMessage(uint8_t* buffer, uint16_t length, struct M24SR_WifiConfig *wifiConfig)
{
	buffer += 2;	// Bytes 0+1 = length of full Message.
	unsigned int idLengthOffset = 0;

	struct NDEFMSGHDR* pHdr = (struct NDEFMSGHDR*)buffer;

	// pull out bit fields
	bool mb = (pHdr->tnf & 0x80) != 0;
	bool me = (pHdr->tnf & 0x40) != 0;
	bool cf = (pHdr->tnf & 0x20) != 0;
	bool sr = (pHdr->tnf & 0x10) != 0;
	bool il = (pHdr->tnf & 0x8) != 0;
	uint8_t tnf = (pHdr->tnf & 0x7);

	if (mb && me)	// only one record.
	{
		Log_Debug("One NDEF Record\n");
	}
	else
	{
		Log_Debug("Error: Only single NDEF record supported.\n");
		return -1;
	}

	if (sr)
	{
		Log_Debug("Short Record <= 255 bytes\n");
	}
	else
	{
		Log_Debug("ERROR: Only short NDEF records are supported\n");
		return -1;
	}

	if (il)
	{
		Log_Debug("Record contains ID Length\n");
		idLengthOffset = 1;
	}

	if (tnf & 0x02)
	{
		Log_Debug("Record contains MIME type\n");
	}
	else
	{
		Log_Debug("ERROR: Only MIME type is supported\n");
		return -1;
	}

	if (!cf)
	{
		Log_Debug("Record is not chunked\n");
	}
	else
	{
		Log_Debug("ERROR: Chunked record not supported\n");
		return -1;
	}

	Log_Debug("Type Length %d (0x%02x)\n", pHdr->typeLength, pHdr->typeLength);
	Log_Debug("Payload Length %d (0x%02x)\n", pHdr->payloadLength, pHdr->payloadLength);
	Log_Debug("ID Length %d (0x%02x)\n", idLengthOffset, idLengthOffset);

	if (strncmp("application/vnd.wfa.wsc", &buffer[sizeof(NDEFMSGHDR) + idLengthOffset], pHdr->typeLength) == 0)
	{
		Log_Debug("WiFi MIME type confirmed\n");
	}
	else
	{
		Log_Debug("ERROR: Not WiFi NDEF Record\n");
		return -1;
	}

#ifdef ENABLE_VERBOSE_DEBUG_OUTPUT
	Log_Debug("NDEF Message Payload:\n");
	DumpBuffer(&buffer[sizeof(NDEFMSGHDR) + pHdr->typeLength], pHdr->payloadLength);
#endif

	// Now walk the NDEF Record tags.
	// three are needed...
	// 0x1045 SSID
	// 0x1027 Network Key
	// 0x1003 Authentication Type(needs to map to Azure Sphere types)

	uint8_t* ptr = &buffer[sizeof(NDEFMSGHDR) + idLengthOffset + pHdr->typeLength + 1];	// point to first record.
	size_t bufferOffset = 0;		// offset into the NDEFMSGHDR buffer.

	uint16_t content16t = 0;

	bool haveSSID = false;
	bool haveAUTHTYPE = false;
	bool haveNETWORKKEY = false;

	wifiConfig->wifiConfigSecurityType = WifiConfig_Security_Open;
	memset(wifiConfig->networkKeyString, 0x00, 32);
	memset(wifiConfig->ssidString, 0x00, 32);

	struct NDEFRECORD ndefRecord;

	while (bufferOffset <= (size_t)pHdr->payloadLength)
	{
		struct NDEFRECORD* pRecord = (struct NDEFRECORD*)&ptr[bufferOffset];
		SwapNDEFRecordItems(pRecord, &ndefRecord);
		bufferOffset += sizeof(NDEFRECORD);		// skip past type and length.

		Log_Debug("recordType: 0x%02x\n", ndefRecord.recordType);

		// Records are defined as 2 byte ID, 2 byte size, then content
		switch (ndefRecord.recordType) {
		case WIFI_CREDENTIAL:		// skip
			Log_Debug("WIFI_CREDENTIAL\n");
			break;
		case WIFI_NETWORKINDEX:		// skip size and content
			Log_Debug("WIFI_NETWORKINDEX\n");
			bufferOffset += ndefRecord.recordLength;
			break;
		case WIFI_SSID:
			Log_Debug("SSID\n");
			if (ndefRecord.recordLength > 0)
			{
				haveSSID = true;
				memcpy(wifiConfig->ssidString, &ptr[bufferOffset], ndefRecord.recordLength);
				bufferOffset += ndefRecord.recordLength;
			}
			break;
		case WIFI_AUTHTYPE:			// two bytes
			Log_Debug("AUTHTYPE\n");
			content16t= (uint16_t)((ptr[bufferOffset] << 8) + (ptr[bufferOffset + 1] & 0x00ff));
			bufferOffset += 2;

			wifiConfig->wifiConfigSecurityType=MapAuthType(content16t);

			Log_Debug("AuthType: 0x%02x\n", wifiConfig->wifiConfigSecurityType);
			haveAUTHTYPE = true;
			break;
		case WIFI_ENCRYPTIONTYPE:
			Log_Debug("WIFI_ENCRYPTIONTYPE\n");
			bufferOffset += ndefRecord.recordLength;
			break;
		case WIFI_NETWORKKEY:
			Log_Debug("WIFI_NETWORKKEY\n");

			if (ndefRecord.recordLength > 0)
			{
				haveNETWORKKEY = true;
				memcpy(wifiConfig->networkKeyString, &ptr[bufferOffset], ndefRecord.recordLength);
				bufferOffset += ndefRecord.recordLength;
			}
			break;
		case WIFI_MACADDRESS:
			bufferOffset += ndefRecord.recordLength;
			break;
		default:
			break;
		}
	}

	if (!haveSSID || !haveAUTHTYPE || !haveNETWORKKEY)
	{
		Log_Debug("Error: missing ssid, auth type, or network key\n");
		return -1;
	}

	Log_Debug("SSID       : %s\n",wifiConfig->ssidString);
	Log_Debug("Network Key: %s\n", wifiConfig->networkKeyString);

	return 0;
}