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 Operational Credentials Cluster for initial Fabric support #6096

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
1 change: 1 addition & 0 deletions examples/all-clusters-app/all-clusters-common/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ chip_data_model("all-clusters-common") {
"media-playback-server",
"network-commissioning",
"on-off-server",
"operational-credentials",
"ota-server",
"scenes",
"target-navigator-server",
Expand Down
101 changes: 101 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 @@ -1420,6 +1420,107 @@
}
]
},
{
"name": "Operational Credentials",
"code": 62,
"mfgCode": null,
"define": "OPERATIONAL_CREDENTIALS_CLUSTER",
"side": "client",
"enabled": 0,
"commands": [
{
"name": "GetFabricId",
"code": 0,
"mfgCode": null,
"source": "client",
"incoming": 1,
"outgoing": 1
},
{
"name": "UpdateFabricLabel",
"code": 9,
"mfgCode": null,
"source": "client",
"incoming": 1,
"outgoing": 1
},
{
"name": "RemoveFabric",
"code": 10,
"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": "Operational Credentials",
"code": 62,
"mfgCode": null,
"define": "OPERATIONAL_CREDENTIALS_CLUSTER",
"side": "server",
"enabled": 1,
"commands": [
{
"name": "GetFabricIdResponse",
"code": 1,
"mfgCode": null,
"source": "server",
"incoming": 1,
"outgoing": 1
}
],
"attributes": [
{
"name": "fabrics list",
"code": 1,
"mfgCode": null,
"side": "server",
"included": 1,
"storageOption": "RAM",
"singleton": 0,
"bounded": 0,
"defaultValue": "",
"reportable": 0,
"minInterval": 0,
"maxInterval": 65344,
"reportableChange": 0
},
{
"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": "Door Lock",
"code": 257,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7013,6 +7013,200 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En

} // namespace OnOff

namespace OperationalCredentials {

void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
{
{
switch (aCommandId)
{
case ZCL_GET_FABRIC_ID_COMMAND_ID: {

// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
emberAfOperationalCredentialsClusterGetFabricIdCallback();
break;
}
case ZCL_REMOVE_FABRIC_COMMAND_ID: {
// 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.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
chip::FabricId FabricId;
bool FabricIdExists = false;
chip::NodeId NodeId;
bool NodeIdExists = false;
uint16_t VendorId;
bool VendorIdExists = false;
uint32_t validArgumentCount = 0;

while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
{
case 0:
if (FabricIdExists)
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
TLVUnpackError = aDataTlv.Get(FabricId);
if (CHIP_NO_ERROR == TLVUnpackError)
{
FabricIdExists = true;
validArgumentCount++;
}
break;
case 1:
if (NodeIdExists)
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
TLVUnpackError = aDataTlv.Get(NodeId);
if (CHIP_NO_ERROR == TLVUnpackError)
{
NodeIdExists = true;
validArgumentCount++;
}
break;
case 2:
if (VendorIdExists)
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
TLVUnpackError = aDataTlv.Get(VendorId);
if (CHIP_NO_ERROR == TLVUnpackError)
{
VendorIdExists = true;
validArgumentCount++;
}
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (TLVUnpackError != CHIP_NO_ERROR)
{
ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
}
else
{
ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
}

// TODO(#5590) We should encode a response of status code for invalid TLV.
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
emberAfOperationalCredentialsClusterRemoveFabricCallback(FabricId, NodeId, VendorId);
}
else
{
apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
ChipLogProgress(
Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
3, validArgumentCount, TLVError, TLVUnpackError);
}
break;
}
case ZCL_UPDATE_FABRIC_LABEL_COMMAND_ID: {
// 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.
CHIP_ERROR TLVError = CHIP_NO_ERROR;
CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR;
const uint8_t * Label;
bool LabelExists = false;
uint32_t validArgumentCount = 0;

while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR)
{
switch (TLV::TagNumFromTag(aDataTlv.GetTag()))
{
case 0:
if (LabelExists)
{
ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag()));
TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT;
break;
}
// TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
TLVUnpackError = aDataTlv.GetDataPtr(Label);
if (CHIP_NO_ERROR == TLVUnpackError)
{
LabelExists = true;
validArgumentCount++;
}
break;
default:
// Unsupported tag, ignore it.
ChipLogProgress(Zcl, "Unknown TLV tag during processing.");
break;
}
if (TLVUnpackError != CHIP_NO_ERROR)
{
ChipLogProgress(Zcl, "Failed to decode TLV data with tag %" PRIx32 ": %" PRId32,
TLV::TagNumFromTag(aDataTlv.GetTag()), 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;
}
else
{
ChipLogProgress(Zcl, "Failed to decode TLV data: %" PRId32, TLVError);
}

// TODO(#5590) We should encode a response of status code for invalid TLV.
if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 1 == validArgumentCount)
{
// TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks.
emberAfOperationalCredentialsClusterUpdateFabricLabelCallback(const_cast<uint8_t *>(Label));
}
else
{
apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kBadRequest,
Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
ChipLogProgress(
Zcl, "Failed to dispatch command, %d/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 ", UnpackError=%" PRIu32,
1, validArgumentCount, TLVError, TLVUnpackError);
}
break;
}
default: {
// Unrecognized command ID, error status will apply.
apCommandObj->AddStatusCode(nullptr, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
Protocols::SecureChannel::Id, Protocols::SecureChannel::kProtocolCodeGeneralFailure);
ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId,
ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID);
break;
}
}
}
}

} // namespace OperationalCredentials

namespace Scenes {

void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv)
Expand Down Expand Up @@ -7703,6 +7897,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC
case ZCL_ON_OFF_CLUSTER_ID:
clusters::OnOff::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_OPERATIONAL_CREDENTIALS_CLUSTER_ID:
clusters::OperationalCredentials::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
case ZCL_SCENES_CLUSTER_ID:
clusters::Scenes::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,15 @@ typedef struct _ExtendedDiscoverAttributesInfoRecord
uint8_t attributeAccessControl;
} EmberAfExtendedDiscoverAttributesInfoRecord;

// Struct for FabricDescriptor
typedef struct _FabricDescriptor
{
chip::FabricId FabricId;
uint16_t VendorId;
uint8_t * Label;
chip::NodeId NodeId;
} EmberAfFabricDescriptor;

// Struct for GpPairingConfigurationGroupList
typedef struct _GpPairingConfigurationGroupList
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,13 @@

// Server attributes

// Attribute ids for cluster: Operational Credentials

// Client attributes

// Server attributes
#define ZCL_FABRICS_ATTRIBUTE_ID (0x0001)

// Attribute ids for cluster: Shade Configuration

// Client attributes
Expand Down
Loading