Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement administrator commissioning cluster #8680

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions examples/all-clusters-app/all-clusters-common/all-clusters-app.zap
Original file line number Diff line number Diff line change
Expand Up @@ -3215,6 +3215,83 @@
}
]
},
{
"name": "AdministratorCommissioning",
"code": 60,
"mfgCode": null,
"define": "ADMINISTRATOR_COMMISSIONING_CLUSTER",
"side": "client",
"enabled": 0,
"commands": [
{
"name": "OpenCommissioningWindow",
"code": 0,
"mfgCode": null,
"source": "client",
"incoming": 1,
"outgoing": 1
},
{
"name": "OpenBasicCommissioningWindow",
"code": 1,
"mfgCode": null,
"source": "client",
"incoming": 1,
"outgoing": 1
},
{
"name": "RevokeCommissioning",
"code": 2,
"mfgCode": null,
"source": "client",
"incoming": 1,
"outgoing": 1
}
],
"attributes": [
{
"name": "cluster revision",
"code": 65533,
"mfgCode": null,
"side": "client",
"included": 1,
"storageOption": "RAM",
"singleton": 0,
"bounded": 0,
"defaultValue": "0x0001",
"reportable": 0,
"minInterval": 0,
"maxInterval": 65344,
"reportableChange": 0
}
]
},
{
"name": "AdministratorCommissioning",
"code": 60,
"mfgCode": null,
"define": "ADMINISTRATOR_COMMISSIONING_CLUSTER",
"side": "server",
"enabled": 1,
"commands": [],
"attributes": [
{
"name": "cluster revision",
"code": 65533,
"mfgCode": null,
"side": "server",
"included": 1,
"storageOption": "RAM",
"singleton": 0,
"bounded": 0,
"defaultValue": "0x0001",
"reportable": 0,
"minInterval": 0,
"maxInterval": 65344,
"reportableChange": 0
}
]
},
{
"name": "Operational Credentials",
"code": 62,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,203 @@ void ReportCommandUnsupported(Command * aCommandObj, EndpointId aEndpointId, Clu

namespace clusters {

namespace AdministratorCommissioning {

void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId,
TLV::TLVReader & aDataTlv)
{
// We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV
// When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error.
// Any error value TLVUnpackError means we have received an illegal value.
// The following variables are used for all commands to save code size.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
uint32_t validArgumentCount = 0;
uint32_t expectArgumentCount = 0;
uint32_t currentDecodeTagId = 0;
bool wasHandled = false;
{
switch (aCommandId)
{
case Clusters::AdministratorCommissioning::Commands::Ids::OpenBasicCommissioningWindow: {
expectArgumentCount = 1;
uint16_t CommissioningTimeout;
bool argExists[1];

memset(argExists, 0, sizeof argExists);

while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 1)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0:
TLVUnpackError = aDataTlv.Get(CommissioningTimeout);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}

if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}

if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount)
{
wasHandled = emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallback(aEndpointId, apCommandObj,
CommissioningTimeout);
}
break;
}
case Clusters::AdministratorCommissioning::Commands::Ids::OpenCommissioningWindow: {
expectArgumentCount = 6;
uint16_t CommissioningTimeout;
chip::ByteSpan PAKEVerifier;
uint16_t Discriminator;
uint32_t Iterations;
chip::ByteSpan Salt;
uint16_t PasscodeID;
bool argExists[6];

memset(argExists, 0, sizeof argExists);

while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
// Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element.
// Skip this element if it is not a ContextTag, not consider it as an error if other values are valid.
if (!TLV::IsContextTag(aDataTlv.GetTag()))
{
continue;
}
currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag());
if (currentDecodeTagId < 6)
{
if (argExists[currentDecodeTagId])
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
else
{
argExists[currentDecodeTagId] = true;
validArgumentCount++;
}
}
switch (currentDecodeTagId)
{
case 0:
TLVUnpackError = aDataTlv.Get(CommissioningTimeout);
break;
case 1: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
PAKEVerifier = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 2:
TLVUnpackError = aDataTlv.Get(Discriminator);
break;
case 3:
TLVUnpackError = aDataTlv.Get(Iterations);
break;
case 4: {
const uint8_t * data = nullptr;
TLVUnpackError = aDataTlv.GetDataPtr(data);
Salt = chip::ByteSpan(data, aDataTlv.GetLength());
}
break;
case 5:
TLVUnpackError = aDataTlv.Get(PasscodeID);
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (CHIP_NO_ERROR != TLVUnpackError)
{
break;
}
}

if (CHIP_END_OF_TLV == TLVError)
{
// CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error.
TLVError = CHIP_NO_ERROR;
}

if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 6 == validArgumentCount)
{
wasHandled = emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback(
aEndpointId, apCommandObj, CommissioningTimeout, PAKEVerifier, Discriminator, Iterations, Salt, PasscodeID);
}
break;
}
case Clusters::AdministratorCommissioning::Commands::Ids::RevokeCommissioning: {

wasHandled = emberAfAdministratorCommissioningClusterRevokeCommissioningCallback(aEndpointId, apCommandObj);
break;
}
default: {
// Unrecognized command ID, error status will apply.
ReportCommandUnsupported(apCommandObj, aEndpointId, Clusters::AdministratorCommissioning::Id, aCommandId);
return;
}
}
}

if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
{
chip::app::CommandPathParams returnStatusParam = { aEndpointId,
0, // GroupId
Clusters::AdministratorCommissioning::Id, aCommandId,
(chip::app::CommandPathFlags::kEndpointIdValid) };
apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
ChipLogProgress(Zcl,
"Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" CHIP_ERROR_FORMAT
", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32,
validArgumentCount, expectArgumentCount, ChipError::FormatError(TLVError),
ChipError::FormatError(TLVUnpackError), currentDecodeTagId);
// A command with no arguments would never write currentDecodeTagId. If
// progress logging is also disabled, it would look unused. Silence that
// warning.
UNUSED_VAR(currentDecodeTagId);
}
}

} // namespace AdministratorCommissioning

namespace BarrierControl {

void DispatchServerCommand(app::CommandHandler * apCommandObj, CommandId aCommandId, EndpointId aEndpointId,
Expand Down Expand Up @@ -7033,6 +7230,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC
SuccessOrExit(aReader.EnterContainer(dataTlvType));
switch (aClusterId)
{
case Clusters::AdministratorCommissioning::Id:
clusters::AdministratorCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case Clusters::BarrierControl::Id:
clusters::BarrierControl::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId)
case ZCL_ACCOUNT_LOGIN_CLUSTER_ID:
emberAfAccountLoginClusterInitCallback(endpoint);
break;
case ZCL_ADMINISTRATOR_COMMISSIONING_CLUSTER_ID:
emberAfAdministratorCommissioningClusterInitCallback(endpoint);
break;
case ZCL_APPLICATION_BASIC_CLUSTER_ID:
emberAfApplicationBasicClusterInitCallback(endpoint);
break;
Expand Down Expand Up @@ -186,6 +189,11 @@ void __attribute__((weak)) emberAfAccountLoginClusterInitCallback(EndpointId end
// To prevent warning
(void) endpoint;
}
void __attribute__((weak)) emberAfAdministratorCommissioningClusterInitCallback(EndpointId endpoint)
{
// To prevent warning
(void) endpoint;
}
void __attribute__((weak)) emberAfApplicationBasicClusterInitCallback(EndpointId endpoint)
{
// To prevent warning
Expand Down
Loading